Sida 1 av 2
Räknare går bara till 20
Postat: 24 februari 2010, 01:15:38
av Kalf
Hej. Jag håller på och labba lite med en PIC16F628A och en 4*7segments display. Men jag har lite problem med koden. Tanken med koden är att räkna upp en siffra per ca 0.5s. Detta fungerar bra upp till när displayen visar 0020 då visas det i ca 0.5s för att sedan nollställas till 0000.
Här är koden, visningen fungerar bra, så det är troligtvis fel någonstans i sista delen.
Kod: Markera allt
unsigned short shifter, digit, portd_index;
unsigned int number;
unsigned short portd_array[4];
unsigned short digit1 = 0;
unsigned short digit2 = 0;
unsigned short digit3 = 0;
unsigned short digit4 = 0;
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
} //case end
}//~
void interrupt() {
PORTA = 0; // Turn off all 7seg displays
PORTB = portd_array[portd_index]; // bring appropriate value to PORTB
PORTA = shifter; // turn on appropriate 7seg. display
// move shifter to next digit
shifter <<= 1;
if (shifter > 8u)
shifter = 1;
// increment portd_index
portd_index++ ;
if (portd_index > 3u)
portd_index = 0; // turn on 1st, turn off 2nd 7seg.
TMR0 = 0; // reset TIMER0 value
INTCON = 0x20; // Clear TMR0IF
}
void main() {
while(1)
{
OPTION_REG = 0x80; // Timer0 settings
portd_index = 0;
shifter = 1;
TMR0 = 0;
INTCON = 0xA0; // Enable GIE, TMR0IE
PORTA = 0; // make sure that all segments are off
TRISA = 0; // designate porta pins as output
PORTB = 0; // make sure that nothing is displayed
TRISB = 0; // designate portd pins as output
portd_array[0] = mask(digit1);
portd_array[1] = mask(digit2);
portd_array[2] = mask(digit3);
portd_array[3] = mask(digit4);
digit1++;
delay_ms(500);
if (digit1 > 9)
{
digit1 = 0;
digit2++;
if (digit2 > 9)
{
digit2 = 0;
digit3++;
if (digit3 > 9)
{
digit3 = 0;
digit4++;
if (digit4 > 9)
{
digit4 = 0;
}
}
}
}
}
}
//Kalf
Re: Räknare går bara till 20
Postat: 24 februari 2010, 06:11:11
av bearing
Jag kan inte se något fel i koden som skulle kunna göra att den nollställs efter 0020. Förmodligen betyder det att processorn startas om efter 20.
Tycker att du borde ta bort initeringen ur while-loopen i main. Initieringen borde bara behöva göras en gång, i början av main, innan loopen.
För att se om processorn startas om skulle du kunna göra så att initieringen sätter siffror 9999 på displayen, eller liknande.
Re: Räknare går bara till 20
Postat: 24 februari 2010, 06:41:19
av Micke_s
Har du kollat vakthunden (WDT)?
Re: Räknare går bara till 20
Postat: 24 februari 2010, 06:43:38
av Swech
Rent allmänt om kodningen eftersom jag är kass på C.
Vad returnerar din CASE om siffran inte är inom 0-9 ?
Varje IF utför ju två saker , öka siffra och kontrollera om den är inom 0-9
Kontrollen 0-9 bör man köra på alla siffror kontinuerligt oavsett om man fått föregående siffra att slå runt.
Får du av någon anledning in något annat än 0-9 i de högre så tar det lång tid innan programmet rättar till det.
Swech
Re: Räknare går bara till 20
Postat: 24 februari 2010, 06:48:38
av Micke_s
flytta ut
Kod: Markera allt
OPTION_REG = 0x80; // Timer0 settings
portd_index = 0;
shifter = 1;
TMR0 = 0;
INTCON = 0xA0; // Enable GIE, TMR0IE
PORTA = 0; // make sure that all segments are off
TRISA = 0; // designate porta pins as output
PORTB = 0; // make sure that nothing is displayed
TRISB = 0; // designate portd pins as output
utanför while också...
Sedan hade jag flyttat ut digit++ osv till en egen funktion istället.
Re: Räknare går bara till 20
Postat: 24 februari 2010, 06:50:59
av bearing
Det var alltså ovanstående kod jag kallade "initieringen".
Re: Räknare går bara till 20
Postat: 24 februari 2010, 09:31:15
av Kalf
Hej.
Jag flyttade ut initieringen från while loopen. dessutom la jag till att lysa upp hela displayen i en sekund efter initieringen för att lokalisera problemet. Det som händer nu är att 1: displayen lyser med alla 4*8segment (7+en prick) 2. den räknar upp från 0000 till 0020 som innan. 3. hela displayen lyser upp igen. 4. den räknar om från 0000.
Detta betyder altså att efter 20 så nollställs variablerna och den börjar om från början i main. Den faller altså ur while loopen.
Micke_s: WDT är avstängd.
Swech: Jag fixade så CASE retunerar ett värde även om det ligger utanför 0-9
//Kalf
Kod: Markera allt
unsigned short shifter, digit, portd_index;
unsigned int number;
unsigned short portd_array[4];
unsigned short digit1 = 0;
unsigned short digit2 = 0;
unsigned short digit3 = 0;
unsigned short digit4 = 0;
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
default: return 0xFF;
} //case end
}//~
void interrupt() {
PORTA = 0; // Turn off all 7seg displays
PORTB = portd_array[portd_index]; // bring appropriate value to PORTB
PORTA = shifter; // turn on appropriate 7seg. display
// move shifter to next digit
shifter <<= 1;
if (shifter > 8u)
shifter = 1;
// increment portd_index
portd_index++ ;
if (portd_index > 3u)
portd_index = 0; // turn on 1st, turn off 2nd 7seg.
TMR0 = 0; // reset TIMER0 value
INTCON = 0x20; // Clear TMR0IF
}
void main() {
OPTION_REG = 0x80; // Timer0 settings
portd_index = 0;
shifter = 1;
TMR0 = 0;
INTCON = 0xA0; // Enable GIE, TMR0IE
PORTA = 0; // make sure that all segments are off
TRISA = 0; // designate porta pins as output
PORTB = 0; // make sure that nothing is displayed
TRISB = 0; // designate portd pins as output
portd_array[0] = 0xFF;
portd_array[1] = 0xFF;
portd_array[2] = 0xFF;
portd_array[3] = 0xFF;
delay_ms(1000);
while(1)
{
portd_array[0] = mask(digit1);
portd_array[1] = mask(digit2);
portd_array[2] = mask(digit3);
portd_array[3] = mask(digit4);
digit1++;
delay_ms(500);
if (digit1 > 9)
{
digit1 = 0;
digit2++;
if (digit2 > 9)
{
digit2 = 0;
digit3++;
if (digit3 > 9)
{
digit3 = 0;
digit4++;
if (digit4 > 9)
{
digit4 = 0;
}
}
}
}
}
}
Re: Räknare går bara till 20
Postat: 24 februari 2010, 09:52:21
av bearing
Är 20 tänt hela sin halvsekund, eller dör den snabbt efter att 20 visas?
Det skulle kunna bero på en "kortslutning" med av kombinationen PORTA=2 och PORTD=mask(2)
Jag tror det är dags för dig att visa oss hur allt är kopplat.
Re: Räknare går bara till 20
Postat: 24 februari 2010, 09:53:07
av Glenn
BOR då ? nu minns jag inte om just den picen har BOR iofs, men jag har för mej det.
Har du picen ordentligt avkopplad ? gärna med en mindre (typ 100nF) och en större (1uF ?) konding ?
Re: Räknare går bara till 20
Postat: 24 februari 2010, 10:15:01
av Kalf
Så, tack för hjälpen. Det var BOR som var problemet. Jag stängde det och det fungerar felfritt nu.
//Kalf
Re: Räknare går bara till 20
Postat: 24 februari 2010, 10:23:40
av Glenn
Whee

Re: Räknare går bara till 20
Postat: 24 februari 2010, 11:04:32
av sneaky
Även om det nu fungerar med BOR avstängt så kanske det kan vara en idé att kika på varför den löste ut? Bara en tanke.
Re: Räknare går bara till 20
Postat: 24 februari 2010, 11:19:14
av Glenn
Ja, därav min frågha ang avkoppling, har man bara en mindre konding (eller ingen alls) kan det ju bli just sådär..
Re: Räknare går bara till 20
Postat: 24 februari 2010, 11:57:13
av sodjan
> Så, tack för hjälpen. Det var BOR som var problemet.
*NEJ*, det var det inte !
Problemet var det som fick BOR att "trigga". Om du inte
hittar det så har du fortfarande problemet kvar. Ditt val...
Re: Räknare går bara till 20
Postat: 24 februari 2010, 16:36:25
av Kalf
Sodjan: Det har du helt rätt i, nu när jag tänker efter. Det måste vara något i min koppling då?
saxat från databladet:
...If VDD falls below VBOR for longer than TBOR, the
brown-out situation will reset the chip....
Betyder det att uC'n tappar spänning då eller?
Sedan har det dykt upp ett till problem. Det kan kanske ha med samma sak och göra? Men Jag har kopplat in en tryckknapp som jag hade tänkt att styra uppräkningen med. Men när jag trycker på knappen fortsätter den räkna upp ca 100 gånger. (detta tar betydligt längre tid än vad jag håller knappen intryckt.)
Min misstanke var att det har något med min interrupt och göra. att den får interrupt precis i samband med
digit1++; och när den då åter går så kör den samma sak igen så får den interuppt osv.....
Här är iaf koden:
Kod: Markera allt
void display(void);
void button_check(void);
unsigned short shifter, digit, portd_index;
unsigned int number;
unsigned short portd_array[4];
unsigned short digit1 = 0;
unsigned short digit2 = 0;
unsigned short digit3 = 0;
unsigned short digit4 = 0;
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
default: return 0xFF;
} //case end
}//~
void display(void) {
while(1)
{
portd_array[0] = mask(digit1);
portd_array[1] = mask(digit2);
portd_array[2] = mask(digit3);
portd_array[3] = mask(digit4);
if (button(&PORTA, 7, 100, 1)) digit1++;
if (digit1 > 9)
{
digit1 = 0;
digit2++;
if (digit2 > 9)
{
digit2 = 0;
digit3++;
if (digit3 > 9)
{
digit3 = 0;
digit4++;
if (digit4 > 9)
{
digit4 = 0;
}
}
}
}
}
}
void interrupt() {
PORTA = 0; // Turn off all 7seg displays
PORTB = portd_array[portd_index]; // bring appropriate value to PORTB
PORTA = shifter; // turn on appropriate 7seg. display
// move shifter to next digit
shifter <<= 1;
if (shifter > 8u)
shifter = 1;
// increment portd_index
portd_index++ ;
if (portd_index > 3u)
portd_index = 0; // turn on 1st, turn off 2nd 7seg.
TMR0 = 0; // reset TIMER0 value
INTCON = 0x20; // Clear TMR0IF
}
void main() {
OPTION_REG = 0x80; // Timer0 settings
portd_index = 0;
shifter = 1;
TMR0 = 0;
INTCON = 0xA0; // Enable GIE, TMR0IE
PORTA = 0; // make sure that all segments are off
TRISA = 0b10000000; // designate porta pins as output
PORTB = 0; // make sure that nothing is displayed
TRISB = 0; // designate portd pins as output
portd_array[0] = 0xFF;
portd_array[1] = 0xFF;
portd_array[2] = 0xFF;
portd_array[3] = 0xFF;
delay_ms(1000);
display();
}
//Kalf