Problem z zasymulowaniem obsługi przerwania w AvrStudio

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
Scrobik
-
Posty: 12
Rejestracja: 03 sie 2007, 11:06
Lokalizacja: Stalowa Wola
Kontakt:

Problem z zasymulowaniem obsługi przerwania w AvrStudio

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.

ODPOWIEDZ