PIC16F873 vs. SLEEP MODE og wake up

Hej NG.

Jeg sidder med et projekt, hvor jeg bruger en Pic16F873 til at måle forbrugsmængden, der løber igennem et vandsystem. For hver liter der løber igennem, summerer den op i et 2 Line 16 Segment LCD-display. Ved start på

0000h indledes med bla.bla bla bla osv opstartstekst !! Kredsløbet, hvori Pic-processoren sidder er, er spændingsovervåget af IC2, jeg ikke husker navnet på. Når forsyningsspændingen forsvinder, detekterer RC1 en HIGH fra IC2'ens output, som fortæller PIC'en at den skal gå i SLEEP MODE for at mindske strømforbruget.

Når supply-forsyningen forsvinder, har jeg en 1F / 6,3V-kondensator siddende, som agerer battery, for at huske de data, som er lagret i PIC'en.

Jeg har fået den til at gå i SLEEP Mode, men når jeg sender en lav på MCLR, viser den kortvarig opstartsteksten i mit display, hvorefter den ej fortsætter med at måle forbrugsmængden. JEg har målt direkte på krystallet, og den starter fint op ved MCLR, hvor efter den forsvinder, når den når til programstart igen. Når jeg så sluker strømforsyningen og tænder igen, starter programmet fint op igen.

Jeg undrede mig over, at jeg måtte bruge ASM-commandoer for overhovedet at kuynne lave et SLEEP-forløb - Er det normalt, at man skal blande ASM med C++ ??

Hvordan sætter portene til at bruge mindst mulig strøm ??

Hvordan laver jeg et korrekt SLEEP - Wake UP forløb ??

Hvordan gemmes DATA'er i EEPROM'en ??

Jeg skal nok Copy / paste mit program her i forummet imorn, men dette indlæg bare for at give en fornemmesle af prblemet jeg sidder med.

mvh Kenneth Huus

Reply to
Kenneth Huus
Loading thread data ...

En kort lav puls på MCLR burde starte PIC'en op igen. Hvad sker der hvis du giver en MCLR puls mens dit program kører normalt (altså ikke når den er i sleep mode)? Det er faktisk muligt at se forskel på Power On Reset (POR) og en MCLR during sleep. Det kan ses på bittene POR, BOR, TO og PD. Se databladet her. Men hvis din kode ikke kigger på disse bit, burde PIC'en starte normalt.

Måske kan det hjælpe hvis du har følgende allerførst i din kode: clrf PCLATH

Desuden er det godt at nulstille watchdog'en og lige deaktivere interrupts: clrwdt clrf INTCON

Når så du igen har nulstillet dine timere, kan du enable interrupts igen. Noget andet som kan få mystisk konsekvenser er hvis du har en return eller retfie stående som tilfældigvis køres. Det kan måske resultere i, at din sleep kommando eksekveres igen. Hvis du har et debug værktøj (såsom ICD2), så prøv at sætte et break-point før din sleep kommando.

Det er helt normalt.

Det er efter min mening bedst at sætte porte til udgange, da de så ikke kan opfange støj (som resulterer i at portene skifter state, og bruger strøm).

Det burde ikke være noget problem..

Kig i databladet. Du skal følge en ganske bestemt sekvens, hvor du gør nogle ting i den rigtige rækkefølge. Det er en sikring mod tilfældig skrivning. Jeg plejer desuden af have en parameter, som skal have en bestemt (magisk) værdi før skrivningen kan eksekveres.

Mvh Thomas Jørgensen

Reply to
Thomas Jørgensen

Når jeg laver en MCLR under programafvikling, starter den programmet almindelig vis. Det er kun, når PIC'en går i Sleep, at opstarten er i ged. Jeg har ingen kode på POR, BOR, TO og PD.

Hvad er clrf for en kommando ??

Dette var også mit umiddelbare næste bud, men mente ik, der var nødvendigt.

Jeg bruger kun Timer0. Jeg har ingen return eller retfie (hvad det nu end er). Hvor kan man hente et debug værktøj henne ??

Ja, jeg ved godt at jeg skal sætte dem til output - Men hvilken state Hi, Lo Three State ??

Kan du gi et eksempel ??

mvh Kenneth

Reply to
Kenneth Huus

Okay.

Hvad er clrf for en kommando ??

clrf er "clear file". Den lægger blot 0x00 ind i registret.

Prøv det alligevel :)

Jeg har købt en uoriginal ICD2 til omkring 700 kroner. Den tilsluttes USB, og så har man direkte adgang til registre og kan single-steppe og sætte break-points ind i koden. Det er nok mest velegnet til assembler programmering.

Three state er jo indgang.. Du skal sætte dem til output. Om de er Hi eller Lo er ifølge App.note AN606 ikke så vigtigt.

Ja, sådan gør jeg på 16F874.. det er assembler, og mere eller mindre kopieret fra databladet :)

ReadEEbyte ;Læser fra adresse i eepromaddr register movf eepromaddr, w bsf STATUS, RP1 ;Bank 2 bcf STATUS, RP0 movwf EEADR clrf EEADRH bsf STATUS, RP0 ;RAM-BANK3 movlw b'00000000' ;Sæt op til Data memory movwf EECON1 bsf EECON1, RD bcf STATUS, RP0 ;RAM-BANK2 bcf STATUS, RP0 ;Bank2 igen movf EEDATA, w bcf STATUS, RP1 movwf eepromvalue ;Her ligger den læste byte return

Skrivning er mere tricky...

WriteEEbyte ;Skriver til den valgte adresse (i eepromaddr) movf eepromvalue, w bsf STATUS, RP1 ;Bank 2 bcf STATUS, RP0 ; movwf EEDATA

bcf STATUS, RP1 movf eepromaddr, w bsf STATUS, RP1 ;Bank 2 movwf EEADR clrf EEADRH bsf STATUS, RP0 ;Bank3 movlw b'00000100' ;Sæt op til Data memory movwf EECON1

waiteeread btfsc EECON1, WR goto waiteeread ;Make sure EEPR is not writing. eeprready bcf INTCON, GIE bsf EECON1, WREN movlw 55h movwf EECON2 movlw 0AAh movwf EECON2 bsf EECON1, WR bcf EECON1, WREN bsf INTCON, GIE

bcf STATUS, RP0 ;Back in back0 bcf STATUS, RP1 return ;

Mvh Thomas

Reply to
Thomas Jørgensen

Den Sun, 12 Dec 2004 22:23:47 +0100, Thomas Jørgensen skrev:

Hvis man hellere vil bygge selv så er opskriften her:

formatting link

Godtnok kun med serielport, men prisen er ok.

--
Jens   OZ2JP   callto://jensep

There are thinkers and there are doers. I think I need a doer.
Reply to
Jens Petersen

Tak for svarene - Jeg melder tilbage imorn, når jeg har forsøgt med de nye tiltag. Desuden får I lige en udskrift af min source-fil !!

Nat nat herfra

Reply to
Kenneth Huus

Her er selve hovedprogrammet så!!

------------------------------------------------------------------- void main(void) // Hovedprogram { TRISA = 16; // Port A til output an input ("1" input og "0" output) TRISB = 0; // Port B til output TRISC = 0; // Port C til output ADCON1 = 6; // Set Port B til Digital

PORTB = 56; // 8 Bit interface PORTA = 2; // LCDdelay(); // Kalder LCDdelayroutine PORTA = 0; //

PORTB = 12; // Display on, Cursor off, Blink off PORTA = 2; // LCDdelay(); // Kalder LCDdelayroutine PORTA = 0; //

PORTB = 1; // Clear display PORTA = 2; // LCDdelay(); // Kalder LCDdelayroutine PORTA = 0; //

bitsum=0; // Reset bitsum TMR0=0; // Reset 8 bit counter 0 start=0; // Reset start

flag='a'; // Flag sættes til a - Viser startoptekst init_disp(); // Kalder init_disp for at tjekke hvilket flag, der er sat DELAY(); // Lav et delay, så vi kan se udlæsningen på displayet flag='b'; // Sæt flag b, så displayet viser forbrugsudlæsning

do{ PORTB = 2; // Cursor at home PORTA = 2; // PORTA = 0; //

input(); // Læs inputsignalet fra flowmåleren

level(); // Kalder level-routinen til LED-udvisning

reset(); // Kalder reset-routinen fra Extern reset

init_disp(); // Kalder initialisering af display

init_led(); // Kalder initialisering af LED-status

if (RC2==1) { // Programmet skal her gemme double-værdien i EEPROM'en, for at programmet // ved næste MCLR fortsætter med det forbrug programmet er kommet frem // til ved SLEEP !!

sleep(); }

} while(1); // Kør sløjfen igen og igen ......osv }

-------------------------------------------------------------------

Min SLEEP-routine ser således ud:

------------------------------------------------------------------- void sleep(void) // SLEEP-routine { #asm sleep nop nop #endasm }

-------------------------------------------------------------------

Håber der er nogen der kan se hvad der måske mangler !!

mvh Kenneth Huus

Reply to
Kenneth Huus

Efter lidt nørglen rundt, har jeg med lidt mindre småjusteringer fundet en løsning. For at nævne et par ting som gjorde udslaget, så kan jeg nævne, at watchdog'en skulle resettes, return from interupt skulle med i sløjfen, general interupt enable skulle resettes ligesom det mest væsentlige = Indgangen hvor mit signal til sleep kommer på, skulle også resettes under opstart. Ellers aner den jo ikke hvad værdi den har og om den skal resette, og støjen kunne åbenbart godt få den til at gå i SLEEP mode.

Det eneste jeg stadig ikke helt kan greje, er hvordan man skriver en doubles-værdi til EEPROM'en !! Jeg synes bestemt ikke de Assamblerkoder til PIC16f873 ligner de samme, som jeg brugte på min AtMEL89c2056. På en eller anden måde skal stackpointeren vel have at vide, at nu skal lagringsprocessen skrive eller læse i EEPROM'en - Kan jeg sgu ikke umiddelbart greje.

Det færdige stykke kommer her !!

/*----------------------------------SLEEP-routine---------------------------

------*/ /* SLEEP-routinen mindsker strømforbruget på processoren, når den ext. forsyning */ /* mangler. */ /*--------------------------------------------------------------------------

------*/ void sleep(void) // SLEEP-routine { #asm sleep nop nop #endasm }

/*------------------------------Assambler-kommandoer------------------------

------*/ /* Assambler kommandoen skal slette diverse flags under opstart, for at sikre */ /* korrekt opstart af Wake up. */ /*--------------------------------------------------------------------------

------*/ void asambl(void) // asambler-routine { #asm clrwdt retfie #endasm }

/*----------------------------------Hovedprogram----------------------------

------*/ void main(void) // Hovedprogram { TRISA = 16; // Port A til output an input ("1" input og "0" output) TRISB = 0; // Port B til output TRISC = 0; // Port C til output ADCON1 = 6; // Set Port B til Digital

PORTB = 56; // 8 Bit interface PORTA = 2; // LCDdelay(); // Kalder LCDdelayroutine PORTA = 0; //

PORTB = 12; // Display on, Cursor off, Blink off PORTA = 2; // LCDdelay(); // Kalder LCDdelayroutine PORTA = 0; //

PORTB = 1; // Clear display PORTA = 2; // LCDdelay(); // Kalder LCDdelayroutine PORTA = 0; //

RC2=0; // GIE=0; // bitsum=0; // Reset bitsum TMR0=0; // Reset 8 bit counter 0 start=0; // Reset start

asambl(); //

flag='a'; // Flag sættes til a - Viser startoptekst init_disp(); // Kalder init_disp for at tjekke hvilket flag, der er sat DELAY(); // Lav et delay, så vi kan se udlæsningen på displayet flag='b'; // Sæt flag b, så displayet viser forbrugsudlæsning

do{ PORTB = 2; // Cursor at home PORTA = 2; // PORTA = 0; //

input(); // Læs inputsignalet fra flowmåleren

level(); // Kalder level-routinen til LED-udvisning

reset(); // Kalder reset-routinen fra Extern reset

init_disp(); // Kalder initialisering af display

init_led(); // Kalder initialisering af LED-status

if (RC2==1) // { // Programmet skal her gemme double-værdien i EEPROM'en, for at programmet // ved næste MCLR fortsætter med det forbrug programmet er kommet frem // til ved SLEEP !!

sleep(); // }

} while(1); // Kør sløjfen igen og igen ......osv }

Reply to
Kenneth Huus

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.