Zegar na wyświetlaczach 7-segmentowych - Obsługa Timera

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!
Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 24 wrz 2012, 21:27

maxxxior pisze:a mógłby ktoś mi w między czasie wytłumaczyć o co chodzi z tym dziesiatki = liczba/10 i jednosci = liczba%10 ?? nie rozumiem jak to działa :/
Operacje arytmetyczne: http://mikrokontrolery.blogspot.com/201 ... yczne.html

maxxxior pisze:nie no, nie mam siły już...
bo nie zrobiłeś tego co sugerowałem:
dondu pisze:Na tej podstawie wykombinuj na razie jedynie wyświetlanie jakiejś liczby, bez żadnych innych funkcjonalności zegara. Chodzi o to, byś załapał jak posługiwać się przerwaniem oraz jak multipleksować wyświetlacz.
Nie wzoruj się na innych kodach, których nie rozumiesz. Po prostu pisz swój kod po kolei.
Na początek wyświetlaj np. same zera na każdej cyfrze wyświetlacza.

I pokazuj konkretnie swój kod, a nie jakiś z czeluści internetu.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 24 wrz 2012, 21:49

OK, wklejam mój kod, wyświetlenie liczby 32:

Kod: Zaznacz cały

#include <avr/io.h>
#define F_CPU 1000000
#include <util/delay.h>
#include<avr/interrupt.h>

#define A (1<<PA0)
#define B (1<<PA1)
#define C (1<<PA2)
#define D (1<<PA3)
#define E (1<<PA4)
#define F (1<<PA5)
#define G (1<<PA6)
#define DP (1<<PA7)

volatile char flaga;
volatile int wysw;
volatile unsigned char liczba_LED[10] = {A|B|C|D|E|F, E|F, D|E|G|B|A, D|E|G|F|A, C|G|E|F, D|C|G|F|A, D|C|B|A|F|G, D|E|F, A|B|C|D|E|F|G, C|D|E|G|F|A};

ISR (TIMER0_OVF_vect)
{
	flaga = 1;
}		

int main()
{
	
    //ustaw kierunki transmisji
    DDRD |= (1<<4) | (1<<5);
    DDRA = 0xFF;
	
	sei();
	
	while(1)
	{
		if(flaga=1)
		{ 
		flaga=0;
			switch(wysw)
			{
			case 0:
				PORTD |= (1<<5);		//wlacz wyswietlacz drugi
				PORTA = liczba_LED[2];	//liczba na wyswietlacz
				PORTA &= ~liczba_LED[2];	//wyzerowanie segmentów wyswietlacza drugiego
				PORTD &= ~(1<<5);		//wylacz wyswietlacz drugi
				wysw++;
				break;
				
			case 1:
				PORTD |= (1<<4);		//wlacz wyswietlacz pierwszy
				PORTA = liczba_LED[3];	// zapal segmenty dla odpowiednij liczby
				PORTA &= ~liczba_LED[3];	//wyzerowanie segmentow tej liczby
				PORTD &= ~(1<<4);			// wylacz wyswietlacz pierwszy
				wysw = 0;
				break;
			}
		}
	}
	return 0;
}

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 24 wrz 2012, 21:56

Zacznijmy od tego błędu:

Kod: Zaznacz cały

 if(flaga=1) 
szczegóły: http://mikrokontrolery.blogspot.com/201 ... nania.html

Awatar użytkownika
Ertew
Użytkownik
Posty: 1414
Rejestracja: 03 lip 2005, 10:36
Lokalizacja: Leszno
Kontakt:

Post autor: Ertew » 24 wrz 2012, 22:04

Brakuje 'case: default', pomyśl co zrobi program gdy zmienna wysw przyjmie wartość 2 lub większą.


Teraz błędy odnośnie techniki wyświetlania.
Dlaczego wyświetlasz liczbę przez ułamek sekundy i gasisz?
Przerwanie powinno zgasić to co się świeci, zapalić swoje i na tym zakończyć aż do następnego wywołania przerwania. Inna metoda nie ma sensu.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 24 wrz 2012, 22:08

ok powinno być if(flaga) lub if(flaga==1)

co dalej?

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 24 wrz 2012, 22:25

OK, następnie musimy ustalić jak działa Twój timer.

Wykorzystujesz przerwanie od przepełnienia timer0.
Ale nie widzę, byś go w ogóle ustawiał.
Zegar masz 1MHz.

Jak więc według Ciebie jest ustawiony timer0 i jego preskaler?


EDIT:
Ertew pisze:Brakuje 'case: default', pomyśl co zrobi program gdy zmienna wysw przyjmie wartość 2 lub większą.
Nie przyjmie takich wartości.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 24 wrz 2012, 22:27

tzn jak jest ustawiony teraz, bez żadnej mojej konfiguracji?

P.S. po zmianie tego warunku if(flaga) nic mi nie wyświetla na wyświetlaczu :/

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 24 wrz 2012, 22:29

maxxxior pisze:tzn jak jest ustawiony teraz, bez żadnej mojej konfiguracji?
Tak, bo tak właśnie jest po włączeniu zasilania.
maxxxior pisze:P.S. po zmianie tego warunku if(flaga) nic mi nie wyświetla na wyświetlaczu :/
OK, spokojnie, po kolei ustalimy, co jest nie teges :)



EDIT:
Sprawdzasz datasheet, a ja za ten czas:

Teraz zwróć uwagę na to co napisał kol:
Ertew pisze:Dlaczego wyświetlasz liczbę przez ułamek sekundy i gasisz?
Przerwanie powinno zgasić to co się świeci, zapalić swoje i na tym zakończyć aż do następnego wywołania przerwania. Inna metoda nie ma sensu.
Chodzi o ten fragment:

Kod: Zaznacz cały

            case 0: 
-->             PORTD |= (1<<5);        //wlacz wyswietlacz drugi 
                PORTA = liczba_LED[2];    //liczba na wyswietlacz 
                PORTA &= ~liczba_LED[2];    //wyzerowanie segmentów wyswietlacza drugiego 
-->             PORTD &= ~(1<<5);        //wylacz wyswietlacz drugi 
                wysw++; 
                break; 
Ile czasu według Ciebie świeci ta cyfra?

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 24 wrz 2012, 22:44

No więc po włączeniu zasilanie bity CS00 CS01 CS02 są ustawione na 000, brak sygnału, czyli timer jest wyłączony i brak preskalera.

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 24 wrz 2012, 22:45

maxxxior pisze:No więc po włączeniu zasilanie bity CS00 CS01 CS02 są ustawione na 000, brak sygnału, czyli timer jest wyłączony i brak preskalera.
Bardzo dobrze! Czyli wiemy czemu timer nie pędzi do przodu :)
Gdy to sprawdzałeś ja dopisałem następny punkt - przeczytaj powyżej.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 24 wrz 2012, 22:56

przez ułamek sekundy? ponieważ zapalam ją i od razu bezmyślnie gaszę? Czyli, jak to zrobić aby było dobrze?

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 24 wrz 2012, 23:00

maxxxior pisze:przez ułamek sekundy? ponieważ zapalam ją i od razu bezmyślnie gaszę? Czyli, jak to zrobić aby było dobrze?
Tak jak napisał Ertew, a ja wyjaśnię.
Case 0 wyłącza wyświetlacz B, włącza wyświetlacz A i podaje na niego cyfrę,
Case 1 wyłącza wyświetlacz A, włącza wyświetlacz B i podaje na niego cyfrę,

Wtedy każda cyfra świeci się tyle czasu, ile trwa odstęp pomiędzy kolejnymi przerwaniami.

No to już jesteśmy prawie u celu. Ale podaj jeszcze Twoją propozycję ustawienia timera - obliczenia preskalera + ustawienie rejestrów.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 24 wrz 2012, 23:04

OK,działa, co dalej?

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 24 wrz 2012, 23:07

maxxxior pisze:OK,działa, co dalej?
Skoro masz już wyświetlanie i działa OK, to teraz sam decydujesz jakie chcesz funkcjonalności. Skoro budujesz zegar jako naukę, to proponuję odliczanie czasu zrobić na innym timerze.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 24 wrz 2012, 23:21

hmmm, no właśnie, jak obliczyć tą jedną sekundę?

Czytałem w pewnej książce, tylko że dla trybu CTC , aby obliczyć wartość którą trzeba wpisać do OCR0 należy na przykład dla częstotliwości taktowania 8Mhz: 8000 000/1024(preskaler) /1Hz(czyli dla jednej sekundy?)/200Hz(czest. odświeżania wyśw. (4x50)) = 39. Ale jak to zrobić dla rejestru TCNT0 oraz trybu normal, i dla jednej sekundy ??

ODPOWIEDZ