Zegar na ATtiny2313 [C]

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Awatar użytkownika
robson
Użytkownik
Posty: 226
Rejestracja: 22 sty 2006, 19:51
Lokalizacja: S.M.
Kontakt:

Zegar na ATtiny2313 [C]

Post autor: robson » 22 sie 2008, 10:11

Witam
Zadanie chyba najprostsze jakie może być a jednak spędza mi sen z powiek bowiem:
Po napisaniu programu na płytce AVT-3505, postanowiłem przenieść go do docelowego układu, który sam sobie zbudowałem. Na płytce AVT-3505 wszystko działało super. Po zamianie definicji wyprowadzeń (#define), okazało się, że program nie działa. Przeprowadziłem symulację w AVR Studio i okazało się, że za żadne skarby nie chce zareagować na przerwanie od Timera0. Wszystkie bity w rejestrze TIMSK i SREG są ustawione prawidłowo, ale po wymuszeniu stanu "1" w rejestrze TIFR (bit TOV0) program nie skacze tam, gdzie powinien (obsługa wyświetlacza). W pliku makefile też wszystko ustawiłem zgodnie z wymaganiami (wybrałem attiny2313, częstotliwość rezonatora, nazwa pliku też jest poprawna). Dodam jeszcze tylko, że program jest zbudowany tak, aby zliczał w trybie przyspieszonym specjalnie po to, aby sprawdzić jego poprawność (godziny zliczane są jako minuty a minuty jako sekundy)
Spędziłem wczoraj całą noc na próbachi niestety nic nie pomogło, dlatego proszę Was o pomoc. Co zrobiłem nie tak? O czym zapomniałem? Poniżej przedstawiam listing programu:

Kod: Zaznacz cały

#include <avr\io.h>
#include <avr\signal.h>
#include <avr\interrupt.h>
#include <inttypes.h>

#define LEDPORT PORTB
#define LEDDDR DDRB
#define COMPORT PORTD
#define COMDDR DDRD
#define COM1 0
#define COM2 1
#define COM3 4
#define COM4 5
#define A PB1
#define B PB2
#define C PB3
#define D PB4
#define E PB5
#define F PB6
#define G PB6
#define STERDDR DDRD
#define PORTSTER PORTD
#define PINSTER PIND
#define SET 3
#define MODE 2 

uint8_t g_AktWyswietlacz ;
uint16_t g_WzoryCyfr[10] ;
uint8_t g_DaneCom[4] ;
uint8_t g_Czas[4] ;
uint8_t g_Ustawienie ;
volatile uint8_t g_Delay ;

// Funkcja zliczania ziesiątek minut:
void Min_dzies(void)
{
	static uint8_t Czas ;
	++Czas ;
	if (Czas > 2)
	{
		Czas = 0 ;
	}
	g_Czas[3] = Czas ;
	return ;
}

// Funkcja zliczania jednostek minut:
void Min_jedn(void)
{
	static uint8_t Czas ;
	++Czas ;
	if (Czas > 3)
	{
		if(g_Czas[3] == 2)
		{
			Czas = 0 ;
			g_Czas[3] = 0 ;
		}
	}	
	if (Czas > 9)
	{
		Czas = 0 ;
		Min_dzies();
	}
	g_Czas[2] = Czas ;
	return ;
}

// Funkcja zliczająca dziesiątki sekund:
void Sek_dzies(void)
{
	static uint8_t Czas ;
	++Czas ;
	if (Czas > 5)
	{
		Czas = 0 ;
		if (g_Ustawienie == 0)
		{
			Min_jedn();
		}
	}
	g_Czas[1] = Czas ;
	return ;
}

// Funkcja zliczająca jednostki sekund: 
void Sek_jedn(void)
{
	static uint8_t Czas ;
	++Czas ;
	if (Czas > 9)
	{
		Czas = 0 ;
		Sek_dzies() ;
	}
	g_Czas[0] = Czas ;
	return ;
}

// Funkcja sprawdzająca przycisk:
void Sprawdz_przycisk(uint8_t przycisk, void(*funkcja)(void))
{
	if (!(PINSTER & przycisk))
	{
		g_Delay = 7 ;
		while (g_Delay != 0){}
		if (!(PINSTER & przycisk))
		{
			g_Ustawienie = 1 ;
			funkcja();
			g_Delay = 160 ;
			while(!(PINSTER & przycisk))
			{
				if (g_Delay == 0)
				{
					g_Delay = 14 ;
					funkcja();
				}
			}
		}
		TCNT1 = 31250 ;
	}
g_Ustawienie = 0 ;
}

	



// Start
int main(void)
{

		// Inicjalizacja wyjść:
		LEDDDR = 0xff ;								
		COMDDR = 1<<COM1 | 1<<COM2 | 1<<COM3 | 1<<COM4 | 1<<6 ;
		PORTD = 1<<SET | 1<<MODE ;
		// Inicjalizacja Timera1:
		TCCR1B = 1<<CS12 ;									// Stopień prescalera Timera1 na 256
		// Inicjalizacja Timera0:
		TCCR0B = 1<<CS02 ;									// Stopień prescalera Timera0 na 256
		// Inicjalizacja Przerwań od timerów:
		TIMSK = 1<<TOIE0 | 1<<TOIE1 ;						// Odblokowanie przerwań od przepełnienia Timera0 i Timera1
		// Globalne odblokowanie przerwań:
		sei() ;
		
	// Tablica wypełniona wzorami cyfr:
	g_WzoryCyfr[0] = ~(1<<A | 1<<B | 1<<C | 1<<D | 1<<E | 1<<F); //0
	g_WzoryCyfr[1] = ~(1<<B | 1<<C) ; //1
	g_WzoryCyfr[2] = ~(1<<A | 1<<B | 1<<D | 1<<E | 1<<G) ; //2
	g_WzoryCyfr[3] = ~(1<<A | 1<<B | 1<<C | 1<<D | 1<<G) ; //3
	g_WzoryCyfr[4] = ~(1<<B | 1<<C | 1<<F | 1<<G) ; //4
	g_WzoryCyfr[5] = ~(1<<A | 1<<C | 1<<D | 1<<F | 1<<G) ; //5
	g_WzoryCyfr[6] = ~(1<<A | 1<<C | 1<<D | 1<<E | 1<<F | 1<<G) ; //6
	g_WzoryCyfr[7] = ~(1<<A | 1<<B | 1<<C) ; //7
	g_WzoryCyfr[8] = ~(1<<A | 1<<B | 1<<C | 1<<D | 1<<E | 1<<F | 1<<G) ; //8
	g_WzoryCyfr[9] = ~(1<<A | 1<<B | 1<<C | 1<<D | 1<<F | 1<<G) ; //9
	
	// Wypełniona tablica odpowiedzialna za obsługę wyświetlaczy:
	g_DaneCom[0] = ~(1<<COM1) ;
	g_DaneCom[1] = ~(1<<COM2) ;
	g_DaneCom[2] = ~(1<<COM3) ;
	g_DaneCom[3] = ~(1<<COM4) ;
	
	for(;;)
	{
		Sprawdz_przycisk(1<<SET, Sek_jedn);
		Sprawdz_przycisk(1<<MODE, Min_jedn);
	}
	return 0 ;
}                      	
// Koniec main





//Przerwanie odpowiedzialne za multipleksowanie i wyświetlanie cyfr:
SIGNAL(SIG_OVERFLOW0)
{
	TCNT0 = 138 ;
	COMPORT |= 1<<COM1 | 1<<COM2 | 1<<COM3 | 1<<COM4 ;
	LEDPORT = g_WzoryCyfr[g_Czas[g_AktWyswietlacz]] ;
	COMPORT &= g_DaneCom[g_AktWyswietlacz] ;
	if (g_Delay > 0)
	{
		--g_Delay ;	
	}
	++g_AktWyswietlacz ;
	if(g_AktWyswietlacz > 3)
		g_AktWyswietlacz = 0 ;
}


// Przerwanie wywoływane co 1s.:
SIGNAL(SIG_OVERFLOW1)
{
        // Ta część odpowiedzialna jest za miganie diodami pomiędzy cyframi minut i sekund
	if ((PORTD & 1<<6))
	{
		PORTD |= 1<<6 ;
	}
	else
	{
		PORTD &= 1<<6 ;
	}
	TCNT1 = 31250 ;
	Sek_jedn();
} 
Z góry dziękuje za każdą pomoc i pozdrawiam robi251:)

p.s.: Czy to możliwe, że mikrokontroler jest uszkodzony?

ZbeeGin

Post autor: ZbeeGin » 22 sie 2008, 17:52

Czyli w symulacji nie działa. Jaki to był AVRGCC, która wersja AVR Studio?

Skompilowałem to przez najnowsze (?) AVR GCC
avr-gcc (WinAVR 20080610) 4.3.0
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling C: zegarek.c
avr-gcc -c -mmcu=attiny2313 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./zegarek.lst -std=gnu99 -Wundef -MMD -MP -MF .dep/zegarek.o.d zegarek.c -o zegarek.o

Linking: zegarek.elf
avr-gcc -mmcu=attiny2313 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=zegarek.o -std=gnu99 -Wundef -MMD -MP -MF .dep/zegarek.elf.d zegarek.o --output zegarek.elf -Wl,-Map=zegarek.map,--cref -lm

Creating load file for Flash: zegarek.hex
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock zegarek.elf zegarek.hex

Creating load file for EEPROM: zegarek.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O ihex zegarek.elf zegarek.eep || exit 0

Creating Extended Listing: zegarek.lss
avr-objdump -h -S -z zegarek.elf > zegarek.lss

Creating Symbol Table: zegarek.sym
avr-nm -n zegarek.elf > zegarek.sym

Size after:
AVR Memory Usage
----------------
Device: attiny2313

Program: 774 bytes (37.8% Full)
(.text + .data + .bootloader)

Data: 35 bytes (27.3% Full)
(.data + .bss + .noinit)

I uruchomiłem w AVR Studio 4.14 (build 589). Program wywołuje przerwania poprawnie - licznik chodzi, przepełnia się, a symulacja wskakuje do SIGNAL(SIG_OVERFLOW0). Ręczne wywoływanie przerwań nie działa - taki kaprys Studio.

Usunąłem jednak z prologu #include <avr/signal.h> i zostawiłem tylko "interrupt.h". Stosowanie SIGNAL jest nieco przestarzałe wypadałoby je zmienić na ISR().

Awatar użytkownika
robson
Użytkownik
Posty: 226
Rejestracja: 22 sty 2006, 19:51
Lokalizacja: S.M.
Kontakt:

Post autor: robson » 23 sie 2008, 8:48

Zainstalowałem inne AVRStudio - takie jak Twoje - 4.14 i... po prostu zadziałało...To na prawdę był kaprys:)
ZbeeGin pisze:Usunąłem jednak z prologu #include <avr/signal.h> i zostawiłem tylko "interrupt.h". Stosowanie SIGNAL jest nieco przestarzałe wypadałoby je zmienić na ISR().
Dzięki ZbeeGin a tak przy okazji, skąd wiesz o takich ciekawostkach? Domyślam się, że czytając różne fora a także strony (najczęściej nie w polskim języku)można się natknąć na wiele ciekawych rzeczy, ale o tym jakoś nie wiedziałem. Polecam stronkę http://www.avrfreaks.net/ jest dużo informacji (Zapewne ją już znasz, ale może komuś jeszcze się przyda) - sorki za offa.
Pozdrawiam :grin:

[ Dodano: 2008-08-23, 09:50 ]
p.s.: Ale na mikrokontrolerze zadziałało dopiero po Twojej sztuczce z usunięciem SIGNAL.
Ostatnio zmieniony 26 sie 2008, 17:35 przez robson, łącznie zmieniany 1 raz.

ZbeeGin

Post autor: ZbeeGin » 23 sie 2008, 19:36

robson pisze:Dzięki ZbeeGin a tak przy okazji, skąd wiesz o takich ciekawostkach?
Od kompilatora który uprzedził Mnie, że ten plik nagłówkowy jest "obsolete". Zresztą już wiele na ten i tematy SBI, CBI napisano...

ODPOWIEDZ