Interrupt fel, Krets: ATMega32, Språk: C

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Interrupt fel, Krets: ATMega32, Språk: C

Inlägg av Virr3 »

Tjenare. Jag har lite problem med min kod till en klocka.

Det hela byggs runt några 4094 om ni skulle undra. Kretsen som progameras är en ATMega32.

Jag får inga kompilerings fel, men ingenting händer när jag testar.

Så här ser koden ut:

Kod: Markera allt

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

uint8_t Htio = 0;//Variabler som behövs
uint8_t Hen = 0;
uint8_t Mtio = 0;
uint8_t Men = 0;
uint8_t Stio = 0;
uint8_t Sen = 0;
	
void strobe(void);
void strobe(void)
{
	DDRC = _BV(PA0);
	PORTC |=  _BV(PA0);
	_delay_loop_1(10);
	PORTC &= ~_BV(PA0);
}
void clock(void);
void clock(void)
{
	DDRC = _BV(PA2);
	PORTC |=  _BV(PA2);
	_delay_loop_1(10);
	PORTC &= ~_BV(PA2);
}
void data_ok(void);
void data_ok(void)
{
	DDRC = _BV(PA1);
	PORTC |=  _BV(PA1);
	_delay_loop_1(10);
	PORTC &= ~_BV(PA1);
}

void data_nej(void);
void data_nej(void)
{
	_delay_loop_1(10);
}

void enable_on(void);
void enable_on(void)
{
	DDRC = _BV(PA3);
	PORTC |=  _BV(PA3);
}




SIGNAL(SIG_OVERFLOW2)//interuppt triggas på owerflow
{
	strobe();
	clock();	
	enable_on();
	
	Sen++;
	if(Sen>10)
	{	
		Sen=1;
		Stio++;
	}
	else if(Stio==6)
	{
		Stio=0;
		Men++;
	}
	else if(Men>10)
	{
		Men=0;
		Mtio++;
	}
	else if(Mtio==6)
	{
		Mtio=0;
		Hen++;
	}
	else if(Hen==10)
	{
		Hen=0;
		Htio++;
	}
	else if(Htio==2){Htio=0;}
}


int main(void)
{
	TCCR2 = 0x05;  //Aktivera "Normal mode"
	ASSR = 0x08 ;   //Asynchronous Timer/Counter2 Enable
	TIMSK = 0x80;   //Timer/Counter2 Overflow Interrupt Enable 
	

	uint8_t a;
	uint8_t b;
	uint8_t c;
	uint8_t d;
	uint8_t e;
	
	asm volatile("sei");  //enable interrupt 
	
	while(1)
	{	
		for(a=0;a>9;a++)
		{
			if(Htio==a)
			{
				data_ok();
			}
	   
			else
			{
				data_nej();
				clock();
			}
		}
	}
		{
			for(b=0;b>9;b++)
			{
				f=0;
				if(Hen==b)
				{data_ok();}
				else
				{
					data_nej();
					clock();
				}
			}
		}
		{
			for(c=0;c>9;c++)
			{
				if(Mtio==c)
				{data_ok();}
				else
				{
					data_nej();
					clock();
				}
			}
		}
		{
			for(d=0;d>9;d++)
			{
				if(Men==d){data_ok();}
				else
				{
					data_nej();
					clock();
				}
			}
		}
		{
			for(e=0;e>9;e++)
			{
				if(Stio==e)
				{
					data_ok();
				}
				else
				{
				   data_nej();
				   clock();
			   }
			}
		}
		{
			for(f=0;f>9;f++)
			{
			   if(Sen==f)
			   {
					data_ok();
				}
			   else
			   {
					data_nej();
					clock();
			   }
			}
		}
	
	}
}
Jag har kollat med oscilloskop på PA0,PA1,PA2,PA3. ungefär samma sak på alla.
Störst signal är de på PA0, Alltså Strobe, men det är absolut ingen stark signal, inte mer än några millivolt.
Det är inte heller några pulser utan det är mer ett brus.

har suttit och ändrat och ändrat, men nu har idéerna tagit slut, jag kan inte komma på vad som är fel.

Skulle uppskatta stort ifall någon berättade vad som var fel, och varför :)
henkebenke
Inlägg: 516
Blev medlem: 31 maj 2003, 10:42:37
Ort: Helsingborg

Inlägg av henkebenke »

Du borde få kompileringsfel kan man tycka eftersom du har en massa onåbar kod. Din while-sats innehåller endast första for-loopen.

Sen kan man tillägga att funktionsprototyper raden innan deklarationen är meningslös. Man radar upp prototyperna först (lämpligtvis i en h-fil som man inkluderar) så att kompilatorn vet hur funktionen ser ut när den sedan anropas.

Dessutom har du block utanför dina for-loopar vilket bara gör att det ser rörigt ut, ta bort en nivå av {}-paranteser.
Senast redigerad av henkebenke 19 januari 2006, 21:51:20, redigerad totalt 1 gång.
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Vad utvecklar du i? En god idé hade varit att simulera programmet (går i de flesta miljöer). Då ser du var koden går, och hur registrerna rör sig, osv. Breakpoints kan ju vara en bra idé också.

Mvh
speakman
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Inlägg av Virr3 »

Jag utvecklar de hela i Programmers notepad 2. d.v.s Winavr.

Om det går att simulera programmet där i så skulle jag bli mycket glad:)
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Jag vet inte exakt vad du vill göra med programmet, men hela programstrukturen verkar väldigt ologiskt... Jag antar att du vill klocka ut pulser till skiftregistret men jag tror att det är fel på "tänket" när det gäller denna pryl... jag förstår i alla fall inte hur koden ska funka. men jag kanske är lite trött också! =)
JJ
Inlägg: 366
Blev medlem: 16 maj 2005, 21:33:02

Inlägg av JJ »

Virr3 skrev:Jag utvecklar de hela i Programmers notepad 2. d.v.s Winavr.

Om det går att simulera programmet där i så skulle jag bli mycket glad:)
Går det att simulera i AVR Studio?
Användarvisningsbild
PaNiC
Inlägg: 2610
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Inlägg av PaNiC »

Jepp.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Kod: Markera allt

    while(1)
      { // START MAIN-loop
       for(a=0;a>9;a++)
         {
          if(Htio==a)
            {
            data_ok();
            }
         else
           {
           data_nej();
           clock();
           }
        } // SLUT for(a=0;a>9;a++)
     } // STOP MAIN-loop
        { // Hit kommer den aldrig...
        for(b=0;b>9;b++)
          {
          f=0;
          if(Hen==b)
            {
            data_ok();
            }
          else
            {
            data_nej();
            clock();
..... // en del mer
Din main-loop kod kör alltså enbart ut en liten del av det samlade...

Sen tycker jag att det är konstigt att det lilla som kommer inte är digitala nivåer, belaster du för kraftigt eller har du glömt att sätta porten till ut?
Användarvisningsbild
karlstedt
EF Sponsor
Inlägg: 966
Blev medlem: 14 oktober 2003, 16:55:23
Ort: Lund
Kontakt:

Inlägg av karlstedt »

om du vill skippa inline asm så funkar ju även sei() ;)
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Inlägg av Virr3 »

Har ändrat lite i koden nu. nu ser den ut såhär:

Kod: Markera allt

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

uint8_t Htio = 0;//Variabler som behövs
uint8_t Hen = 0;
uint8_t Mtio = 0;
uint8_t Men = 0;
uint8_t Stio = 0;
uint8_t Sen = 0;
	
void strobe(void);
void strobe(void)
{
	DDRA = _BV(PA0);
	PORTA |=  _BV(PA0);
	_delay_loop_1(10);
	PORTA &= ~_BV(PA0);
}
void clock(void);
void clock(void)
{
	DDRA = _BV(PA2);
	PORTA |=  _BV(PA2);
	_delay_loop_1(10);
	PORTA &= ~_BV(PA2);
}
void data_ok(void);
void data_ok(void)
{
	DDRA = _BV(PA1);
	PORTA |=  _BV(PA1);
	_delay_loop_1(10);
	PORTA &= ~_BV(PA1);
}

void data_nej(void);
void data_nej(void)
{
	_delay_loop_1(10);
}

void enable_on(void);
void enable_on(void)
{
	DDRA = _BV(PA3);
	PORTA |=  _BV(PA3);
}




SIGNAL(SIG_OVERFLOW2)//interuppt triggas på owerflow
{
	enable_on();
	strobe();
	clock();	
	
	Sen++;
	if(Sen>10)
	{		
		Stio++;
		Sen=1;
	}
	else if(Stio==6)
	{
		Men++;
		Stio=0;
	}
	else if(Men>10)
	{
		Mtio++;
		Men=0;
	}
	else if(Mtio==6)
	{
		Hen++;
		Mtio=0;
	}
	else if(Hen==10)
	{
		Htio++;
		Hen=0;
	}
	else if(Htio==2)
	{
		Htio=0;
	}
}


int main(void)
{
	TCCR2 = 0x05;  //Aktivera "Normal mode"
	ASSR = 0x08 ;   //Asynchronous Timer/Counter2 Enable
	TIMSK = 0x80;   //Timer/Counter2 Overflow Interrupt Enable 
	

	uint8_t a;
	uint8_t b;
	uint8_t c;
	uint8_t d;
	uint8_t e;
	uint8_t f;
	
	asm volatile("sei");  //enable interrupt 
	
	while(1)
	{	
		for(a=0;a>9;a++)
		{
			if(Htio==a)
			{
				data_ok();
			}
			else
			{
				data_nej();
				clock();
			}
		}
		for(b=0;b>9;b++)
		{
			if(Hen==b)
			{
				data_ok();
			}
			else
			{
				data_nej();
				clock();
			}
		}
		for(c=0;c>9;c++)
		{
			if(Mtio==c)
			{
				data_ok();
			}
			else
			{
				data_nej();
				clock();
			}
		}
		for(d=0;d>9;d++)
		{
			if(Men==d)
			{
				data_ok();
			}
			else
			{
				data_nej();
				clock();
			}
		}
		for(e=0;e>9;e++)
		{
			if(Stio==e)
			{
				data_ok();
			}
			else
			{
			   data_nej();
			   clock();
		   }
		}
		for(f=0;f>9;f++)
		{
		   if(Sen==f)
		   {
				data_ok();
			}
		   else
		   {
				data_nej();
				clock();
		   }
		}
	}
}
Men, ingen större skilnad på utförandet...
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Då du ändå bara har utgångar, så ta bort alla DDRA-rader, och sätt DDRA = 0xFF i början av main() istället.
En vild gissning kan ju vara att den inte tycker om att sätta in/ut en klockcykel, och styra porten i nästa.
Samtliga portar som inte är inkopplade kan rekommenderas sättas som output.

Mvh
speakman
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Bifoga ett kopplingsschema och en förklaring på hur allt SKA funka så blir det lättare för oss att felsöka vad som är fel...
Genom dina DDRA-rader så sätts en utgång i taget till utgång.. jag antar att alla pinnar ska ha samma riktning hela tiden och då är det bättre att bara sätta DDRA i början av programmet. Risken är mindre att man råkar skriva fel värden till DDRA och koden blir kompaktare och mer lättläst.
Virr3
Inlägg: 840
Blev medlem: 25 juli 2004, 23:05:59
Ort: Göteborg

Inlägg av Virr3 »

Okej, kopplingschema kommer här: http://stuffnet.1go.dk/schema.png
Klistra in och klip ut i adressfältet ifall de inte funkar

Men i alla fall. Jag har läst i data bladet gång på gång, nu har jag hittat några rader om just den asynkrona timern. och på sida 216 här står det följande:
When Timer/Counter2 operates asynchronously, some considerations must be taken.
Warning: When switching between asynchronous and synchronous clocking of
Timer/Counter2, the Timer Registers TCNT2, OCR2, and TCCR2 might be
corrupted. A safe procedure for switching clock source is:
1. Disable the Timer/Counter2 interrupts by clearing OCIE2 and TOIE2.
2. Select clock source by setting AS2 as appropriate.
3. Write new values to TCNT2, OCR2, and TCCR2.
4. To switch to asynchronous operation: Wait for TCN2UB, OCR2UB, and
TCR2UB.
5. Clear the Timer/Counter2 Interrupt Flags.
6. Enable interrupts, if needed.
Så, nu har jag ändrat och ändrat, nu de sista har jag gjort såhär:

Kod: Markera allt

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

uint8_t Htio = 0;//Variabler som behövs
uint8_t Hen = 0;
uint8_t Mtio = 0;
uint8_t Men = 0;
uint8_t Stio = 0;
uint8_t Sen = 0;


SIGNAL(SIG_OVERFLOW2)//interuppt triggas på owerflow
{
	PORTA |=  _BV(PA3);
	
	PORTA |=  _BV(PA0);
	_delay_loop_1(10);
	PORTA &= ~_BV(PA0);
	
	Sen++;
	if(Sen>10)
	{		
		Stio++;
		Sen=1;
	}
	else if(Stio==6)
	{
		Men++;
		Stio=0;
	}
	else if(Men>10)
	{
		Mtio++;
		Men=0;
	}
	else if(Mtio==6)
	{
		Hen++;
		Mtio=0;
	}
	else if(Hen==10)
	{
		Htio++;
		Hen=0;
	}
	else if(Htio==2)
	{
		Htio=0;
	}
}


int main(void)
{

	DDRA = 0xFF;	
	
	TIMSK =  0x00;
	ASSR  =  _BV(AS2);
	TCCR2 =  _BV(CS20) | _BV(CS22); 
	TCNT2=0x00;
	while(TCN2UB==0 |TCR2UB==0 )
	{
		TIFR = 0x00;
		
	}
	asm volatile("sei");  //enable interrupt 
	
	uint8_t a;
	uint8_t b;
	uint8_t c;
	uint8_t d;
	uint8_t e;
	uint8_t f;
	
	
	
	while(1)
	{	
		for(a=0;a>9;a++)
		{
			if(Htio==a)
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				PORTA |=  _BV(PA1);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA1);
			}
			else
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				_delay_loop_1(10);
			}
		}
		for(b=0;b>9;b++)
		{
			if(Hen==b)
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				PORTA |=  _BV(PA1);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA1);
			}
			else
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				_delay_loop_1(10);
				
			}
		}
		for(c=0;c>9;c++)
		{
			if(Mtio==c)
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				PORTA |=  _BV(PA1);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA1);
			}
			else
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				_delay_loop_1(10);
			}
		}
		for(d=0;d>9;d++)
		{
			if(Men==d)
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				PORTA |=  _BV(PA1);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA1);
			}
			else
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				_delay_loop_1(10);
			}
		}
		for(e=0;e>9;e++)
		{
			if(Stio==e)
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				PORTA |=  _BV(PA1);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA1);
			}
			else
			{
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
			   _delay_loop_1(10);	
		   }
		}
		for(f=0;f>9;f++)
		{
		   if(Sen==f)
		   {
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				PORTA |=  _BV(PA1);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA1);	
			}
		   else
		   {
				PORTA |=  _BV(PA2);
				_delay_loop_1(10);
				PORTA &= ~_BV(PA2);
				
				_delay_loop_1(10);
				
		   }
		}
	}
}
Men fortfarande samma problem.

B1n4ry förklarade för mig ganska bra hur 4094 funkade i
detta inlägget.
Senast redigerad av Virr3 23 januari 2006, 18:58:02, redigerad totalt 1 gång.
Användarvisningsbild
Icecap
Inlägg: 26647
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Du har ett sista punkt i länken till schemat, ta bort det.

Du verkar sakna kondingar till klockkristallet, jag hade kopplat annolunda men det bör ju fungera rent elektrisk.

Du har ingen pull-down motstånder till dina tryckknappar, 2K2 - 10K borde duga fint.

Programmeringsfel däremot:

Kod: Markera allt

SIGNAL(SIG_OVERFLOW2)//interuppt triggas på overflow
  {
   PORTA |=  _BV(PA3); // OK, den tror jag på
   PORTA |=  _BV(PA0); // Samma här
   _delay_loop_1(10); // Öhhhh...delay i en interrupt???? Varför i all sin dar???
   PORTA &= ~_BV(PA0); // Nåväl, någon anledning är det väl...
   Sen++;  // Räkna upp sekund-ental
   if(Sen>10) // Det är ju en Nixie så minst 1 ska vara aktiv= OK
     {
     Stio++; // Räkna upp sekund-tiorna
     Sen=1; // Nåja, det var en Nixie ju...fast de andra nollas ju...???
     }
   else if(Stio==6) // Nämen...ska vara if(Stio >= 6) OCH inget else!
     { // Originalt: kommer hit 1 sek för sent
     Men++;
     Stio=0;
     }
   else if(Men>10) // Same here: WHY 'else'????
   {
      Mtio++;
      Men=0;
   }
   else if(Mtio==6) // och här...'else'...???
   {
      Hen++;
      Mtio=0;
   }
   else if(Hen==10) // tjatigt men....'else'
   {
      Htio++;
      Hen=0;
   }
   else if(Htio==2) // Har sagt det eller hur??  Jupp, 'else'...
   {
      Htio=0;
   }
}
Mitt förslag till en enkel och välfungerande uppräkning:

Kod: Markera allt

SIGNAL(SIG_OVERFLOW2)//interuppt triggas på overflow
  {
  PORTA |=  _BV(PA3); // OK, den tror jag på
  PORTA |=  _BV(PA0); // Samma här
  _delay_loop_1(10); // Öhhhh...delay i en interrupt????
  PORTA &= ~_BV(PA0); // Nåväl, någon anledning är det väl...
  if(++Sen >= 10) // Räkna upp sekund-ental
    { // Hoppla, 10 eller mer
    Sen = 0; // Nolla sekund-ental
    if(++Stio >= 6) // Räkna upp sekund-tiorna
      { // Hoppla, sekund-tiotal är 6 eller mer
      Stio = 0; // Nolla sekund-tiotal
      if(++Men >= 10) // Räkna upp minut-ental
        { // Oj då, mer än 9 minuter på entalen
        Men = 0; // Nolla minut-ental
        if(++Mtio >= 6) // räkna upp minut-tiotal
          { // Jaha...overflow här med...
          Mtio = 0; // Nolla den då...
          if(++Hen >= 10) // Räkna upp timme-ental
            { // Ojsan, det är mer än 9 timmer på entalen...det går inte
            Hen = 0; // Nolla timme-ental
            if(++Htio >= 2) Htio = 0; // Räkna upp timme-tiotal, om mer än 2 ska den nollas
            }
          }
        }
      }
    }
  }
matseng
Inlägg: 2360
Blev medlem: 16 september 2003, 17:18:13
Ort: Dubai, United Arab Emirates
Kontakt:

Inlägg av matseng »

Icecap skrev:Du har ingen pull-down motstånder till dina tryckknappar, 2K2 - 10K borde duga fint.
Ja, jag vet att man inte ska citera, med eftersom det är off-topic i den här tråden så gör jag det allfall.

Jo, pullmotstånd saknas, men i det stora hela har han ca 109 motstånd för mycket i schemat.

Hade han valt ett shiftreg med lite bättre drivförmåga än en i cmos-serien så hade han kunnat hoppa över alla basmotstånd genom att koppla emittrana till shiftregistret och alla basarna till ett gemensamt motstånd mot +5. (kräver dock att man invertera datat in i shiftregistret så att mnan har en 0'a för den siffra som ska vara tänd). Sen så man kan oxo använda bara ett enda anodmotstånd istället för tio separata katodmotstånd.

Fast tycker man om att borra och löda motstånd så är ju originalschemat bra..... :-)
Skriv svar