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 + RS232 i odbierania 2 bajtów

bartosz.kolo 06 Sie 2009 16:04 1715 4
REKLAMA
  • #1 6863626
    bartosz.kolo
    Poziom 10  
    Witam wszystkich

    Robię urządzenie oparte na mikrokontrolerze ATmega16. Do portów B i C podłączone są linie wejściowe sterowanego źródła prądowego. Zadając odpowiednie kombinacje na portach (wejście ŹP ma 12 bitów rozdzielczości) uzyskujemy odpowiedni prąd wyjściowy źródła. Wykorzystuje 8 wyjść portu B i 4 wyjścia portu C, mam dzięki temu 4096 poziomów natężenia prądu. Od strony komputera całością steruje LabView, wysyłając na COM1 kolejno po sobie dwa bajty - bardziej i mniej znaczący.

    W jaki sposób przechwycić na ATmedze pierwszy i drugi bajt, używając przerwań? Programuję w C, do tej pory, przy jednym bajcie danych nie było problemów, jednak umożliwia on zadanie jedynie 256 poziomów natężenia prądu.

    Dzięki za podpowiedzi
  • REKLAMA
  • #2 6863834
    _Robak_
    Poziom 33  
    Bufor cykliczny. Gotowy kod masz tutaj:
    https://www.elektroda.pl/rtvforum/topic1327746.html
    Jesli zalozysz ze nigdzie zaden pakiet nie zginie i inne idealne warunki, mozesz w przerwaniu skladac dwa bajty do jednej zmiennej. Ale wystarczy ze stracisz jeden bajt i bedziesz laczyc drugi bajt poprzedniej ramki z pierwszym kolejnej.
  • REKLAMA
  • #3 6867768
    rpal
    Poziom 27  
    np tak: źródło jest wygenerowanie automatycznie przez Codevision ale jak się przyjżysz to załapiesz o co chodzi :) i będzie to dla ciebie jakaś pomoc dla własnych modyfikacji
    
    #include <mega32.h>
    
    #define RXB8 1
    #define TXB8 0
    #define UPE 2
    #define OVR 3
    #define FE 4
    #define UDRE 5
    #define RXC 7
    
    #define FRAMING_ERROR (1<<FE)
    #define PARITY_ERROR (1<<UPE)
    #define DATA_OVERRUN (1<<OVR)
    #define DATA_REGISTER_EMPTY (1<<UDRE)
    #define RX_COMPLETE (1<<RXC)
    
    // USART Receiver buffer
    #define RX_BUFFER_SIZE 8
    char rx_buffer[RX_BUFFER_SIZE];
    
    #if RX_BUFFER_SIZE<256
    unsigned char rx_wr_index,rx_rd_index,rx_counter;
    #else
    unsigned int rx_wr_index,rx_rd_index,rx_counter;
    #endif
    
    // This flag is set on USART Receiver buffer overflow
    bit rx_buffer_overflow;
    
    // USART Receiver interrupt service routine
    interrupt [USART_RXC] void usart_rx_isr(void)
    {
    char status,data;
    status=UCSRA;
    data=UDR;
    if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
       {
       rx_buffer[rx_wr_index]=data;
       if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
       if (++rx_counter == RX_BUFFER_SIZE)
          {
          rx_counter=0;
          rx_buffer_overflow=1;
          };
       };
    }
    
    #ifndef _DEBUG_TERMINAL_IO_
    // Get a character from the USART Receiver buffer
    #define _ALTERNATE_GETCHAR_
    #pragma used+
    char getchar(void)
    {
    char data;
    while (rx_counter==0);
    data=rx_buffer[rx_rd_index];
    if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
    #asm("cli")
    --rx_counter;
    #asm("sei")
    return data;
    }
    #pragma used-
    #endif
    
    // USART Transmitter buffer
    #define TX_BUFFER_SIZE 8
    char tx_buffer[TX_BUFFER_SIZE];
    
    #if TX_BUFFER_SIZE<256
    unsigned char tx_wr_index,tx_rd_index,tx_counter;
    #else
    unsigned int tx_wr_index,tx_rd_index,tx_counter;
    #endif
    
    // USART Transmitter interrupt service routine
    interrupt [USART_TXC] void usart_tx_isr(void)
    {
    if (tx_counter)
       {
       --tx_counter;
       UDR=tx_buffer[tx_rd_index];
       if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
       };
    }
    
    #ifndef _DEBUG_TERMINAL_IO_
    // Write a character to the USART Transmitter buffer
    #define _ALTERNATE_PUTCHAR_
    #pragma used+
    void putchar(char c)
    {
    while (tx_counter == TX_BUFFER_SIZE);
    #asm("cli")
    if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
       {
       tx_buffer[tx_wr_index]=c;
       if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
       ++tx_counter;
       }
    else
       UDR=c;
    #asm("sei")
    }
    #pragma used-
    #endif
    
    // Standard Input/Output functions
    #include <stdio.h>
    
    // Declare your global variables here
    
    void main(void)
    {
    // Declare your local variables here
    
    // Input/Output Ports initialization
    // Port A initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTA=0x00;
    DDRA=0x00;
    
    // Port B initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTB=0x00;
    DDRB=0x00;
    
    // Port C initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTC=0x00;
    DDRC=0x00;
    
    // Port D initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTD=0x00;
    DDRD=0x00;
    
    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: Timer 0 Stopped
    // Mode: Normal top=FFh
    // OC0 output: Disconnected
    TCCR0=0x00;
    TCNT0=0x00;
    OCR0=0x00;
    
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: Timer 1 Stopped
    // Mode: Normal top=FFFFh
    // OC1A output: Discon.
    // OC1B output: Discon.
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    TCCR1A=0x00;
    TCCR1B=0x00;
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;
    
    // Timer/Counter 2 initialization
    // Clock source: System Clock
    // Clock value: Timer 2 Stopped
    // Mode: Normal top=FFh
    // OC2 output: Disconnected
    ASSR=0x00;
    TCCR2=0x00;
    TCNT2=0x00;
    OCR2=0x00;
    
    // External Interrupt(s) initialization
    // INT0: Off
    // INT1: Off
    // INT2: Off
    MCUCR=0x00;
    MCUCSR=0x00;
    
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x00;
    
    // USART initialization
    // Communication Parameters: 8 Data, 1 Stop, No Parity
    // USART Receiver: On
    // USART Transmitter: On
    // USART Mode: Asynchronous
    // USART Baud rate: 38400
    UCSRA=0x00;
    UCSRB=0xD8;
    UCSRC=0x86;
    UBRRH=0x00;
    UBRRL=0x19;
    
    // Analog Comparator initialization
    // Analog Comparator: Off
    // Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;
    
    // Global enable interrupts
    #asm("sei")
    
    while (1)
          {
          // Place your code here
    
          };
    }
    
  • REKLAMA
  • #4 6877337
    bartosz.kolo
    Poziom 10  
    Cześć

    Próbowałem kodu z przykładu kolegi Robaka, i niestety ale następuje "przesuwanie się" bajtów, czyli bajt mniej znaczący staje się czasami bajtem bardziej znaczącym i na odwrót. Nie mam za bardzo koncepcji, jak to obejść. Zależy mi na tym, aby w pamięci mikrokontrolera mieć dwuelementową tablicę (każdy element typu char), w której pierwszy element tablicy zawierałby bardziej znaczący bajt, a drugi element mniej znaczący bajt, z którego potem wyciągnę sobie 4 interesujące mnie bity. Wejście źródła prądowego jest 12-bitowe więc użyję wszystkich 8 bitów pierwszego elementu tablicy, i 4 bitów z drugiego elementu.

    Program w LabView mam napisany tak, że najpierw na COM1 wysyłany jest pierwszy bajt uformowany na podstawie zadajnika (knob), a po odczekaniu 500 ms następny bajt (mniej znaczący).

    Dzięki z góry za pomoc i sugestie
    ATMega16 + RS232 i odbierania 2 bajtów
  • Pomocny post
    #5 6879909
    flapo213
    Poziom 21  
    Witam. Moja propozycja jest następująca:

    1. Bufor kołowy jak już wcześniej koledzy zaznaczyli

    2. Format ramki telekomunikacyjnej <STX> <Byte1> <Byte2> <CRC> <ETX>

    I w tym momencie niczego nie pogubisz nie pozamienia Ci się baj pierwszy z drugim itd.

    Nie wiem czy tym jesteś to w stanie w labview tak zmodyfikować aby sobie stworzyć taką ramkę ale z punktu widzenie mikrokontrolera to najlepsze rozwiązanie.

    Pozdrawiam
REKLAMA