Sida 1 av 1

PIC18F1320: Problem med PORTA

Postat: 19 juli 2006, 16:26:36
av JimmyAndersson
MikroBasic. PIC18F1320. Intern oscillator. (8MHz).
På PORTA.0 och PORTA.1 sitter två lysdioder. (En på varje pinne.) Dessa är kopplade med varsitt 330-ohms motstånd. Från MCLR går ett 10k motstånd till +5V. Det sitter avstörnings-kondingar över PIC'ens matningspänning. Resten av labbplattan är tom.



Jag stötte på något konstigt när jag debuggade en kod. Snabb problem-beskrivning:

Detta blinkar med båda lysdioderna samtidigt:

while true
PORTA = $FF
delay_ms(500)
PORTA = $00
delay_ms(500)
wend

-------

Om jag däremot gör såhär:

while true
PORTA.0 = 1
PORTA.1 = 1
delay_ms(500)
PORTA.0 = 0
PORTA.1 = 0
delay_ms(500)
wend

Så blinkar bara lysdioden på PORTA.1 (Den andra är släckt hela tiden.)
Byter jag plats på PORT-raderna så det blir såhär:

while true
PORTA.1 = 1
PORTA.0 = 1
delay_ms(500)
PORTA.1 = 0
PORTA.0 = 0
delay_ms(500)
wend

så blinkar bara lysdioden på PORTA.0 (Den andra är släckt hela tiden.)


Varför?? Det går förstås att komma runt, men det vore bra att veta varför det blir såhär.



Bifogar hela test-koden ifall någon vill kika:

Kod: Markera allt

'Använder interna oscillatorn.
'INTI02_OSC_1H är satt i Project -> Edit -> Device Flags.

'INTERN OSCILATOR SÄTTS HÄR!
OSCCON.IDLEN = 0 ' Run-mode enabled; CPU-core is clocked in Run-modes, but not in Sleep-mode.
OSCCON.IRCF2 = 1 ' 8MHz! Internal Oscillator Frequency. (Source drives clock directly.)
OSCCON.IRCF1 = 1 ' 8MHz! Internal Oscillator Frequency. (Source drives clock directly.)
OSCCON.IRCF0 = 1 ' 8MHz! Internal Oscillator Frequency. (Source drives clock directly.)
OSCCON.SCS1 = 1 ' Internal oscillator.

'Utgångar och rensar PORT A
TRISA = 0
PORTA = 0

'PORT A2 - A4 = Digitala in.
ADCON1 = %00001100

'Stäng av komparator..
CCP1CON = $0

'Stäng av interrupt..
INTCON = $0
PIE1 = $0
PIE2 = $0

'Low-voltage-detect = OFF  -Bara för att vara säker. :-)
LVDCON.LVDEN = 0

main:

while true
  PORTA.0 = 1
  PORTA.1 = 1
  delay_ms(500)

  PORTA.0 = 0
  PORTA.1 = 0
  delay_ms(500)
wend

end.

Postat: 19 juli 2006, 16:45:31
av cyr
Det var ett tag sen jag pysslade med PIC senast, men jag har för mig att bit-operationer på portarna är "read-modify-write", och att ingångar som är satta som analoga in alltid läses som 0.

Dvs när du kör PORTA.1 = 1 så läses hela PORTA in, bit 0 läses som 0 (fast du nyss satt den till 1), bit 1 sätts till 1 och sen skrivs resultatet tillbaka till porten (så att bit 0 skrivs som 0).

Om du ser till att PORTA bit 0,1 är digitala ingångar så funkar det nog bättre.

Postat: 19 juli 2006, 17:03:47
av sodjan
Lägg en kort (räcker med en eller ett par NOP, om du kan det)
delay mellen de två "=1" och "=0" oerationerns. Det *ser ut*
som RMW problemet.

Eller, byt PORTA.x => LATA.x

Postat: 19 juli 2006, 17:38:45
av JimmyAndersson
MikroBasic klarar NOP, men eftersom det behövdes ganska många (fler än 3-4st) så provade jag med LAT istället, och det fungerade utmärkt.

Tack för hjälpen! :)

Postat: 19 juli 2006, 18:24:27
av sodjan
> MikroBasic klarar NOP, men eftersom det behövdes ganska många (fler än 3-4st)

Lite märkligt att det behövdes så pass många NOP's. Har du något annat
på samma pinnar förrutom LED'arna ? Eller är det långa ledningar ?
Breadboard ?

> så provade jag med LAT istället, och det fungerade utmärkt.

Och jag hoppas att du har listat ut *varför*... :-)

Postat: 19 juli 2006, 19:17:28
av JimmyAndersson
Jag tror att jag förstått. :)

Svaret på läxan:
(Använder PORTA.0 och PORTA.1 som exempel.)

När man skriver till t.ex PORTA.0 så läses först hela porten lästs av, sedan modifieras detta och skrivs till data-latchen (och därefter till PORTA.0). RMW-problemet uppstår när två skrivningar (t.ex till PORTA.0 och PORTA.1) sker för tätt. Så att när man skriver till PORTA.1 och portens (utgångens) innehåll lagrats i data-latchen, så har inte innehållet från PORTA.0-skrivningen inte hunnit nå utgångs-pinnen. Därför syns inte skrivningen till PORTA.0 på utgången. (Den blir helt enkelt "överskriven" igen.) Hoppas det lät begripligt. :)

När man däremot skriver till LAT så läses innehållet från data-latchen, istället för att läsas från i/o-pinnen.

(Hoppas på bra betyg) :)


"Lite märkligt att det behövdes så pass många NOP's. Har du något annat på samma pinnar förrutom LED'arna ? Eller är det långa ledningar ?
Breadboard ?"


Inget annat på samma pinnar. Korta sladdar, så det ser inte ut såhär alltså. :D
Däremot sitter kretsen (och lysdioderna) mycket riktigt på ett breadboard.

När vi ändå är inne på breadboard:
Du råkar inte ha några till salu? :)

Postat: 19 juli 2006, 19:25:41
av cyr
När man använder PORTA så läses det direkt från själva pinnen, och när man använder LATA så läser man bara värdet som man tidigare skrivit till utgången.

Fast jag har själv aldrig märkt att värdet inte "hunnit" ut på en cykel. Det beror förstås på lasten på pinnen och andra saker i "omvärlden".

Postat: 19 juli 2006, 19:35:23
av sodjan
Japp, stämmer.
Det stämmer också som cyr säger att det är inte så där jättevanligt
att man "ser" fenomenet. Det beror på två faktorer, vilken kapacitans
som pinner "ser" och vilket hastighet man kör processorn i.

> När vi ändå är inne på breadboard:
> Du råkar inte ha några till salu?

De fabriksnya jag hade är slut.
Jag har ett parti beg, 50:- inkl frakt och allt.
Är ganska skapliga...

/Janne.

Postat: 19 juli 2006, 23:14:24
av JimmyAndersson
"Det beror på två faktorer, vilken kapacitans som pinner "ser" och vilket hastighet man kör processorn i."

Mycket bra att veta.


Breadboarden/labbplattorna är intressanta. Jag har renoverat sådana tidigare. :D :oops:
Hm, jag skickar ett PM. :)

Postat: 19 juli 2006, 23:36:48
av sodjan
Igentligen är det som att "driva" vilken RC-länk som helst.

PIC pinnen kan inte driva oändligt med ström, alltså har den en
ekvivalent resistans på kanske några 10-tal ohm. Om man sedan
har en kapacitiv last (kan räcka med kontaktbanorna i en labbplatta
vid höga hastigheter) så har man en RC länk.

Varje intruktionscycel (Tcy) består av 4 faser. Skrivningen sker i sista
fasen och läsningen sker i första. Så om man har *två* BCF/BSF (eller
liknande) direkt efter varandra, så har inte pinnen en hel Tcy "på sig"
innan nästa läsning sker, utan snarare Tcy/4, eller samma som
oscillator frekvensen. I ditt fall med 8 Mhz, alltså 0.125 us. Om man lägger
till *en* NOP så har man plötstligt *en hel* Tcy ytterligare på sig, eller
(vid 8 Mhz) ca 0.125 + 0.5 = 0.625 us, fem gånger mer än innan.
Så en enda NOP kan göra stor skillnad och man tänker kanse inte på
att det gör så stor skillnad som 5 gånger...

Hur som helst, på PIC18 är lösningen oftast att köra med LATx registren.
Detta är en av de stora fördelarna med PIC18. PIC16 har i och för sig
samma *interna* arkitektur med ett "latch" register, men det är inte
"mappat" i minnesmappen bland övriga SFR's, så man kan inte använda
dete direkt i sin kod...

Och där kom PM'et när jag tryckte "Förhandsgranska"... :-)
Då kollar vi det istället......

Postat: 20 juli 2006, 00:08:45
av JimmyAndersson
Intressant! Man lär sig något nytt hela tiden. :)

Jahopp, nu har man spenderat lite pengar utan att resa sig från stolen.. :)