Опубликовано 2010-05-07 11:30:31 автором Ruslan

Передача даних через UART в AVR. Урок AVR 9


Для зв'язку мікроконтролера зі своїм старшим братом - ПК - можна використовувати інтерфейси передачі даних , але так як я навчальний курс з AVR намагаюся побудувати на мікроконтролері mega8 , то краще за все для зв'язку з ПК використовувати інтерфейс USART . Ні, можна, звичайно , заюзать і USB , але USART в mega8 реалізований апаратно , а це означає , що нам не доведеться вручну реалізовувати логіку передачі даних , ми просто запишемо дані в регістр , а самим процесом відправки вже буде рулити МК апаратно .
Протокол UART ( Universal asynchronous receiver / transmitter ) є одним з найпоширеніших протоколів передачі даних між пристроями. У Atmega8 один USART , виведений він на ніжки PD0 - Rx , receiver (приймач ) і PD1 - Tx , transmitter ( передавач ) . Вивод Usart у mega8 Давайте спробуємо передати дані з пк . Коли з пк приходитиме 1 , то світлодіод світитиметься , коли 0 , то гаснути . Схема виглядає наступним чином: Uart у proteus Далі нам потрібно написати програму :
У CodeVision AVR створюємо новий проект , частоту мк встановлюємо на 8 мегагерц , далі переходимо у вкладку USART , там включаємо приймач і передавач Uart у proteus Приберемо все зайве і допишемо свій код

 # include <mega8.h>  
 void main ( void )  
 {  
 char date = 0 ;  
   PORTC = 0x00;  
 DDRC = 0x01;    
 // USART initialization  
 // Communication Parameters : 8 Data , 1 Stop , No Parity  
 // USART Receiver : On  
 // USART Transmitter : On  
 // USART Mode : Asynchronous  
 // USART Baud Rate : 9600  
 UCSRA = 0x00;  
 UCSRB = 0x18 ;  
 UCSRC = 0x86 ;  
 UBRRH = 0x00;  
 UBRRL = 0x33 ;  
   while ( 1 )  
 {  
 date = UDR ;  
  
 if ( date == '1 ' ) PORTC.0 = 1 ;  
 if ( date == '0 ') PORTC.0 = 0 ;  
 } ;  
 }  
 

У AVR є регістр UDR . Насправді , це два різних регістра , які мають одну адресу . Коли записуємо дані , то вони потрапляють в регістр передавача , а коли читаємо - беруться з регістра приймача. Для відправки ми просто записуємо дані в цей регістр і вони полетять до приймача , а якщо нам щось прийшло - зчитуємо їх з регістра .
Стежити за UART вручну не потрібно , все обслуговування можна повісити на переривання. Коли до нас приходять дані , генерується переривання по завершенню прийому , а коли дані відправляться - викликається переривання по спустошенню
Компілюємо програму , закидаємо в мк в Протеус . Для відсилання даних з терміналу потрібно поставити галочку біля : передача даних через uart Вводимо одиничку - світлодіод світиться uart в Proteus Вводимо 0 - світлодіод гасне передача даних через uart в Proteus

Робота на переривання

Як ви помітили , наша програма нескінченно очікує приходу байта. Так робити недоцільно , тому що головний цикл завантажений прийомом і передачею даних через uart і більше нічого робити не може. Звичайно , можна не зациклюватися , а наприклад періодично раз в 10 мілісекунд перевіряти , чи не прийшли нам дані , в решту часу робити щось своє . Але тоді , якщо передача йде на великій швидкості , можна припустити байти . Найкраще цю малину замутити на переривання : прийшли дані - викликався обробник переривання і все. Для цього в CodeWizard AVR у вкладці USART потрібно поставити галочку біля Rx Interrapt

uart на прериваніях
генер код , і отримуємо

 # include <mega8.h>  
 # ifndef RXB8  
 # define RXB8 1  
 # endif    
 # ifndef TXB8  
 # define TXB8 0  
 # endif    
 # ifndef UPE  
 # define UPE 2  
 # endif    
 # ifndef DOR  
 # define DOR 3  
 # endif    
 # ifndef FE  
 # define FE 4  
 # endif    
 # ifndef UDRE  
 # define UDRE 5  
 # endif    
 # ifndef RXC  
 # define RXC 7  
 # endif    
 # define FRAMING_ERROR ( 1 < < FE)  
 # define PARITY_ERROR ( 1 < < UPE )  
 # define DATA_OVERRUN ( 1 < < DOR )  
 # 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 ;  
 } ;  
 } ;  
 if ( data == '1 ' ) PORTC.0 = 1 ;  
 if ( data == '0 ') PORTC.0 = 0 ;  
 }  
  
 # include <stdio.h>    
 void main ( void )  
 {  
 // Port C initialization  
 PORTC = 0x00;  
 DDRC = 0x01;    
 // USART initialization  
 // Communication Parameters : 8 Data , 1 Stop , No Parity  
 // USART Receiver : On  
 // USART Transmitter : Off  
 // USART Mode : Asynchronous  
 // USART Baud Rate : 9600  
 UCSRA = 0x00;  
 UCSRB = 0x90 ;  
 UCSRC = 0x86 ;  
 UBRRH = 0x00;  
 UBRRL = 0x33 ;  
   / / Global enable interrupts  
 # asm ( " sei " )  
   while ( 1 )  
 {  
 } ;  
 }  
 

Тут codewizard згенерував різні перевірки парності і буфер для запису даних , які прийшли. Нам для того , щоб засвітити світло діод, все це не потрібно , тому видаляємо зайве, і отримуємо

 # include <mega8.h>  
 # include <stdio.h>  
 // USART Receiver interrupt service routine   interrupt [ USART_RXC ] void usart_rx_isr ( void )  
 {  
 char data ;  
 data = UDR ;  
  
 if ( data == '1 ' ) PORTC.0 = 1 ;  
 if ( data == '0 ') PORTC.0 = 0 ;  
 }  
  
 void main ( void )  
 {  
 // Port C initialization  
 PORTC = 0x00;  
 DDRC = 0x01;  
   // USART initialization  
 // Communication Parameters : 8 Data , 1 Stop , No Parity  
 // USART Receiver : On  
 // USART Transmitter : Off  
 // USART Mode : Asynchronous  
 // USART Baud Rate : 9600  
 UCSRA = 0x00;  
 UCSRB = 0x90 ;  
 UCSRC = 0x86 ;  
 UBRRH = 0x00;  
 UBRRL = 0x33 ;  
   // Global enable interrupts  
 # asm ( " sei " )  
  
 while ( 1 )
   {  
 } ;  
 }  
 

Як бачите , головний цикл вільний . Тепер нам не потрібно регулярно перевіряти , а чи не прийшли дані по uart . Коли прийде байт по uart , то викличеться обробник переривання , і ми вже в ньому зробимо необхідні нам дії .

Переходимо до заліза
Якщо у вашого пк є COM порт , то вам для сполучення з мікроконтролером знадобиться перетворювач рівнів ТТЛ - RS232. Його легко зібрати на мікросхемі MAX232 . Він потрібен , тому що напруга на виході даних з COM- порту ПК:
  • логічна "1" від -5 до -15 вольт
  • логічний " 0 " від +5 до +15 вольт
а в мк
    < li > логічна "1" від 1,8 до напруги живлення вольт
  • логічний \ " 0 \ " від 0 до 1,3 вольт
Схема підключення RS232 приблизно така Схема підключення RS232 приблизно такая Якщо у вашого ПК немає СОМ - портів , то потрібно юзати адаптер на мікросхемі FT232 - він підключається до USB вашого ПК і в системі з'являється віртуальний СОМ порт , а на виводах FT232 відповідні сигнали UART . Схема підключення RS232 приблизно такая

Комментарии - (2)

Добавить комментарий

Для отправки комментария вы должны авторизоваться.