sobota, 1 października 2016

[4] Atmega328 - Komunikacja przez UART

Ten post chciałbym poświęcić na przygotowanie komunikacji poprzez UART.

Jeśli chodzi o wysyłanie danych to do tego celu wykorzystana zostanie następująca funkcja.

  1. void SEND_BYTE(uint8_t b8_data)
  2. {
  3.     while(d_SEND_DATA_COMPLETE) { ; }
  4.     UDR0 = b8_data;
  5. }



Powyższa funkcja pozwala na przesłanie 8 bitowych danych przez interfejs uart. Pętla while czeka aż dane zostaną przesłane. Do tego celu wykorzystany zostaje odpowiednia defincja:

  1. #define d_SEND_DATA_COMPLETE !(UCSR0A&(1<<UDRE0))

Gdy dane zostaną wprowadzone do rejestru UDR0, który odpowiada za przesłanie danych, to zostają one automatycznie wysłane poprzez UART. Do sprawdzania czy dane zostały przesłane wykorzystywane jest sprawdzanie flag rejestrów UDRE0 oraz UCSR0A. Dzięki nim można się dowiedzieć czy buffor został już opróżniony.

Dane można wysłać przez tą funkcję w postaci liczbowej bądź jako znak. W drugim przypadku należy ją wtedy podać w pojedynczych cudzysłowach np. 'a', '4', 't'.

W przypadku wysłania grupy danych to należy wpisać je do buffora i przesłać każdy znak z niego pojedynczo:

  1. void Write_Buff(unsigned char *buff, uint8_t lenght)
  2. {
  3.   uint8_t i = 0;
  4.   for(i=0;i<lenght;i++)
  5.   {
  6.     USART0SendByte(buff[i]);
  7.   }
  8. }

Kolejna funkcja pozwoli na odebranie danych 8 bitowych przez port szeregowy. W tym przypadku należy odczekać na opróżnienie buffora odbierającego. Należy odczekać na wystawienie flagi RXC0, która poinformuje o zakończeniu odbierania danych. Po odebraniu dane zostaną wprowadzone do rejestru UDR0.

  1. #define d_RECEIVE_DATA_COMPLETE !(UCSR0A&(1<<RXC0))
  2.  
  3. uint8_t USART0ReceiveByte()
  4. {
  5.     while(d_RECEIVE_DATA_COMPLETE){ ; }
  6.     return UDR0;
  7. }

Włączenie interfejsu odbywa się w następujący sposób:

  1. void USART_INITIALIZATION(void)
  2. {
  3.     UBRR0H = (uint8_t)(UBRR_VALUE_WRITE>>8);
  4.     UBRR0L = (uint8_t)UBRR_VALUE_WRITE;
  5.     UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);  
  6.     UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
  7. }

Na samym początku wysyłane są dane do rejestru UBRR0H oraz UBRR0L. Najpierw 8 bitów wyższych do rejestru high a następnie 8 niższych. Obliczenie danych wygląda następująco:

  1. #define BAUDRATE 9600

  1. #define UBRR_VALUE (((F_CPU / (BAUDRATE * 16UL))) - 1)

Jako BAUDRATE podane zostaje aktualna wartość np. 9600. Pozostałe wartości zostały pobrane z bibliotek.

Następna linijka pozwala na ustawienie formatu. W tym przypadku wybrane zostało 8 bitów, wyłączona kontrola parzystości oraz jeden bit stopu.

Poniżej cały program:

  1. #include <avr/io.h>
  2. #define BAUDRATE 9600
  3. #define UBRR_VALUE_WRITE (((F_CPU / (BAUDRATE * 16UL))) - 1)
  4. #define d_SEND_DATA_COMPLETE !(UCSR0A&(1<<UDRE0))
  5. #define d_RECEIVE_DATA_COMPLETE !(UCSR0A&(1<<RXC0))
  6.  
  7. void USART_INITIALIZATION(void);
  8. void SEND_BYTE(uint8_t b8_data);
  9. uint8_t USART0ReceiveByte();
  10. void Write_Buff(unsigned char *buff, uint8_t lenght);
  11.  
  12. int main (void)
  13. {
  14.     unsigned char buff[5];
  15.    
  16.     USART_INITIALIZATION(void)
  17.  
  18.     buff[0] = '1';
  19.     buff[1] = 'o';
  20.     buff[2] = '3';
  21.     buff[3] = 'u';
  22.     buff[4] = '\n';
  23.        
  24.     *znak = '1';
  25.     while(1)
  26.     {
  27.         SEND_BYTE(0x100);
  28.         SEND_BYTE('r');
  29.         SEND_BYTE('\n');
  30.         Write_Buff(buff, 0x05);
  31.         _delay_ms(100);
  32.     }
  33. }
  34.  
  35. void USART_INITIALIZATION(void)
  36. {
  37.     UBRR0H = (uint8_t)(UBRR_VALUE_WRITE>>8);
  38.     UBRR0L = (uint8_t)UBRR_VALUE_WRITE;
  39.     UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);  
  40.     UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
  41. }
  42.  
  43. void SEND_BYTE(uint8_t b8_data)
  44. {
  45.     while(d_SEND_DATA_COMPLETE) { ; }
  46.     UDR0 = b8_data;
  47. }
  48.  
  49. uint8_t USART0ReceiveByte()
  50. {
  51.     while(d_RECEIVE_DATA_COMPLETE){ ; }
  52.     return UDR0;
  53. }
  54.  
  55. void Write_Buff(unsigned char *buff, uint8_t lenght)
  56. {
  57.   uint8_t i = 0;
  58.   for(i=0;i<lenght;i++)
  59.   {
  60.      SEND_BYTE(buff[i]);
  61.   }
  62. }