logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

ATmega16 - przepełnienie od T0 powoduje problemy na portach

golas17 11 Wrz 2009 19:13 1830 20
REKLAMA
  • #1 7006713
    golas17
    Poziom 16  
    Witam,
    Opiszę może krótko sytuację: mam atmega16, na timer1 mam ustawiony tryb pracy pwm, używam kilku pinów na PORTD i PORTA do sterowania mostkamiH. Potrzebuję odmierzanie czasu 10ms i chciałem to zrealizować przy pomocy przepełnienie od timera0 lub timera2. Niestety kiedy chcę obsługiwać przerwanie od przepełnienia T0 lub T2, to całkowicie psuje mi się wszystko to co ma sterować mostkami - te kilka pinów i pwm na T1. Problem znika kiedy wyzeruję znacznik TOIE0 w TIMSK. Kiedy ten znacznik jest ustawiony to niestety układ nie pracuje tak jak oczekuję.
    Czy ktoś wie czym to jest spowodowane? Będę wdzięczny za każdą sugestię
  • REKLAMA
  • #2 7007489
    mirekk36
    Poziom 42  
    PWM Timera może mieć tylko coś wspólnego z PD4 i PD5. Timer2 z PD7 a Timer0 z PB3 - zajrzyj sobie do PDF'a - to są wyjścia OC1A, OC1B , OC0 i OC2. Mogą mieć tyle wspólnego - że są właśnie wyjściami PWM - jeśli więc podłączyłeś je do mostków to nie dziwota że coś nie tak - jeśli tego nie zamierzałeś wcześniej - no ale to można tylko zgadywać - bo pytanie typowe dla większości - typu - "co się u mnie dzieje?" - a zero schematu, informacji w czym programujesz itp

    .... PORTA nie ma nic a nic wspólnego z żadnym z wyjść PWM żadnego Timera - więc jeśli i tam uważasz że coś ci się chrzani - to możesz być pewien, że to tylko twoja wina:

    1. albo złych połączeń
    2. albo braku zasilania na wszystkich nogach procka - np na AVCC
    3. albo samego kodu programu

    no ale - przy tak tylko enigmatycznie sformuowanym pytaniu to raczej robota dla dobrej wróżki - jak zwykle
  • #3 7007505
    rusala
    Poziom 22  
    nie sposob sie nie zgodzic z przedmowca. Na tych pinach sa wyjscia pwma od tych licznikow i jedyne co sie logicznego nasuwa to wlasnie sytuacja, w ktorej sygnal pwm pojawia sie na jednym z pinow sterujacych moskiem. Nasuwa sie podstawowe pytanie - po kiego grzyba do odmierzania czasu uzywac trybu PWM ?!?
  • REKLAMA
  • #4 7007861
    golas17
    Poziom 16  
    Wyjaśniam: do odmierzania czasu nie używam trybu PWM. PWM został wykorzystany do sterowania silnikami dc (mam dwa silniki). Wybrałem kanały 0C1A i OC1B - Timer1. Do odmierzania czasu chciałem użyć timera0 - ustawiłem preskaler na 1024. Odmierza poprawnie. Problem w tym, że kiedy poprawnie działa odmierzanie czasu, to coś złego dzieje się z PWM generowanym przez T1, na dodatek piny PD0, PD1, PA6, PA7 dziwnie się zachowują. Wszystko jest całkowicie poprawnie kiedy przy odmierzaniu czasu nie korzystam z przerwania od przepełnienia T0 - sprawdzam po prostu w while(1) czy doszło do przepełnienia. Kiedy mam ustawiony bit TOIE0 w TIMSK-u, to wszystko się wali.
    Gdyby tu chodziło o podłączenie pod złe piny to bym nie pisał postu. Spaliłem już jeden mostek i musiałem przelutowywać tranzystory. To jest dla mnie totalnie niezrozumiałe. Miałem nadzieję, że ktoś miał podobny problem i mi pomoże.
    Tak w ogóle to działam na wydrukowanej już płytce - nie ma mowy o złym podłączeniu.
    Najdziwniejsze jest to o czym już pisałem - wszystko się psuje kiedy mam ustawiony bit TOIE0 lub TOIE2 w TIMSK. Kiedy ten bit jest skasowany (nie korzystam z przerwań) - wszystko gra.

    Piszę w AVRstudio w C.
  • REKLAMA
  • #6 7007929
    mirekk36
    Poziom 42  
    napisałeś, że nie korzystasz z przerwań - tzn nigdzie w programie nie masz na pewno polecenia sei(); ???

    po drugie po co włączasz w ogóle zezwolenie na przerwanie Timera 0 lub 2 bitami TOIE0 lub 2 w TIMSK ???? skoro właśnie nie używasz przerwań

    przecież jeśli tylko programowo chcesz używać odmierzania czasu Timerem to bez zezwolenia na przerwanie powinieneś badać stan flagi TOV0 lub TOV2 - ona zostanie ustawiona i bez zezwolenia na przerwanie. Oczywiście wtedy trzeba ją kasować samemu "ręcznie" ale poprzez wpisanie JEDYNKI ....

    być może jednak - w jakiś sposób uaktywniają się przerwania a że nie masz procedury obsługi tego przerwania to może program idzie w maliny - i wtedy te dziwne objawy na różnych pinach portów

    może?

    a może pokaż fragment kodu jak sprawdzasz te czasy?
  • #7 7007959
    rusala
    Poziom 22  
    tak kod by co nieco wyjasnic mogl sprawe. Tak jak pisze mirekk36 kod moze isc w maliny ale tez jak sugeruje mozna obejsc problem poprostu nie uzywajac przerwania do odmierzania czasu bo i po co? wystarczy sprawdzic flage w while'u
  • REKLAMA
  • #8 7007979
    golas17
    Poziom 16  
    Właśnie sprawdzam flagę w while. Ale chciałem to zrobić na przerwaniach - w końcu po to są przerwania.

    
    void init_timers()                          //dotyczy T0
    {
    	TIMER_CONTROL_REG |= _BV(TIMER_SCK2) | _BV(TIMER_SCK0);       //preskaler ustawiony na 1024
    //	TIMER_INT_REG |= _BV(TIMER_OVW_INT_ENABLE);     //!!!!tutaj jest problem o którym piszę. Jeżeli ustawię ten bit, to wszystko szlag trafia. Jeżeli ta linijka jest w komentarzu to wszystko śmiga
    	TIMER_VAL=254;
    }
    
    unsigned char odmierz_ms(unsigned char ms)       //dotyczy T0
    {
    	TIMER_VAL=0xff-(ms*MS);
    	return 1;
    }
    //------------------------------------------------------------------------
    /*SIGNAL(SIG_OVERFLOW0)                       //
    {
    	odmierz_ms(OKRES_SPI_MS);
    	SPI_master_transmit(SLAVE_NADAWAJ);
    	_delay_us(1);
    	received16.byte.lo=SPI_master_get_data();
    	PORTC=received16.byte.lo;
    	SPI_master_transmit(SLAVE_NADAWAJ);
    	received16.byte.hi=SPI_master_get_data();
    }*/
    //-------------------------------------------------------------------------
    int main()
    {
    //--
    //inicjalizacja master SPI na atmega16--------------------------------------------------------------
    init_SPI(INIT_MASTER);
    //--------------------------------------------------------------------------------------------------
    
    init_timers();                  
    
    init_PWM();                         //ustawiam piny PD0,PD1,PA6,PA7 i timer1 w trym pwm
    set_M1_PWM_duty(0);          //ustawiam wartość rejestru OCR1A,B
    set_M2_PWM_duty(0);
    set_M1_direction(LEFT);       //zwykłe operacje na pinach wyjściowych
    set_M2_direction(LEFT);
    
    
    
    sei(); //zgoda globalna na przerwania
    
    
    	while(1)
    	{
    
    		if(bit_is_set(TIMER_INT_FLAG_REG,TOV_FLAG))		         
    //jeżeli dojdzie do przepełnienia timera to pobierz dane od układu slave
    		{
    			TIMER_INT_FLAG_REG|=_BV(TOV_FLAG);
    			odmierz_ms(OKRES_SPI_MS);
    			SPI_master_transmit(SLAVE_NADAWAJ);
    			temp16.byte.lo=SPI_master_get_data();
    			SPI_master_transmit(SLAVE_NADAWAJ);
    			temp16.byte.hi=SPI_master_get_data();
    		}
    
    		if(temp16.word!=received16.word)            //podejmij działania tylko w wypadku gdy coś uległo zmianie od ostatniej operacji
    		{
    			.........reszta kodu niezwiazana z problemem
    		}
    	}
    }


    Jak coś jeszcze potrzebujecie to piszcie. Jaką funkcję itp. Jeżeli macie uwagi do samego stylu w jakim to jest napisane to też chętnie poczytam.
    Ja w kodzie nie mogłem się doszukać problemu... Zobaczymy czy wy dacie radę
  • #9 7008003
    rusala
    Poziom 22  
    przerwania sa po to zeby cos zrobic priorytetowo i niezaleznie od tego co sie dzieje w programie a jak nic innego nie muszisz w tym czasie robic tylko czekac to poco to komplikowac przerwaniem? Tak na pierwsza uwage do kodu proponuje uzyc zamiast SIGNAL ISR.
  • #10 7008200
    golas17
    Poziom 16  
    A mógłbyś opisać krótko podstawowe różnice pomiędzy SIGNAL i ISR? Wiem że signal wyłącza obsługę innych przerwań. W przypadku ISR przerwanie o wyższym priorytecie może przerwać aktualnie wykonywane przerwanie? Czy są tam jakieś inne różnice?
  • #11 7008385
    Freddie Chopin
    Specjalista - Mikrokontrolery
    golas17 napisał:
    A mógłbyś opisać krótko podstawowe różnice pomiędzy SIGNAL i ISR?

    A nie mógłbyś sam sobie przeczytać w dokumentacji do avr-libc? Przecież chyba po to jest no nie?

    4\/3!!
  • #13 7008569
    golas17
    Poziom 16  
    Ok, sorry za te priorytety przerwań. Chodziło mi o to, że inne przerwanie może przerwać obsługę aktualnie wykonywanego przerwania.
    A wracając do tematu. Jakieś pomysły dlaczego ustawienie TOIE0 powoduje jakieś dziwne perturbacje w układzie?
  • #14 7008601
    mirekk36
    Poziom 42  
    golas17 ---> czy gdzieś w swoim kodzie używasz tych pinów, na których występują ci te zakłócenia ???

    coś ciebie trzeba ciągnąć za język jak nie wiem ....

    doszukujesz się problemu a nawet nie przedstawiłeś tych fragmentów kodu gdzie - wykonujesz jakieś działania na tych pinach.....

    schematu też ni w ząb - nawet rąbka - co to wszystko mniej więcej chociaż robi

    no ja dalej to już pasuję - jeśli chodzi o takie stawianie enigmatycznych zagadek i zgadywanek - sam napisałeś:

    golas17 napisał:
    Ja w kodzie nie mogłem się doszukać problemu... Zobaczymy czy wy dacie radę


    pewnie, szczgólnie że dla ułatwienia ukryłeś np sterowanie tymi portami na których rzekomo z powodu TOIE występują u ciebie zakłócenia
  • #15 7008761
    golas17
    Poziom 16  
    Podaję więc te fragmenty gdzie używam timera1 i pinów PD0,PD1,PA6,PA7:
    
    #define MOTOR1_DDR					DDRA
    #define MOTOR1_LEFT_DDR_PIN			DDA6
    #define MOTOR1_RIGHT_DDR_PIN		DDA7
    #define MOTOR2_DDR					DDRD
    #define MOTOR2_LEFT_DDR_PIN			DDD0
    #define MOTOR2_RIGHT_DDR_PIN		DDD1
    /*PORT*/
    #define MOTOR1_PORT					PORTA
    #define MOTOR1_LEFT_PORT_PIN		PA6
    #define MOTOR1_RIGHT_PORT_PIN		PA7
    #define MOTOR2_PORT					PORTD
    #define MOTOR2_LEFT_PORT_PIN		PD0
    #define MOTOR2_RIGHT_PORT_PIN		PD1
    /*TIMER1 - PWM*/
    /* TCCR1A */
    #define T1_CONTROL_REGA				TCCR1A
    #define COMPARE_OUT_MODE_CHANNEL_A1	COM1A1
    #define COMPARE_OUT_MODE_CHANNEL_A0	COM1A0
    #define COMPARE_OUT_MODE_CHANNEL_B1	COM1B1
    #define COMPARE_OUT_MODE_CHANNEL_B0	COM1B0
    #define WAVE_GEN_MODE11				WGM11
    #define WAVE_GEN_MODE10				WGM10
    /* TCCR1B */
    #define T1_CONTROL_REGB				TCCR1B
    #define WAVE_GEN_MODE13				WGM13
    #define WAVE_GEN_MODE12				WGM12
    #define T1_SCK2						CS12
    #define T1_SCK1						CS11
    #define T1_SCK0						CS10
    /*TCNT1*/
    #define T1_VAL						TCNT1
    /*OCR1A, OCR1B*/
    #define MOTOR_PWM_DUTY_DDR			DDRD
    #define MOTOR1_PWM_DUTY_PIN			DDD5
    #define MOTOR2_PWM_DUTY_PIN			DDD4
    #define MOTOR1_PWM_DUTY				OCR1A
    #define MOTOR2_PWM_DUTY				OCR1B
    /*ICR1 - DEFINING THE TOP OF PWM COUNTER*/
    #define PWM_TOP_REG					ICR1
    #define PWM_TOP_VAL					20000
    #define LEFT						100
    #define RIGHT						101
    
    
    
    void init_PWM()
    {
    	MOTOR_PWM_DUTY_DDR |= _BV(MOTOR1_PWM_DUTY_PIN) | _BV(MOTOR2_PWM_DUTY_PIN);     
    	MOTOR1_DDR |= _BV(MOTOR1_LEFT_DDR_PIN) | _BV(MOTOR1_RIGHT_DDR_PIN);
    	MOTOR1_PORT |= _BV(MOTOR1_LEFT_PORT_PIN) | _BV(MOTOR1_RIGHT_PORT_PIN);
    	MOTOR2_DDR |= _BV(MOTOR2_LEFT_DDR_PIN) | _BV(MOTOR2_RIGHT_DDR_PIN);
    	MOTOR2_PORT |= _BV(MOTOR2_LEFT_PORT_PIN) | _BV(MOTOR2_RIGHT_PORT_PIN);
    	T1_CONTROL_REGA |= _BV(COMPARE_OUT_MODE_CHANNEL_A1) | _BV(COMPARE_OUT_MODE_CHANNEL_B1) | _BV(COMPARE_OUT_MODE_CHANNEL_A0) | _BV(COMPARE_OUT_MODE_CHANNEL_B0);  //set OC1A or OC1B on compare match when upcounting
    	T1_CONTROL_REGB |= _BV(WAVE_GEN_MODE13) | _BV(T1_SCK0);									 //pwm phase and frequency correct, start timer
    	PWM_TOP_REG=PWM_TOP_VAL;
    }
    void set_M1_PWM_duty(char percent)
    {
    	int temp=0;
    	temp=(PWM_TOP_VAL/100)*percent;
    	MOTOR1_PWM_DUTY=temp;
    }
    void set_M2_PWM_duty(char percent)
    {
    	int temp=0;
    	temp=(PWM_TOP_VAL/100)*percent;
    	MOTOR2_PWM_DUTY=temp;
    }
    void set_M1_direction(char left_or_right)
    {
    	MOTOR1_PWM_DUTY=0;  //zatrzymanie sygnału pwm
    	_delay_us(3);
    	MOTOR1_PORT |= _BV(MOTOR1_LEFT_PORT_PIN) | _BV(MOTOR1_RIGHT_PORT_PIN);	//włączenie hamulca na dwóch górnych tranzystorach mostka
    	_delay_ms(10);
    	if(left_or_right==LEFT)  MOTOR1_PORT&=~_BV(MOTOR1_RIGHT_PORT_PIN);
    	if(left_or_right==RIGHT) MOTOR1_PORT&=~_BV(MOTOR1_LEFT_PORT_PIN);
    	_delay_us(3);
    }
    void set_M2_direction(char left_or_right)
    {
    	MOTOR2_PWM_DUTY=0;
    	_delay_us(3);
    	MOTOR2_PORT |= _BV(MOTOR2_LEFT_PORT_PIN) | _BV(MOTOR2_RIGHT_PORT_PIN);
    	_delay_ms(10);
    	if(left_or_right==LEFT)  MOTOR2_PORT &=~ _BV(MOTOR2_RIGHT_PORT_PIN);
    	if(left_or_right==RIGHT) MOTOR2_PORT &=~ _BV(MOTOR2_LEFT_PORT_PIN);
    	_delay_us(3);
    }

    ATmega16 - przepełnienie od T0 powoduje problemy na portach
  • #16 7008772
    janbernat
    Poziom 38  
    " //ustawiam piny PD0,PD1,PA6,PA7 i timer1 w trym pwm "
    A jak się ustawia PA6 i PA7 w tryb pwm?
    A PD0 i PD1 to jest UART.
    Wyjścia sprzętowe pwm od TIMER1 to są PD4 i PD5.
    Chyba że jest to PWM programowy.
    Wtedy trzeba sprawdzić ile czasu program tkwi w przerwaniu.
    Bo wtedy nie obsługuje pwm.
    A żeby nie spalić mostków proponuję zamiast silników dać opornik i dwa LED-y.
    Wtedy można bezpiecznie sprawdzać niesprawdzony program.
  • #17 7008858
    golas17
    Poziom 16  
    Dzięki za radę z tymi ledami.
    Piny PD0,PD1,PA6,PA7 - one tylko sterują kierunkiem obrotów prawo/lewo silników. Nie mają nic wspólnego z PWM. Są ustawione jako zwykłe wyjścia.
    Sygnał PWM pojawia się tylko na wyjściach OC1A,OC1B.
  • #18 7008886
    janbernat
    Poziom 38  
    A jednak pwm sprzętowy.
    Ale do czego służą s5 i s6?
    Do jakiegoś pomiaru?
    I jak są sterowane?

    Dodano po 5 [minuty]:

    Przyznam się że kompletnie nie rozumiem jak te piny mają sterować kierunkiem obrotów.
    Gdyby napięcie z nich służyło to wysterowania cewki jakiegoś przekaźnika-to rozumiem.
    Ale one idą na styki przekaźnika- mogą najwyżej coś mierzyć.
    Ale co?
    W dodatku to są wyjścia.

    Dodano po 8 [minuty]:

    ATmega16 - przepełnienie od T0 powoduje problemy na portach
    To jest mostek który raczej się po odłączeniu silnika nie spali.
    A na diodach wszystko widać.
  • #19 7008978
    golas17
    Poziom 16  
    PD0-PD1 - sterują kierunkiem obrotów silnika: 01 - lewo, 10 - prawo, 11 - hamulec na górnych tranzystorach. Podobnie PA6,PA7. To nie jest tak, że te piny bezpośrednio wysterowują duży tranzystor. Wysterowują one małe tranzystorki, które kontrolują pracę tranzystorów górnych i dolnych mostka.
    Włączniki S5 i S6 - dodałem je w razie gdybym nie chciał używać silników, a tylko testował czujniki - pozwalają mi odłączyć silniki od sterowania.
    I rozumie ktoś coś z tego? Gdzie jest związek pomiędzy przerwaniem od przepełnienia T0 a tymi pinami?
  • #20 7009240
    janbernat
    Poziom 38  
    A gdyby wyłączyć pwm i sprawdzić tylko spi i przerwania z timer0?
    A potem włączyć tylko sterowanie sprzętowe pwm - bez zmiany wypełnienia i kierunku?
    I wtedy sprawdzić tylko czy to działa.
    Bo nie wiadomo czy to wychodzi z pętli "while".
    "set_M1_PWM_duty" i "set_M1_direction" to nie wiem gdzie są wywoływane.
  • #21 7010142
    golas17
    Poziom 16  
    Funkcje ustawiające wartość wypełnienia pwm i kierunek obrotów wywoływane są w pętli while(1). W zależności od odczytów z czujników. Nie ma sensu tego tutaj przedstawiać. Te nieudane testy podczas których spaliłem jeden z mostków wykonywałem kiedy pętla while zawierała tylko dwie zmiany kierunku i wypełnienia.
    Pokombinuje przy czasie z tym włączaniem i wyłączaniem timerów, ale teraz niestety sobie to odpuszczę bo nie stanowi to priorytetowego problemu. Dziękuję za zaangażowanie i pomoc
REKLAMA