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!
-
Laik
- Użytkownik
- Posty: 242
- Rejestracja: 21 maja 2007, 19:19
- Lokalizacja: z nienacka
Post
autor: Laik » 17 wrz 2010, 12:03
Witam. Chcę zrobić czujnik odległości. Mam już potrzebne elementy tylko na razie brakuje wiedzy i dlatego mam pytania. Mam taki program do sterowania 2 wyświetlaczami 7seg problem w tym ze przerwania nie startują. Co jest problemem?
Kod: Zaznacz cały
#define F_CPU 1000000L
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define Enable_INT0_F MCUCR |= (1 << ISC01); GICR |= (1 << INT0);
#define Timer0_Start TCCR0 = (1 << CS01) | (1 << CS00); TIMSK |= (1 << TOIE0); TCNT0 = 131;
#define Timer0_Stop TCCR0 =0;
int cyf[10] = {0xA0,0xFc,0x92,0x98,0xCC,0x89,0x81,0xBC,0x80,0x88};
int wyswietlacz = 1;
int liczba = 12;
int dziesiatki = 0;
int jednosci = 0;
int main(void)
{
Enable_INT0_F;
Timer0_Start;
sei();
DDRB = 0x01;
PORTB = 0xFF;
DDRD = 0xFF;
PORTD = 0x80;
while(1)
{
// Odczytywanie stanu przyciskow
while(!(PINB & 0x02)) {
liczba++;
_delay_ms(80);
while(!(PINB & 0x02)) {}
_delay_ms(80);
}
while(!(PINB & 0x04)) {
liczba--;
_delay_ms(80);
while(!(PINB & 0x04)) {}
_delay_ms(80);
}
while(!(PINB & 0x08)) {
liczba = 0;
_delay_ms(80);
while(!(PINB & 0x08)) {}
_delay_ms(80);
}
while(!(PINB & 0x10)) {
liczba = 9;
_delay_ms(80);
while(!(PINB & 0x10)) {}
_delay_ms(80);
}
//Rozdzielanie liczby dwu cyfrowej na dziesiatki i jednosci
dziesiatki = liczba / 10;
jednosci -= 10 * dziesiatki;
}
}
SIGNAL (INT0_vect) //Obsluga przerwania
{
//...
}
SIGNAL (TIMER0_OVF_vect)
{
if(wyswietlacz == 1){
PORTB ^= 0x40;
PORTD = cyf[dziesiatki];
wyswietlacz++;
}
if(wyswietlacz == 2){
PORTB ^= 0x80;
PORTD = cyf[jednosci];
wyswietlacz--;
}
}
-
keruseykaryu
Post
autor: keruseykaryu » 17 wrz 2010, 16:57
Magiczne słowa są potrzebne:
volatile. No i nie używaj SIGNAL() bo to przestarzałe jest. A i samo przerwanie jest źle napisane. Raportu kompilacji się nie czyta?
[ Dodano: 2010-09-17, 18:34 ]
Aha! I jeszcze tu się zastanów co dadzą te dwie instrukcje
Kod: Zaznacz cały
dziesiatki = liczba / 10;
jednosci -= 10 * dziesiatki;
-
Laik
- Użytkownik
- Posty: 242
- Rejestracja: 21 maja 2007, 19:19
- Lokalizacja: z nienacka
Post
autor: Laik » 18 wrz 2010, 15:12
Magiczne słowa są potrzebne: volatile
Już wstawiłem w kod i jest ok. Przerwania ruszyły
No i nie używaj SIGNAL() bo to przestarzałe jest.
To co używać zamiast tego ?
Kod: Zaznacz cały
dziesiatki = liczba / 10;
jednosci -= 10 * dziesiatki;
tutaj glupi błąd powinno być
Problem jest z wyświetlaniem bo wyświetla mi tylko 1 segment. Coś nie tak w przerwaniu ?
PS. jak zrobic pod PB6 i PB7 czyli piny od kwarcu aby dzialaly jako zwykle wejscia/wyjscia?
-
keruseykaryu
Post
autor: keruseykaryu » 18 wrz 2010, 18:29
Laik pisze:To co używać zamiast tego ?
Zapewne jakbyś poszukał to i owo w dokumentacji to znalazłbyś makro ISR(), które zastąpiło poprzednie makra.
Laik pisze:Problem jest z wyświetlaniem bo wyświetla mi tylko 1 segment. Coś nie tak w przerwaniu ?
Owszem. Dlatego napisałem, że masz je źle napisane. Musisz zrobić tak, by obie cyfry miały czas się wyświetlić. Tylko bez żadnych _delay_ms/us() w przerwaniu.
Laik pisze:PS. jak zrobic pod PB6 i PB7 czyli piny od kwarcu aby dzialaly jako zwykle wejscia/wyjscia?
Skąd mam wiedzieć jak nie napisałeś nawet jakiego procesora używasz...
-
Laik
- Użytkownik
- Posty: 242
- Rejestracja: 21 maja 2007, 19:19
- Lokalizacja: z nienacka
Post
autor: Laik » 19 wrz 2010, 0:37
Korzystam z ATmega8. Co do zwolnienia przerwań chodzi o preskaler CS00, CS01, CS02 ? Znalazłem w internecie taka tabele:

Ale zmieniając konfiguracje efekt nie był zadowalający. Jak rozumiem timer0 w trybie normalnym zlicza od 0 do 255. Więc potrzebuje użyć trybu CTC i ustawić OCR0 na większą wartość niż 255 tak? W moim kodzie mam jeszcze cos takiego jak TCNT0 - ustawienie licznika jest na 131 czyli licznik pracuje 131 - 255 tak ? Zmiana wartości także nie przynosi rezultatu.
Tak wygląda symulacja (wyświetlacz powinien wyświetlić 25)

-
keruseykaryu
Post
autor: keruseykaryu » 19 wrz 2010, 6:21
Nie masz zwalniać przerwań! Masz je poprawnie napisać. Przeanalizuj sobie jaki czas będzie świecić jedna, a jaki druga cyfra. Co możesz zrobić by się wyświetlały z tym samym czasem? Przy pisaniu programów trzeba niestety ruszyć głową, a nie szukać gdzie popadnie. Nie możesz wpisać do licznika 8bit wartości większej niż 255. Zostaw tą konfigurację licznika na razie w spokoju.
-
Laik
- Użytkownik
- Posty: 242
- Rejestracja: 21 maja 2007, 19:19
- Lokalizacja: z nienacka
Post
autor: Laik » 19 wrz 2010, 20:11
Faktycznie głupi błąd w kodzie przerwania. Kod poprawiłem na taki:
Kod: Zaznacz cały
ISR(TIMER0_OVF_vect)
{
PORTD = 0xFF;
PORTB ^= 0xC0;
switch(wys){
case 1:
PORTD = cyf[dziesiatki];
wys++;
break;
case 2:
PORTD = cyf[jednosci];
wys = 1;
break;
default: wys = 1;
break;
}
}
I jest wszystko ok. Teraz wracam z pytaniem o tych pinach PB6 i PB7 w atmega8. Jak ustawić abym mógł z nich korzystać?
-
keruseykaryu
Post
autor: keruseykaryu » 21 wrz 2010, 5:24
Laik pisze:Teraz wracam z pytaniem o tych pinach PB6 i PB7 w atmega8. Jak ustawić abym mógł z nich korzystać?
W zasadzie nic nie trzeba robić. Nowa ATMega8 (taka prosto ze sklepu) ma tak ustawione bezpieczniki, że PB6 i PB7 to normalne porty. Jak już przestawiałeś fuski to musisz zawrócić zmiany oscylatora na Internal RC.
-
Laik
- Użytkownik
- Posty: 242
- Rejestracja: 21 maja 2007, 19:19
- Lokalizacja: z nienacka
Post
autor: Laik » 21 wrz 2010, 7:35
Oto chodzi że żadnych fuse bitów nie przestawiałem a porty nie działają. W takim razie będę zmuszony do zmiany układu. Dziękuje za pomoc.