Gå til innhold

Atmega164 interrupt problem


Anbefalte innlegg

Innlegget er på engelsk, jeg gidder ikke å skrive om, copy og paste fra et annet forum jeg skrev på.

 

Hello again. I have another obstackle i want to pass.

My code is built in this matter:

 


int index =0; //Counter for the different video modes

/*  PORT C */
PORTC = 0xFF; /*PC0-7 = Input */
DDRC = 0x00;

// check for button press to change state
    if (PINC != 0xFF){

Switch(index)[

    case 0:
    *send different commands on the I2C.
    index++;
    break;

    case 1:
    *send different commands on the I2C.
    index++;
    break;

    case 2:
    *send different commands on the I2C.
    index=0;
    break;

 

I have 4 push buttons connectes as you see in the illustration which is attached.

When i press button 1, I want the code to send commands when the button is pressed. I'm afraid the button will oscillate, which gets the index to suddenly "jump" to the value 3 instead of just jumping one step at a time.

 

My first question is if my code is correct, when I just want this code to work for button 1 like it is connected in the illustration.

 

My second question is, I wish to avoid the button to oscillate. Then my idea is to use interupts. I've tried reading the datasheet how this works. But I'm not quite sure. What do I have to include,how do I enable interupt, and how do I get interupt to work.

 

Hope someone can help me with this problem.

 

-Paul-

 

Kort sagt så er jeg redd for "prelling" på knappen, slik at dette kan få index min til å hoppe flere hakk enn ett hakk om gangen. Dette vil jeg unngå ved å bruke interrupt.

Men hvordan gjøres dette, er ny innenfor AVR familien. Jeg vet jeg skal inkludere interrupt.h filen, men det er omtrent det jeg er sikker på.

post-19689-1176681571_thumb.jpg

Endret av Furyfax
Lenke til kommentar
Videoannonse
Annonse

hmm...

 

står atmega64 på tegninga, men det ser ikke ut til å være en atmega64 synes jeg... atmega64 har nemlig 64 pinner, kretsen i skjema har bare 44 ser det ut til...

 

Videre har du ikke koblet knappene til porter som støtter eksternt interrupt, så interrupt fra knappene vil ikke være mulig. Det du kan gjøre er å bruke en timer og noen variabler som sørger for at det må gå en liten tid mellom hvert knappetrykk. Å bruke eksternt interrupt trenger ikke være nok i seg selv, det kan godt hende du vil trenge en slik timer likevel. kommer litt an på hvor raks interruptrutinen blir.

 

når det gjelder kode (avr-gcc) for interrupt:

 

...
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

...

INTERRUPT(SIG_OVERFLOW0)	//counter0/timer0
{
   //C-kode	
}

SIGNAL(SIG_UART_RECV)
{
   //C-kode
}

 

 

SIG_UART_RECV og SIG_OVERFLOW0 er bare eksempler (fra kode jeg har brukt..), se .h filene for å finne det du vl ha.

 

To alternativer, den ene eksekverer med global interrupt på, den andre med globalt interrupt av i selve avbruddrutinen. Kjekt hvis du skal ha interrupt av høyere prioritet o.l.

Lenke til kommentar
hmm...

 

står atmega64 på tegninga, men det ser ikke ut til å være en atmega64 synes jeg... atmega64 har nemlig 64 pinner, kretsen i skjema har bare  44 ser det ut til...

 

Videre har du ikke koblet knappene til porter som støtter eksternt interrupt, så interrupt fra knappene vil ikke være mulig. Det du kan gjøre er å bruke en timer og noen variabler som sørger for at det må gå en liten tid mellom hvert knappetrykk. Å bruke eksternt interrupt trenger ikke være nok i seg selv, det kan godt hende du vil trenge en slik timer likevel. kommer litt an på hvor raks interruptrutinen blir.

 

når det gjelder kode (avr-gcc) for interrupt:

 

...
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

...

INTERRUPT(SIG_OVERFLOW0)	//counter0/timer0
{
   //C-kode	
}

SIGNAL(SIG_UART_RECV)
{
   //C-kode
}

 

 

SIG_UART_RECV og SIG_OVERFLOW0 er bare eksempler (fra kode jeg har brukt..), se .h filene for å finne det du vl ha.

 

To alternativer, den ene eksekverer med global interrupt på, den andre med globalt interrupt av i selve avbruddrutinen. Kjekt hvis du skal ha interrupt av høyere prioritet o.l.

8394987[/snapback]

 

 

SIGNAL og INTERRUPT er utdatert, i nye versoner skal det benyttes kun ISR(INTERRUPT_VECTOR), for å finne navnet på interrupt vektoren kan man sjekke ioXXX.h fila som ligger under include/avr . Skal man ha på global interrupt kan man bare enable med en gang man går inn i rutinen,

 

Ellers så har en del AVR kretser interrupt på alle pinner eks ATMEGA44/88/168 serien. Men man benytter vel ikke pinn interrupt for her det er vel timer interrupt slik som Dr_VingTor sier som er den riktige løsningen. Sett opp en timer med interrupt ca 50Hz, så sier man at det treng to timerinterrupt med knappen nede for at det skal reagere (selvsagt må man eksprimentere litt her for å få riktig timing å slikt). Man kan også sette inn et delay etter knappen er trykket ned slik at det går en liten stund før nytt trykk godtas (gjøre også med samme timer interrupt).

Lenke til kommentar

(/&%¤¤"()/&==)/&(&¤##

 

*sukk*

 

Takk for svar. Har kanskje gått på en liten blunder. Meininga var å bruke Atmega64.

Men jeg har copy paste fra ett annet prosjekt, dette har ført til at eg kopierte en Atmega164. Dette har ikke altfor mye å si.

Dette er forvørig en liten del av et hovedprosjekt, kravet var at vi skulle bruke en mikrokontroller fra AVR familien, så om jeg bruker 164 eller 64 har lite å si.

Siden jeg allerede har lagd kortutlegg og sånn så er jeg pent nødt til å bruke en Atmega164.

 

Kall meg gjerne dum.. Men jeg skjønner fremdeles ikke nøyaktiv hvordan jeg skal dette helt til.

Har leta etter kodeeksempel, men det meste jeg finner er assembly kode.

 

I databladet til Atmega164 står det følgende under interrupt:

The External Interrupts are triggered by the INT2:0 pin or any of the PCINT31:0 pins.

Mine knapper er jo koblet til PCINT18-21. Skal det ikke da være mulig?

Endret av Furyfax
Lenke til kommentar

hvis du bruker en mega164 så blir det en annen sak ja. den har visst interrupt på alle pinnene, så da er det bare å sette den opp rett. kap 11.i databladet tar for seg dette...

 

kond og motstander kan funke det, men vil vell trenge en motstand i serie også fra kond inn på io pinne. jeg ville brukt timer (billigere, færre komponenter), det virker garantert.

Lenke til kommentar

Jeg har følgende kode nå:

SIGNAL (SIG_INT0){
int button=1;
}


int main(){

/*  PORT C */
DDRC = 0b00111111; // 2 first are outputs, next 6 are inputs
PORTC = 0xFF; 

// Set Pin (PC02) as the pin to use
PCMSK |= (1<<PINC2);

// interrupt on INT0 pin falling edge (sensor triggered) 
MCUCR = (1<<ISC01) | (1<<ISC00);

// turn on interrupts!
GIMSK  |= (1<<INT0);

while(1){

// check for button press to change state
   if (button | startup){
        switch(index){
             case0:
                 *send different I2C commands*
                 startup=0;
                 break;

              case1:
                 *send different I2C commands*
                 startup=0;
                 break;
}//end switch
button=0;
}//end if
}//end while

 

Jeg får warning at signal.h som jeg inkluderer er obselete. Er dett kilden til errorene og warningene?

Her er warnings og errors:

 

C:/WinAVR/avr/include/avr/signal.h:36:2: warning: #warning "This header file is obsolete. Use <avr/interrupt.h>."

../hovedoppgave.c: In function `main':

../hovedoppgave.c:71: error: `PCMSK' undeclared (first use in this function)

../hovedoppgave.c:71: error: (Each undeclared identifier is reported only once

../hovedoppgave.c:71: error: for each function it appears in.)

../hovedoppgave.c:77: error: `GIMSK' undeclared (first use in this function)

../hovedoppgave.c:81: warning: `SIG_INT0' appears to be a misspelled signal handler

../hovedoppgave.c:81: warning: static declaration of 'SIG_INT0' follows non-static declaration

../hovedoppgave.c:81: warning: previous declaration of 'SIG_INT0' was here

Endret av Furyfax
Lenke til kommentar

Fant iallfall ut litt av feilene. Jeg henviste til registre som ikke finnes i Atmega164. Tror jeg nå har fikset dette.

Legger ved et innlegg jeg har på et annet forum, for å se om det er noe input her ifra. (Det er på engelsk igjen):

 

Not sure which _vect to use, I've now used the "INT0_vect ", but I'm not sure wether I should use "PCINT0_vect". Any input on that ?

 

I've now written the following:

#include <avr/interrupt.h>

int button=0;
ISR(INT0_vect) //ISR(PCINT0_vect)
{
button=1;
}//END INT0_vect

int main(){

/*  PORT C */
DDRC = 0b00111111;
PORTC = 0xFF; /*PC0-7 = Input */

// Set Pin (PCint18) as the pin to use for this example
PCMSK2 |= (1<<PCINT18);

// interrupt on INT0 pin falling edge (sensor triggered) 
EICRA = (1<<ISC01) | (1<<ISC00);

// turn on interrupts!
EIMSK  |= (1<<INT0);

while(1){
// check for button press to change state
    if (button | startup){
           bla bla bla}

 

I know only get errors and no warnings, they are:

../hovedoppgave.c:76: error: `PCMSK2' undeclared (first use in this function)

../hovedoppgave.c:76: error: (Each undeclared identifier is reported only once

../hovedoppgave.c:76: error: for each function it appears in.)

../hovedoppgave.c:76: error: `PCINT18' undeclared (first use in this function)

 

Jeg har fått litt informasjon her ifra. Nongnu

 

 

 

EDIT:

 

Her er nøyaktig det som står foran main i mitt program:

 

/* OS headers */
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/io.h>




/* General purpose include files */



/* App required include files. */
#include "hovedoppgave.h"


/* Static functions and variables */
int button=0;


/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 20000000UL
#endif

#define VSP  0xB0

/* I2C clock in Hz */
#define SCL_CLOCK  400000L

ISR(INT0_vect) //ISR(PCINT0_vect)
{
button=1;
}//END INT0_vect



/*************************************************************************
Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
 /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
 
 TWSR = 0;                         /* no prescaler */
 TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */

}/* i2c_init */

Endret av Furyfax
Lenke til kommentar

Fant ut av feilen. Hadde definert chippen som Atmega164, og den fantes visst ikke. Den måtte defineres som Atmega164P!

Gjorde dette og alt ordna seg! Fy faen for et slit og drit. Nå gjenstår det bare å teste å se at det ikke fungerer slikt jeg trodde, hehe.

Endret av Furyfax
Lenke til kommentar

Etter å ha lest litt rundt er jeg ganske usikker på om koden fin funker slik jeg ønsker.

 

Jeg har en pushbutton koblet til PIN21(PCINT18), når denne knappen blir trykket vil jeg at den skal enable en interrupt rutine som setter et flagg høyt.

Her er koden:

#include interrupt.h

int button =0;
ISR(PCINT2_vect)
{
button=1;
}//END PCINT2_vect

int main(){

/*  PORT C */
DDRC = 0b00111111; // Setting the first two to outputs (SCL & SDA) The rest are set as inputs. 
PORTC = 0xFF; 

PCMSK2 |= (1<<PCINT18);

EICRA = (1<<ISC01) | (1<<ISC00); // Kan noen forklare meg litt hva som skjer her?

if(button){
/*bla bla*/
}//end if
}//end main

 

Jeg er usikker på hva EICRA = (1<<ISC01) | (1<<ISC00); gjør, noen som har noe input på det ?

Lenke til kommentar
Jeg er usikker på hva EICRA = (1<<ISC01) | (1<<ISC00); gjør, noen som har noe input på det ?

8404947[/snapback]

EICRA er et register i chippen, ISC01 og ISC00 er 2 forsjellige bit i dette registeret.

Når man skriver slik som over så setter man disse bittene høy, og overser de andre bit'ene i registeret

bytter du ut ett'tallet med null istedet vil du sette dem lav

Lenke til kommentar

Beklager, jeg misforsto vist :=)

 

Det registeret bestemmer om den skal reagere hvis den går fra høy til lav, eller lav til høy osv.

Altså verdien som kommer inn på den eksterne interrupten.

Det kunne iallefall se slik ut i databladet, se side 64 i databladet.

Lenke til kommentar

Ikke helt, hvis du ser i databladet på side 64 som sagt så vil du se en tabell over hvordan den vil oppføre seg etter hvile bit du setter.

Der står det også hvordan du skal bruke registeret og hva man må/bør ta hensyn til.

post-36952-1176835114_thumb.jpg

Datablad

 

EDIT: det står Mega644 i databladet, men det var det som var linka til på siden til Mega164 på avrfreaks, så jeg regner med dem er rimelig like.

Endret av Firesky
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...