Hjälp med interrupt i mikroc.

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
dancar
EF Sponsor
Inlägg: 365
Blev medlem: 19 januari 2005, 00:25:09
Ort: Malmö

Hjälp med interrupt i mikroc.

Inlägg av dancar »

Hej

Jag har börjat experimentera i mikroc. Jag vet att många förespråkar asm för noviser som mig. Men jag var otålig. Jag har blinkat lite ledar och lekt med lcd-display och det har gått fint.

Nu har jag dock stött på problem. Jag skulle vilja göra en enkel klocka. För att åstadkomma det vill jag använda timern och interrupt.

Min uppkoppling verkar ok tycker jag. Processorn kör och jag får ut text på displayen. Dock får jag inga interrupts på timern.

Koden är som följer:

/*
* Project name:
LCDClock
* Copyright:
(c) Daniel Carlsson, 2006.
* Description:
Simple program to learn how to write to 16x2 character display and how to
implement a hardware timer with interrupt.
* Test configuration:
MCU: PIC16F628A
Oscillator: XT, 04.0000 MHz
Ext. Modules: -
SW: mikroC v5.0
* Wiring :
D7 - port.7
D6 - port.6
D5 - port.5
D4 - port.4
E - port.3
RS - port.2
*/

short unsigned hh = 0;
short unsigned mi = 0;
short unsigned ss = 0;

/*
Writes the time in the HH:MM:SS format to an initiated LCD. Row and col
values dertermins the placement on the display.
*/
void WriteTimeToLCD(short unsigned row, short unsigned col,short unsigned hh,
short unsigned mi, short unsigned ss)
{
char tmp[4];

// Write hours to display
ShortToStr(hh, tmp);
if (hh < 10)
tmp[2] = '0';

Lcd_Chr(row, col, tmp[2]);
Lcd_Chr(row, col + 1, tmp[3]);
Lcd_Chr(row, col + 2, ':');

//Write minutes to display
ShortToStr(mi, tmp);
if (mi < 10)
tmp[2] = '0';

Lcd_Chr(row, col + 3, tmp[2]);
Lcd_Chr(row, col + 4, tmp[3]);
Lcd_Chr(row, col + 5, ':');

//Write seconds to display
ShortToStr(ss, tmp);
if (ss < 10)
tmp[2] = '0';

Lcd_Chr(row, col + 6, tmp[2]);
Lcd_Chr(row, col + 7, tmp[3]);
}

//Handels interrupt from TMR0
void interrupt(void) {
TMR0 = 96;
ss ++;
if (ss = 60)
ss = 0;
}

void main() {

OPTION_REG = 0x84; // Assign prescaler to TMR0
TMR0 = 96;
INTCON.T0IE = 1; // Enable TMRO interrupt

TRISB = 0; // PORTB is output
Delay_ms(1000);
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Cmd(Lcd_CLEAR); // Clear display

while (1) {
WriteTimeToLCD(1, 5, hh, mi, ss);
}
}

Det som händer då man kör koden är att man får en utskrift 00:00:00 på displayen vilket är korrekt. Dock hade jag förväntat mig att siffrorna för sekund skulle ändras. Intervallet för interrupt är inte en sekund det är jag medveten om men problemet är att jag får ingen interrupt alls.

Tar tacksamt emot en hjälpande hand.

/Daniel
Johan_46
EF Sponsor
Inlägg: 32
Blev medlem: 1 april 2006, 13:20:53
Ort: Upplands Väsby

Inlägg av Johan_46 »

Du måste även sätta INTCON.T0IF till 0 ( Timer0 interrupt flagga) , INTCON.PEIE till 1 och INTCON.GIE till 1.När Timer0 slår runt sätts flagga INTCON.T0IF och i interruptrutinen sätter du den till 0.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Det låter som om du inte alls har läst kap 14.5 sid 107 ("Interrupts") i databladet !?
Gör du det så är det nästan omöjligt att inte se felet.

Johan_46's är *DELVIS* rätt. Vad som är fel framgår av databladet fig 14-14.
Det är inget som inte får det att fungera, men det är onödigt o detta fall.

Personligen tycker jag det är bättre att tala om var svaret står, än att ge
svaret självt, det kan bli en björntjänst om man har otur. Det finns en liten
risk att man skiver av fel och det kan förvirra mer än det hjälper :-)
dancar
EF Sponsor
Inlägg: 365
Blev medlem: 19 januari 2005, 00:25:09
Ort: Malmö

Inlägg av dancar »

Slimmade koden lite.

//Handels interrupt from TMR0
void interrupt(void) {

INTCON.T0IE = 0; // Disable TMRO interrupt
INTCON.T0IF = 0; //Timer0 Interrupt flag

PORTB.F1 = 1;
Delay_ms(1000);
PORTB.F1 = 0;
Delay_ms(1000);

INTCON.T0IE = 1; // Enable TMRO interrupt
}

void main() {
TRISB = 0; // PORTB is output
OPTION_REG = 0x84; // Assign prescaler to TMR0
TMR0 = 1;
INTCON.GIE = 1;
INTCON.T0IE = 1; // Enable TMRO interrupt
INTCON.T0IF = 0; //Timer0 Interrupt flag
}

Läste sid 107 i databladet som sodjan ordinerade och fick igång timern. Dock fick jag något annat att fundera på.... Så som jag tolkade databladet så förstod jag det som att INTCON.GIE = 1 sätter på samtliga interrupts. Sen får man definiera vilka interrupt man vill "lyssna på" i detta fall timer0 dvs jag sätter INTCON.T0IE = 1. Är jag helt ute och cyklar eller är detta korrekt uppfattat?

Tack för de snabba informativa svaren. Gillar sodjans pedagogik att visa var man skall leta för att få hjälp istället för att levrera svaret direkt.

/daniel
Johan_46
EF Sponsor
Inlägg: 32
Blev medlem: 1 april 2006, 13:20:53
Ort: Upplands Väsby

Inlägg av Johan_46 »

Om du titta i databladet så heter vissa parametrar tex. xxIE som aktiverar valt interrupt. Vid utlöst interrupt sätts motsvarande flagga XxxIF som talar om vilket interrupt som har utlösts.

Använder själv MikroPascal.
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

xxIE = xx Interrupt Enable = xx Tillåt Interrupt
xxIF = xx Interrupt Flag = xx Interrupt Flagga (har händ alltså)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Jag ser att du har upptäckt att det var PEIE som var "överflödig", bra.
Annars ser jag inget fel i din logik.
OBS bara att PEIE behövs för *vissa* interrupt-källor, men fig 14-14
visar tydligt vilka det är...
Användarvisningsbild
BultaIBo
Inlägg: 32
Blev medlem: 21 mars 2006, 18:08:03
Ort: Hammarö

Inlägg av BultaIBo »

Har inte med frågan att göra egentligen, men blev lite tveksam om den "slimmade" koden där delay på totalt 2000ms används i funktionen som hanterar interrup. Är det bra?

Bör man inte hålla interruptfunktioner "tidskorta"?

Eller har jag missupfattat det hela?
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

BultaIBo: Att lägga in delay i ISR är otroligt korkad rakt av. Det kan förvisso finnas tillfällen där det kan vara befogad men det är ytterst sällsynt att det är det.

Så du har fattat rätt!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Vid de allra flesta normala avbott kan det som skall "göras" delas
upp i två delar, en del som måste göras "nu" och som inte får/bör
avbrytas av annat. Detta görs lämpligen i själva ISR'en. T.ex läsa
av ett mottgaget tecken från USART'en eller läsa av ett värde från
ADCn och spara undan dessa. Även vissa beräkningar där man vill
undvika "race conditions" melan olika ruiner kan göras i ISR'en.

Den andra delen som inte är så tidskritisk (t.ex tolkninen av det
mottagana tecknet eller utvärderingen av ADC värdet) kan sedan
göras från main-koden.

D.v,s att ISR'en gör det den *måste* göra (men inte mer!) och sätter
sedan en flagga (en bit i ett register). Main-rutinen ser sedan ut
ungefär så gär :

main-loop
bit-test usart_receive_flagga
om "1", call usart_handler
bit-test adc_value_ready_flagga
om "1", call adc_handler
goto main-loop

D.v.s att rutinen för tolkning av USART tecknet kan avbrytas
av att ADC går klart, och tvärtom. Inga låsningar.

En annan tumregel är att ingen ISR rutin skall vara längre
än den längsta acceptabla fördröjningen för något av de *andra*
avbrotten.

Om man t.ex kör USART i 57 Kbaud baud, så kan det komma tecken med
(ca) 150 us intervall. Alltså får ingen *annan* ISR vara längre än
ca 150 us, eftersom det då finns risk för "over-run" i USART'en.
Lägg på lämpliga säkerhetsmariginaler o.s.v...

Nu är 150 us än ganska lång ISR i alla fall, men du förstår principen.
Det är ovanligt att en ISR *måste* vara längre än ett par 10-tal us.
dancar
EF Sponsor
Inlägg: 365
Blev medlem: 19 januari 2005, 00:25:09
Ort: Malmö

Inlägg av dancar »

Angående delayer i interrupt. De delayerna som var med i den bantade kodsnutten var endast i debugsyfte. Jag ville se om jag kom till interupt funktionen eller ej.

Tackar för all hjälp jag fått tror jag börjar få klarhet i hur det fungerar.

/Daniel
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

I krigstillstånd (= debuggning) finns inga regler... :D :D
Skriv svar