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!
-
Scrobik
- -
- Posty: 12
- Rejestracja: 03 sie 2007, 11:06
- Lokalizacja: Stalowa Wola
-
Kontakt:
Post
autor: Scrobik » 03 sie 2007, 11:30
W ponizszym programi po skompilowaniu i uruchomieniu w avr studio. Mam problem bo nie wiem jak przejsc do podprogramu obslugi przerwania od komparatora analogowego. Nie wiem jakie ustawic flagii aby wejsc do podprogramu: SIGNAL (SIG_INPUT_CAPTURE1) -obsługi przerwania od przechwycenia komparatoratora analogowego. Dziekuje za pomoc
Kod: Zaznacz cały
/****************************************************************/
/* Zastosowanie komparatora analogowego do budowy */
/* przetwornika analogowo-cyfrowego. */
/* Wyzwalanie funkcji przechwytywania timera1 */
/* za pomocą komparatora. */
/* Przerwanie od przechwytywania. */
/* Obsługa wewnętrznej pamięci EEPROM. */
/* */
/****************************************************************/
#include <avr\io.h>
#include <avr\interrupt.h>
#include <avr\signal.h>
#include <avr\sfr_defs.h>
#define _EEGET(VAR,ADR)/* Read data in EEPROM address ADR into variable VAR
*/ \
{ \
while(EECR & 0x02); /* Check if EEPROM is ready*/ \
EEAR = (ADR); /* Write EEPROM address register*/ \
EECR |= 0x01; /* Set the read strobe*/ \
(VAR) = EEDR; /* Read the data into variable in the next cycle */ \
}
#define _EEPUT(ADR,VAL) /* Write data in VAL into EEPROM address ADR*/\
{\
while(EECR&0x02); /* Check if EEPROM is ready*/ \
EEAR = (ADR); /* Write EEPROM address register*/ \
EEDR = (VAL); /* Write EEPROM data register*/ \
EECR |= 0x04; /* Set master write enable signal*/ \
EECR |= 0x02; /* Set write strobe*/ \
}
unsigned char liczt0;
volatile unsigned char pomiar; //flaga dokonania pomiaru
union{
unsigned int wspkal; //współczynnik kalibracji
unsigned char wspkalb[2];
}uwspkal;
void czekaj(unsigned long zt) //procedura wytracania czasu
{
#define tau 10.38
unsigned char zt1;
for(;zt>0;zt--)
{
for(zt1=255;zt1!=0;zt1--);
}
}
SIGNAL (SIG_INPUT_CAPTURE1) //obsługa przerwania od przechwycenia
{
union{
unsigned int czas;
unsigned char czasb[2];
}uczas;
unsigned char czas8;
uczas.czasb[0]=ICR1L; //zatrzaśnij rejestry przechwytywania
uczas.czasb[1]=ICR1H;
czas8=~((uczas.czas/uwspkal.wspkal)<<2); //normalizacja wyniku
//do postaci 6-bitowej liczby binarnej przesuniętej o 2 bity
//w lewo (PORTB1 i 0 są wykorzystywane przez komparator
//analogowy)
PORTB=(PORTB&0x03)|czas8; //wyświetl wynik na LEDach
pomiar=1; //pomiar dokonany (zapal flagę)
PORTD|=(1<<4); //zacznij rozładowywać kondensator pomiarowy
}
int main(void)
{
DDRD=0x13; //PORTD we oprócz PD4, PD1 i PD0 - wy
PORTD=0xff; //z podciąganiem
PORTB=0x01; //PB0 z podciąganiem
DDRB=0xfc; //PORTB7-2 - wy, PORTB1-0 - we
TCCR1A=0; //funkcje porównania i PWM wyłączone
TCCR1B=0x41; //preskaler XTAL/1 dla TC1, przechwytywanie na
//narastającym zboczu
TIMSK=0x08; //zezwolenie na przerwania od przechwytywania
ACSR=1<<ACIC; //zezwolenie na wyzwalanie przechwytywania komparatorem
czekaj(10*tau);
TIFR=0xff; //kasuj przerwania od timerów
if(bit_is_clear(PIND,1))
{ //wciśnięty SW4 - kalibracja
do
{
PORTD&=(1<<4); //ładuj kondensator pomiarowy
TCNT1H=0; //zeruj licznik 1 pomiar czasu ładowania
TCNT1L=0;
TIFR|=1<<ICF1;
while(bit_is_clear(TIFR,ICF1)); //czekaj aż napięcie mierzone zrówna się z napięciem
//wejściowym
uwspkal.wspkal=(ICR1L+256*ICR1H);
PORTD|=1<<4;
czekaj(1*tau); //opóźnienie związane z częstotliwością odświeżania
}while(bit_is_set(PIND,0));
uwspkal.wspkal/=64;
_EEPUT(0,uwspkal.wspkalb[0])
_EEPUT(0x01,uwspkal.wspkalb[0])
TIFR|=1<<ICF1;
}
else
{_EEGET(uwspkal.wspkal,0x01)
//odczytaj współczynnik kalibracji z EEPROM-u
}
sei(); //odblokuj globalne przerwania
while(1) //główna pętla pomiarowa
{
PORTD&=~(1<<4); //ładuj kondensator pomiarowy
TCNT1H=0; //zeruj licznik 1 - pomiar czasu ładowania
TCNT1L=0;
pomiar=0;
while(pomiar==0); //czekaj aż napięcie mierzone zrówna się z napięciem
//na kondensatorze pomiarowym
czekaj(23*tau); //opóźnienie związane z częstotliwością odświeżania
//wskaźnika LED
}
}
----------
Kody programów wstawiamy w tagi CODE a nie SHADOW!
Przy takiej ilości kodu powinieneś go jednak umieścić jako załącznik.
Prosze zapoznać się ze wskazówkami jak piszemy w tym dziale.
Moderator ZbeeGin
Ostatnio zmieniony 01 sty 1970, 1:00 przez
Scrobik, łącznie zmieniany 1 raz.
-
ZbeeGin
Post
autor: ZbeeGin » 03 sie 2007, 17:53
Rozwiń pełną gałąź TIMER1, znajdź bit ICF1 oraz ustaw go...
-
Scrobik
- -
- Posty: 12
- Rejestracja: 03 sie 2007, 11:06
- Lokalizacja: Stalowa Wola
-
Kontakt:
Post
autor: Scrobik » 04 sie 2007, 0:46
Dzieki serdeczne za pomoc ale jest nastepny problem bo stan licznika podczas obslugi przerwania TNCT1L i TNCT1H nie zostal skopiowany do rejestrow ICR1L i ICR1H podczas symualcji. Prosze o jakies wskazowki
-
ZbeeGin
Post
autor: ZbeeGin » 04 sie 2007, 8:57
Spróbuj zmienić stan bitu ACO w gałęzi komparatora.
Nie wiem czy zauważyłeś, ale w Twoim programie brak jest operacji ustawiania bitu TICIE, bez tego przerwania ICF nie są zgłaszane.
Ostatnio zmieniony 01 sty 1970, 1:00 przez ZbeeGin, łącznie zmieniany 1 raz.
-
Scrobik
- -
- Posty: 12
- Rejestracja: 03 sie 2007, 11:06
- Lokalizacja: Stalowa Wola
-
Kontakt:
Post
autor: Scrobik » 04 sie 2007, 9:08
Niestety Licznik sie nie przepisuje nawet po zmianie flagi ACO. Mysle ze wina lezy po stronie symulatora. Zostal napisany dla asm. Nie wiem jak to obejsc. Dziekuje za pomoc.
-
ZbeeGin
Post
autor: ZbeeGin » 04 sie 2007, 9:19
Scrobik pisze:Zostal napisany dla asm.
Ale to nie ma żadnego znaczenia. Przecież plik wynikowy z AVRGCC jest kodem maszynowym. A taki podlega symulacji w AVR Studio.
Niestety pozostaje Ci tylko ręcznie ustawiać bity w
ICR1H/ICR1L oraz żąglować flagą
ICF1.
Z tym bitem TICIE jest ok. Ja z rozpędu przyjąłem, że używasz Mega8 a w rzeczywistości jest to Tiny2313/90s2313.

Choć rozsądniej byłoby napisać:
Kod: Zaznacz cały
TIMSK |= 1<<ICIE1;
//zezwolenie na przerwania od przechwytywania
Ostatnio zmieniony 01 sty 1970, 1:00 przez ZbeeGin, łącznie zmieniany 1 raz.
-
Scrobik
- -
- Posty: 12
- Rejestracja: 03 sie 2007, 11:06
- Lokalizacja: Stalowa Wola
-
Kontakt:
Post
autor: Scrobik » 04 sie 2007, 9:36
Oczywiscie ze tak jest rozsadniej ale program sie nie chce skompilowac gdyz nie zostalo napisane makro w pliku head do obslugi tej maski i wywala program. Tak mi sie wydaje. Uzylem at90s2313.
-
ZbeeGin
Post
autor: ZbeeGin » 04 sie 2007, 9:45
No tak. Datasheet nazywa ten bit TICIE1 a w plikach nagłówkowych "pokutuje" TICIE.
-
Scrobik
- -
- Posty: 12
- Rejestracja: 03 sie 2007, 11:06
- Lokalizacja: Stalowa Wola
-
Kontakt:
Post
autor: Scrobik » 04 sie 2007, 10:18
Ponizej jest przedstawiony podobny program tylko napisany w asm. Nie jestem jego autorem. Wszystko sie kompiluje. rjmp AD_convert powinno nastipic po ustawieniu AC0. Jednak sie tak nie dzieje. Dla mnie to jest dziwne. Moze wie pan jak to zrobic w asm. Ja jestem poczatkujacy i dlatego wazne sa dla mnie symulacje. Dziekuje za dotychczasowa pomoc. Mysle ze wymiana spostrzezen jest wazna:)
Kod: Zaznacz cały
.equ preset = 192 ;T/C0 Preset constant (256-64)
.def result = r16 ;Result and intermediate data
.def temp = r17 ;Scratch register
;**************************************************************************
;*
;* PROGRAM START
;*
;**************************************************************************
.cseg
.org $0000
rjmp RESET ;Reset handle
.org OVF0addr
rjmp ANA_COMP ;Timer0 overflow handle
.org ACIaddr
rjmp AD_convert ;Analog comparator handle
ANA_COMP:
in result, TCNT0 ;Load timer value
clr temp ;Stop timer0
out TCCR0, temp
subi result, preset+1 ;Rescale A/D output
cbi PORTD, PD2 ;Start discharge
set ;Set conversion complete flag
reti ;Return from interrupt
convert_init:
ldi result, $0B ;Initiate comparator
out ACSR, result ;and enable comparator interrupt
ldi result, $02 ;Enable timer interrupt
out TIMSK, result
sbi PORTD, PD2 ;Set converter charge/discharge
;as output
ret ;Return from subroutine
AD_convert:
ldi result, preset ;Clear counter
out TCNT0, result ;and load offset value
clt ;Clear conversion complete flag (t)
ldi result, $02 ;Start timer0 with prescaling f/8
out TCCR0, result
sbi PORTB, PB2 ;Start charging of capacitor
ret ;Return from subroutine
RESET:
rcall convert_init ;Initialize A/D converter
sei ;Enable global interrupt
ldi result, $ff ;set port B as output
out DDRB, result
Delay:
clr result ;Clear temp counter 1
ldi temp, $f0 ;Reset temp counter 2
loop1:
inc result ;Count up temp counter 1
brne loop1 ;Check if inner loop is finished
inc temp ;Count up temp counter 2
brne loop1 ;Check if delay is finished
rcall AD_convert ;Start conversion
Wait:
brtc Wait ;Wait until conversion is complete
out PORTB, result ;Write result on port B
rjmp Delay ;Repeat conversion
Ostatnio zmieniony 01 sty 1970, 1:00 przez
Scrobik, łącznie zmieniany 3 razy.
-
ZbeeGin
Post
autor: ZbeeGin » 04 sie 2007, 10:36
W zasadzie to nie przy ustawieniu
ACO tylko przy
ACI. Niestety okazuje się, że AVR Studio odsłania dalsze swoje ograniczenia, a znam już trzy.
ps. Kolega staje się powoli recydywistą. Znów kod nie zamknięty w tagi.
-
Scrobik
- -
- Posty: 12
- Rejestracja: 03 sie 2007, 11:06
- Lokalizacja: Stalowa Wola
-
Kontakt:
Post
autor: Scrobik » 04 sie 2007, 17:29
Jezeli kolega napisalby jakie to sa ograniczenia bylbym bardzo wdzieczny i w przyszlosci pewnie oszczedzilbym wiele czasu i nerwow

Dzieki
-
ZbeeGin
Post
autor: ZbeeGin » 04 sie 2007, 17:58
Zatem nie da się zasymulować:
- pracującego licznika w trybie FAST PWM. Licznik zachowuje się jakby pracował w trybie normalnym (zliczanie w górę i w dół), pomimo ustawienia wszystkich potrzebnych bitów (sprawdzałem na v4.12 i v4.13).
- pracującego licznika w trybie CTC gdzie wartość przeładunkową określa się w rej. OCR. Mimo kilku prób nie udało mi się tego zrobić. (sprawdzałem na v4.13)
- działania funkcji FOC (Force output compare) poprzez ustawianie odpowiednich bitów. Symulator zachowuje się jakby nic się nie działo (sprawdzałem na v4.12 bądź starszej).
I teraz dochodzi komparator analogowy - w obu przypadkach podlegających dyskusji.