Hjälp att komma över tröskeln till PIC assembler [LÖST]

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
SeniorLemuren
Inlägg: 8447
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Hjälp att komma över tröskeln till PIC assembler [LÖST]

Inlägg av SeniorLemuren »

Jaha, då var det dags att ta sig an PIC för första gången. Jag har visserligen programmerat assembler förr. Men 35 år sedan i Z80 och ingenting sen dess sätter sina spår, eller rättare sagt, spåren har sopats undan. Det är ju och för sig, lite som att cykla, så någonstans därinne finns det väl några avtryck.

I alla fall. Jag har kopplat upp en PIC16F84A med 2 st dioder på utgångarna RA1 och RA2. På RA3 har jag kopplat ena fasen från en optisk resolver som ger 400 pulser per varv. En kristall på 6 Mhz med vidhängande kondingar hittade på en gammal skrivare fick bli oscillator. Driver både resolver och µC gemensamt med 5 V från ett gammalt nätaggregat från en skrotad PC . Övriga pinnar hänger löst.

Att det blev en resolver (optisk givare med 2 fasförskjutna utgångar) som input beror på att den ska ingå i mitt styrsystem till rodermaskineriet på båten, tids nog.

Ja, jag vet. 16F84 är en antikvitet och det finns MYYYCKET bättre och billigare alternativ. Men jag fick ett ryck att komma igång snabbt, hade ett par sådana liggande från något skrotat stuff. Jag fick ett par modernare µC av en hygglig person här på forumet som jag senare ska ta mig an, men dom passar inte i min Willem programmerare utan en adapter och den har jag inte tillverkat ännu. En annan fördel med 16F84 är att databladet är ganska tunt och det är ingen nackdel så här i börja vill jag tro.

Nu till programmeringen. Jag har först gjort ett pytteprogram för att se att upplägget funkar. När jag vrider på resolvern sakta så vill jag att dioderna ska blinka omväxlande i samma takt som insignalen växlar. Voila! Det funkar utan problem.

Ja vet att ni som kan detta undrar varför jag gör det hela med sampling i stället för att använda avbrottshanteringen. Min orsak är att jag vill ta det där med avbrottshantering lite senare, när jag blivit varmare i kläderna. Kanske hade varit lättare att lösa med avbrott, men nu får jag tillfälle att nöta in alla kommandon och använda debuggern ganska intensivt. Det är med avbrott jag tänker lösa det hela i slutändan.

Nu när jag vet att det funkar rent elektriskt så har jag ökat på med att försöka få till det så att en diod tänds och förblir tänd i 255 pulser för att sedan släckas och förbli släckt i 255 pulser. I verkligheten ska det vara tvärs om på den skarpa versionen, en puls in ska ge ett antal fler pulser ut, men jag testar så här för i det andra fallet blir det svårt att vrida resolvern så sakta att pulserna syns.

Problemet är att detta program funkar inte alls som jag tänkt. Det fungerar i debuggern precs som jag vill, men när jag provar i skarpt läge så händer följande:

Trots att jag överhuvudtaget inte manipulerar RA2 (tro jag) så tänds den dioden ibland direkt vid spänningspåslag. Ibland tänds RA1 och RA2 unisont och ibland bara RA1. I det läget kan jag snurra på resolvern hur mycket som helst, inget händer. I vissa enstaka fall när ingen diod tänds vid spänningspåslag kan jag tända Ra1 om jag snurra på resolvern uppskattningsvis 255 pulser (precis som tänkt) men den släcks därefter aldrig. Ibland kan båda dioderna vara släckta och inget reagerar på resolverpulserna.

När jag kör i debuggern så togglar jag RA0 med stimulus som får agera resolver och det funkar perfekt. Laddar jag in det första programmet som växelvis blinkar så funkar allt normalt igen.

Programmet jag totat ihop kan med all säkerhet göras oändligt mycket smartare med mindre kommandon, men som sagt det är bra med mycket kommandon för att nöta in dom snabbt. Att det inte är särskilt smart programmerat betyder ju inte att det inte ska funka i verkligheten om det funkar i debuggern (tycker jag) Men förmodligen så finns det något kardinalfel i själva tänket. Det är där själva tröskeln ligger. :)

Här kommer det lilla program som funkar:

Kod: Markera allt

		processor	16F84A
		include		p16F84.inc
		__config	_XT_OSC & _WDT_OFF & _PWRTE_ON


;******** set port A0 till input A1 till out******
			bsf		STATUS,5		;Gå till Bank 1
			movlw	01h			;flytta in till arbesregistret
			movwf	TRISA		; set portarna
			bcf		STATUS,5		;Gå tillbaka till Bank 0				
;**********här börjar programmet *****************	
start
			btfsc 	PORTA,0		;kolla om port A1 är noll
			call	ledOn		;om inte, tänd led
			
			btfss 	PORTA,0		;kolla om port A1 är ett
			call	ledOff		;om inte, släck led

			goto	start			;börja om

;*************** subrutiner *******************		

ledOn
			movlw	b'0100'	;TÄND LED2
			movwf	PORTA
			return
ledOff
			movlw	b'0010'	;TÄND LED2
			movwf	PORTA
			return
			
			end
Här kommer det som inte funkar i verkligheten, bara i debuggern.

Kod: Markera allt

	processor	16F84A
		include		p16F84.inc
		__config	_HS_OSC & _WDT_OFF & _PWRTE_ON

;********* konstanter********
COUNT		equ		08h
OLDINP		equ		0Ah
LOCK		equ		0Bh
;******** set port A1 till input resten till out******
			bsf		STATUS,5		;gå till Bank 1
			movlw	01h			;
			movwf	TRISA		;set port A0 till input och A1 till output
			bcf		STATUS,5		;gå tillbaka till Bank 0
			bcf		OLDINP,1		;sätt OLDINP,1 till noll från start reolver=1
			bcf		OLDINP,0		;sätt OLDINP,0 till noll från start resolver=0
			movlw	b'11111111'
			movwf	COUNT			
;**********här börjar programmet *****************	
start
			btfss 	PORTA,0		;resolver =1 ?
			goto	kollaInp0		;resolverslinga 0 
;**********här körs slinga för resolver=1*****************
			bcf	OLDINP,0		;släpp slinga 0 ett varv (den låser sig själv) 			
			btfsc	LOCK,1		;kolla om slingan resolver=1 är låst
			goto	start			;Skip if clear
			bsf		LOCK,0	;lås slinga 0 (nu kör vi bara slingan resolver=1)		
			btfsc	OLDINP,1		;kolla om OLDINP=1 (väntar på en resolvernolla)
			goto	start			;om OLDINP=1, börja om från start 
			bsf		OLDINP,1	;sätt OLDINP till 1
			decfsz	COUNT,1	;minska COUNT med 1		
			goto	start			;om COUNT är större än 1, börja om från början
			call	ledOn		;om COUNT är 0 hoppa till ledOn			
;********** här är slingan för resolver=0**************
kollaInp0
			bcf		OLDINP,1	;släpp slinga 1 ett varv (den låser sig själv) 			
			btfsc	LOCK,0		;kolla om slingan resolver=0 är låst
			goto	start			;Skip if clear		
			bsf		LOCK,1	;lås slinga 1 (nu kör vi bara slingan resolver=0)			
			btfsc	OLDINP,0		;kolla om OLDINP2=0
			goto	start			;om OLDINP=1, börja om från start 
			bsf		OLDINP,0	;sätt OLDINP till 1
			decfsz	COUNT,1	;minska COUNT med 1
			goto	start			;om COUNT är större än 1, börja om från början
			call	ledOff		;om COUNT är 0 hoppa till ledOff
;********** Nästa varv ********************			
			goto	start			;börja om	
;*************** subrutiner *******************	
ledOn			
			movlw	b'0010'		
			movwf	PORTA	;sätt port A1 hög	
			bsf		LOCK,1	;lås slinga resolver=1
			bcf		LOCK,0	;lås upp slinga resolver=0 
			
			return
ledOff
			movlw	b'0000'			
			movwf	PORTA	;sätt port A1 låg
			bcf		LOCK,1	;lås upp slinga resolver=1
			bsf		LOCK,0	;lås slinga resolver=0  		
			return			
			end
Senast redigerad av SeniorLemuren 7 mars 2011, 01:04:05, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av sodjan »

> Trots att jag överhuvudtaget inte manipulerar RA2 (tro jag) så tänds den dioden ibland direkt vid spänningspåslag.

Notera att läget för många register (de flesta) är "undefined" vid spänningspåslag.
Så RA2 kan i princip stå hur som helst innan du i koden säger vad som gäller.

> bsf STATUS,5 ;Gå till Bank 1

Du kan lika gärna direkt börja använda BANKSEL. Istället för att manipularna RP
biten/bitarna direkt så låter man MPASM genererea rätt kommandon.

Kod: Markera allt

;******** set port A0 till input A1 till out******
         banksel   TRISA       ; Gå till den bank där TRISA finns.
         movlw     01h         ; flytta in till arbesregistret
         movwf     TRISA       ; set portpinnarnas riktning (in/ut läge)
         banksel   PORTA       ; Gå tillbaka till naknen med PORTA      
Personligen brukar jag justera koden och kommenterarna så att det blir
jämna kollumner, mycket lättare att lära så. Men det kanske var något
som blev så när du kopierade. Använder man TAB så blir det lätt så...

> btfsc PORTA,0 ;kolla om port A1 är noll

Det stämmer inte mellan koden (som testar RA0) och kommentarern !
Och det finns inget som heter "A1", så jag antar at du menar RA1.

Det är lite ologiskt att ha en subrutin med namn "ledOff" där det står "Tänd LED" som kommentar.

> movlw b'0100' ;TÄND LED2
> movwf PORTA

Är inte PORTA ett 8 bitars register ?
Det är lite förvirrande när du enbart anger 4 bitar, man måste tänka till
vilka bitar som läggs till (på vilken sida så att säga). Ange alltid alla 8
bitarna när du gör så där.

Sen så är det kanske bättre att köra med BSF/BCF vilka enbart påverkar
en enskild bit istället för hela PORTA.

Din andra kod har jag inte kollat eller testkört, men det går alltså i MPSIM ?
Dock så är det inte direkt så lätt att se hur det är tänkt. Några småsaker bara...

> movlw b'11111111'
> movwf COUNT

Sannolikt helt onödigt. Om du inte *måste* ha en korrekt beräkning
även första "varvet". Man du kan lika gärna göra "CLRF COUNT". Första
DECFSZ kommer att räkna ner COUNT till '11111111' i alla fall. Notera att
DECFSZ kollar om det är "noll" *efter* att ha räknat ner registret.

> På RA3 har jag kopplat ena fasen från en optisk resolver...
> btfss PORTA,0 ;resolver =1 ?

Dessa två rader stämmer inte alls överens...
Användarvisningsbild
SeniorLemuren
Inlägg: 8447
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av SeniorLemuren »

Det var många goda råd att ta till sig. När man vill igång så blir det mycket småfel i hastigheten, många kommentarsfel kommer sig ju av att man ändrar i koden och slarvar med kommentarerna, en del andra fel kommer sig av dåliga exempelkoder som man kan hitta i olika dåligt skrivna tutorials.

Resolvern är kopplad till RA0 som ju är satt som inport. Allt funkar rent elektriskt med det första programmet.

Det som förbryllar är att jag kan följa flödet rätt väg i debuggern när jag kör animate och togglar ingången.
För att inte behöva toggla mig igenom alla 255 varven så sätter jag ju ner räknaren till ett tal nära omslag, det andra är ju transportsträcka.

Tanken är att jag tittar på första signalen som kommer från resolvern om den tex är en etta så räknas alla omslag som kommer in. när räknaren blir 0 så anropas rutinen som tänder dioden. Den slinga som räknar ner när dioden ska släckas är låst och öppnas när dioden tänts, samtidigt låser jag slingan som räknar ner för att tända nästa gång.

Detta går naturligtvis säkert att lösa på flera enklare vis, men vad jag är ute efter är ju vad i logiken som gör att det går fel i verkligheten men inte i debuggern. Debuggern snurrar ju inte i 6 Mhz så de var därför jag gjorde det lilla testprogrammet för att testa med först.

Kan det vara så att jag måste låsa all portarna rent elektriskt för att dom stör, men i så fall borde ju inte det lilla programmet funka heller? Jag har en maggropskänsla av att jag missat någon liten oskyldig detalj, kan bara inte komma på vad.

I config har jag provat allla versionerna av oscillator utan skillnad
__config _LP_OSC & _WDT_OFF & _PWRTE_ON
__config _XT_OSC & _WDT_OFF & _PWRTE_ON
__config _HS_OSC & _WDT_OFF & _PWRTE_ON
__config _RC_OSC & _WDT_OFF & _PWRTE_ON
RC funkade som väntat inte alls.
Användarvisningsbild
Icecap
Inlägg: 26658
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av Icecap »

Kan bara hålla med sodjan.

Vill även tillägga lite saker. När man skriver program är det viktigt att ange t.ex. LED i en #define. Orsaken är att med den define blir det enklare att läsa och skriva programmet och kastar man om på något är det bara att ändra #define'n och kompilera om, man ska inte leta upp alla användningar i programmet - och det är bra för det blir alltid fel någonstans!

Så gör såhär:
#define LED_1 PORTA,1
#define LED_2 PORTA,2

Då kan man skriva "bsf LED_1" och LED 1 tänds. Tydligt och enkelt att läsa o skriva.

Flyttas LED_1 till PORTA,3 är det bara att ändra #define'n och kompilera om, ska bara göras ett ställe och inget blir fel. Vid större program är detta mycket viktigt, det är OMÖJLIGT att hålla reda på alla ställen!

Man kan göra detta i flera steg också. Anta att ovanstående #define's redan är inskrivna.
#define FEL_LED LED_1
#define OK_LED LED_2
Nu är detta ett mycket enkelt exempel men man kan i mycket göra en hårdvara-definitionsfil där alla anslutningar är beskrivna och sedan i programmet bara använda de defines som anges. Jag har gjort det i ett stort projekt och det betyder att jag numera kan kompilera SAMMA källkod-filer till hhv. en Fujitsu och en Renesas µC, det enda som skiljer är just hårdvara-definitionsfilen och den väljs automatisk av kompilern beroende på vilken kompiler som används.

Jag har definierat INPUT_1, INPUT_2 osv i dessa definitionsfiler samt interrupthanteringen då just den skiljer en del, men den funktionalitet som körs vid interrupts är skriven i källkoden som är gemensam.

Vissa av INPUT_1 osv omdefinierar jag sedan om det passar mig, en bit byter aktivt läge mellan de 2 olika µC varför jag definierar:
#define XXX !INPUT_1

Utropstecknet betyder NOT i C.

Ingen port eller variabel är känd innan du ställer den till ett känd läge! Ta det som en grundregel! Om du letar lite ser du snabbt att MÅNGA trådar är av typen: "men den står ju i det läger efter reset - men nu då jag ställde den rätt fungerar allt som tänkt... konstigt" och du behöver inte göra detta, inget står per definition rätt innan DU ställer det rätt!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av sodjan »

Ja, det man ska leta efter är saker och ting som skiljer
mellan den simulerade miljön och "verkligheten" så att säga.
Ganska självklart kanske, men i alla fall... :-)

För det första, vet du att programmet/processorn "kör" över
huvudtaget i fall 2 ? Den borde göra det med samma kristall
och samma CONFIG.

Du kan lägga till något som visar att programmet har startat
alls före den intressanta koden. Täna en LED eller något.
Eftersom alla pinnar är ingångar efter reset, och man måste
sätta den som utgång i koden, så betyder en tänd LED att
koden måste ha startat.

> För att inte behöva toggla mig igenom alla 255 varven

Du kan sätta en brytpunkt ("breakpoint") på ett strategiskt ställe
direkt efter där du ska hamna efter transportsträckan. Då kan du
köra "run" framtill brytpunkten.

Du kan också använda "Complex Breakpoints" där man anger t.ex ett
värde på ett register som får körningen att stoppa. T.ex då räknaren
har kommit nära noll. Sedan stegar man manuellt resten av vägen.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av sodjan »

En annan sak...

> processor 16F84A
> include p16F84.inc

Stämmer inte överens. Kanske saknas ett "A" i include filen.
Jag får ett larm på det från MPASM...
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av sodjan »

Jag gjorde en snabb test med MPSIM.
Jag fixade en "stimulus" med två knappar så att jag
kan toggla RA0. Jag kommer alrdig fram till någon av
DECFSZ instruktionerna, den fastnar antingen i början av
resolver=1 eller resolver=0 koden.

Någonting i själva logiken verkar konstigt...
Användarvisningsbild
SeniorLemuren
Inlägg: 8447
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av SeniorLemuren »

Kom just in i båten, har varit ute och sågat/huggit upp en kubikmeter ved så jag kan sätta fyr i braskamminen i kväll medan jag kämpar framför datorn. :humm:

Jag ändrade på sättet att släcka tända med bsf/bcf efter rådet om att sätta på bitnivå. Klart lättare och rättare. :)

Så här har jag testat att köra i stimulus och det funkar perfekt. Jag kör i run-läge och har satt breake på ledOn och ledOff och den växlar exakt som den skall. Har kopierat inställningarna på stimulus file-reg och subrutiner. När programet gör halt vid ledOn och ledOff så kan man se att PortA registret ändrar sig korrekt.

Satte dit ett A efter include p16F84 så det meddelandet försvann. Lade in en rad först efter start i programmet som släcker led 1 och tänder led2. Det funkar. Nu tänds inte led1 alls, led 2 lyser vid start men sedan är det stendött.

Ett annat meddelande som får vid Build all som jag undrar över är följande:


Message[302] N:\PIC-PROJEKT\MYPROJ\BLINKALED.ASM 12 : Register in operand not in bank 0. Ensure that bank bits are correct.

I alla fall, här funkar allt i debuggern perfekt men inte i verkligheten.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av sodjan »

> Message[302]

Det är bara en varning. MPASM ser att du använder ett register som
inte ligger i bank0 och påminner bara om det. Många lägger till
ett dirtektiv för att undertrycka dessa medelanden, du kan bara
strunta i det tillsvidare.

En sak...
Kanske att det är lite väl kort low/high cycle. Jag gjorde i princip
samma sak men körde med 30/30 men jag tyckte ända att det
kanske var lite onödigt fort. Koden hinner inte riktigt igenom innan
ingången byter läge igen. Jag vet inte om det har någon betydelse
men det gjorde det lite svårare att följa i SIM.
Användarvisningsbild
SeniorLemuren
Inlägg: 8447
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av SeniorLemuren »

I skarpt läge kommer ju pulserna från resolvern som ger ut 400 pulser per varv och jag vrider den med fingrarna så den tiden borde ju vad långt utöver vad som behövs vid en klockfrekvens på 6 mHz. :humm:
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av sodjan »

Vad jag menade var att man inte kör så fort så att logiken i koden
i sig inte hinner med i växlingarna.

Aja, mycket gissningar. Eftersom simuleringen ju fungerar så skulle
jag fundera lite på hårdvaran. Har ingången på RA0 t.ex pullup ?
Utgången från encodern sluter väl enbart till jord ? Annars kan
det fungera lite hur som helst...
Användarvisningsbild
SeniorLemuren
Inlägg: 8447
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av SeniorLemuren »

Enkodern ger TTL-nivåer ut. Jag lade in kod för att tända resp. släcka led på port A2 i början på slinga 0 resp. 1 och den blinkar i takt ned resolvern. Detta visar ju att programmet växlar mellan slingorna som det skall. Jag ska nu succesivt flytta dessa call i koden för att försöka se vart det stoppar och varför.

Jag skulle ju kunna göra samma program mycket enklare med toggle,men jag tänker att kan jag inte komma på varför det fungerar i sim och inte i verkligheten så behärskar jag inte vad jag håller på med och det känns inte alls bra. :(

Natten är lång...
bos
Inlägg: 2314
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av bos »

Jag har inte testkört koden i MPSIM och orkar tyvärr inte göra det heller, men mitt RMW-larm skriker vrålhögt när jag läser din kod. Det kanske kan vara värt att kolla upp.

Här kan du läsa mer om RMW: http://www.piclist.com/techref/readmodwrite.htm
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av sodjan »

Hm, funderade lite å det, men dels körs processorn inte så snabbt,
dels bör det inte vara några kapacitiva laster direkt. Men visst,
enkelt att testa. Lägg 2-3 NOP efter varje BCF/BSF mot PORTA.
Användarvisningsbild
Glenn
Inlägg: 36767
Blev medlem: 24 februari 2006, 12:01:56
Ort: Norr om Sthlm
Kontakt:

Re: Hjälp att komma över tröskeln till PIC assembler

Inlägg av Glenn »

Var ju ett tag sen man körde 16F84(/A), men är det inte 4MHz max i "normalversionen" av dom ? sen finns det väl en 20Mhz-version också ?

Kör man en 4Mhz-speccad PIC på 6Mhz kan man säkert få en del lustigheter.

..Fast som sagt, jag minns inte riktigt, däremot vet jag att jag brukade köra på 4Mhz av nån anledning.
Skriv svar