Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[avr-gcc, ATmega16] regeler 3f + UART + encoder = problem

08 Wrz 2005 15:33 2475 5
  • Poziom 30  
    Witam...

    To będzie sporo pisania więc trzymajcie się... ;)
    Code:
     
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <inttypes.h>
    #include <stdlib.h>

    #define F_CPU   8000000 //wewnętrzny generato na 8Mhz

    #define PARITY_NONE 0
    #define PARITY_EVEN (1<<UPM1)
    #define PARITY_ODD ((1<<UPM1)|(1<<UPM0))
    #define STOP_BITS_1 0
    #define STOP_BITS_2 (1<<USBS)
    #define DATA_BITS_5 0
    #define DATA_BITS_6 (1<<UCSZ0)
    #define DATA_BITS_7 (1<<UCSZ1)
    #define DATA_BITS_8 ((1<<UCSZ1)|(1<<UCSZ0))
    #define DATA_BITS_9 ((1<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0))


     volatile unsigned char t[6] = {0x05, 0x21, 0x28, 0x0A, 0x12, 0x14}, rpm=0; 
     volatile unsigned int i=0;

    volatile uint16_t timing=58000;

    void USART_Init(void)
    {
     UBRRH = 0x00;
     UBRRL = 0x0C;
     UCSRB = (1 << RXCIE) | (1 << RXEN) | (1 << TXEN);
     UCSRC = (1 << URSEL) | DATA_BITS_8 | PARITY_NONE | STOP_BITS_1;
    }

    void Timer_Init (void)
    {
     TCCR1A = 0b00000000;
     TCCR1B = 0b00000010;
     TIMSK |= (1 << TOIE1);
    }

    void Start_Clock(void) // inicjalizacja timer2 do pracy z kwarcem 32kHz
    {
     ASSR = (1 << AS2); //timer2 ustawiony na prace asynchroniczną z kwarcem 32kHz
     TCCR2 = (1 << CS22) | (1 << CS20); //| (1 << CS20); //prescaler na 128 => przepełnienie co 1s
     TIMSK |= (1 << TOIE2); //aktywne przerwanie przepełnienia od timer2
    }

    void Start_Count(void)
    {
     TCCR0 = (1 << CS02) | (1 << CS01);// | (1 << CS00);
     TCNT0 = 219;
     TIMSK |= (1 << TOIE0);
    }


    int USART_Transmit( unsigned char data )
    {
    while ( !( UCSRA & (1<<UDRE)) );/* Wait for empty transmit buffer */
    UDR = data;/* Put data into buffer, sends the data */
    return 0;
    }



    int main(void)
    {
     DDRA = 0b11111111; 
     cbi(DDRD,PD0);
     cbi(DDRD,PD1);
    // sbi(DDRB,PB2);
     
     USART_Init();
     Start_Clock();
     Start_Count();
     Timer_Init();
     sei();
     
     for(;;) {}

     
     return(0);
    }


    SIGNAL (SIG_OVERFLOW1)
    {
     //cli();
     PORTA = t[i];
     if(i==5) i=0; else i++;
     
     if(timing > 63000)
     {
      if(bit_is_set(PIND, PD0))
       {if(timing < 65535) timing++;}
       
      if(bit_is_set(PIND, PD1))
       {if(timing > 63000) timing--;}
     }
     else timing+=10;
     
     TCNT1 = timing;
     //sei();
    }

    SIGNAL (SIG_OVERFLOW2) // obsługa przerwania od timer2 => przepełnienie
    {
     cli();
     //PORTB ^= (1 << PB2);
     USART_Transmit(rpm);
     rpm=0;
     sei();
    }

    SIGNAL (SIG_OVERFLOW0)
    {
     rpm++;
     TCNT0 = 219;
    }

    Napisałem program który początkowo zajmował się tylko regulacją obrotów silnika 3f (przerobiony silnik z cd-romu)...
    To nic więcej jak funkcje Timer_Init i obsługa przerwania SIGNAL (SIG_OVERFLOW1)...
    Wszystko było ok ale potrzebowałem sprawdzić jakie obroty ma silnik...
    Więc wiziąłem starą myszkę, troche elementów wywaliłem i została mi dioda nadawcza + odbiorcza i rolka z tarczą (36 nacięć, co 1°) czyli generalnie prosty encoder...
    Do programu dorzuciłem UARTa i RTC...
    "Encoder" zasilam z osobnego źródła (3,6V aku)...
    Całość miała działać tak...
    Timer1 + przerwanie zajmuje się silnikiem...
    Timer2 + 32,7kHz + przerwanie co 1s daje czas...
    Timer0 + zewnętrzny sygnał z "encodera" na wejście T0 zlicza do 36 i w przepełnieniu zwiększa rpm ;)...

    No i pojawiły się problemy...
    1. Przyciski zmieniające częstotliwość nie działają poprawnie...
    tzn. na zwiększanie (PD0) nie reaguje wcale a na zminiejszanie (PD1) poprostu się zatrzymuje całkiem...
    2. Wygląda na to że nie zlicza ipulsów albo źle wysyła, nie wiem...
    Zawsze dostaje 0...
    Jeżeli na stałe wstawie za rpm np. 12 to wysyła to w kółko bez błedów...

    Proszę o jakieś sugestie co może być nie tak...
  • Poziom 32  
    Może to nie robi problemu ale wykonywanie w przerwaniu transmisji usarta to chyba przegięcie. Przecież on ma swoje przerwanie a tak to niepotrzebnie zatrzymuje kolejkę przerwań i może coś pominąć.
  • Poziom 30  
    Owszem uart ma przerwanie ale od odbioru...
    A ja wysyłam...
    Pozatym w ten sposób do kompa idzie nowy odczyt co sekundę a w petli głównej leciało by w kółko...
    No można zrobić to tak żeby co jakiś okres szła transmisja ale to znaczeni więcej kombinowania...
  • Poziom 32  
    A wektor 14 to od czego niby jest ? Od babci ?:D
  • Pomocny post
    Poziom 19  
    Hmmmm....

    Po co włączyłeś odbiornik w UART, skoro go nie wykorzystujesz? A na dodatek włączyłeś przerwanie od odbiornika!
    UCSRB = (1 << RXCIE) | (1 << RXEN) | (1 << TXEN);
    Mało tego... TX w uracie jest na tej samej końcówce co PD1, więc jak to możliwe, że po włączeniu nadajnia w UART wogóle program reaguje na tą końcówkę?
    PD0 to końcówka RX odbiornika, więc jak masz tam normalnie niski stan, to odniornik wciąż wykrywa to jak bit startu i co chwilę będzie skok do obsługi przerwania... którego nie ma...
  • Poziom 30  
    Ooooo...
    Dzięki Ci dobry człowieku...
    Wiedziałem, że coś namotałem...
    Co do uarta to przyznaje się bez bicia, że skopiowałem z innego swojego programu konfigurację uarta i tylko obsługę przerwania wywaliłem... :|
    No tak nie sprawdziłem wszystkiego dokładnie a lenistwo nie połaca...

    Jeszcze raz dzięki... :D