| |||||||
Опубликовано 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 (передатчик). Давайте попробуем передать данные с пк. Когда с пк будет приходить 1, то светодиод будет светиться, когда 0, то гаснуть. Схема выглядит следующим образом:
Далее нам нужно написать программу:
Уберем все лишнее и допишем свой код #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.
На самом деле, это два разных регистра, которые имеют один адрес. Когда записываем данные, то они попадают в регистр передатчика, а когда читаем - берутся из регистра приемника. Для отправки мы просто записываем данные в этот регистр и они улетят к приемнику, а если нам что-то пришло - считываем их из регистра.
Вводим единичку - светодиод светится
Вводим 0 - светодиод гаснет
Работа на прерыванияхКак вы заметили, наша программа бесконечно ожидает прихода байта. Так делать нецелесообразно, потому что главный цикл загружен приемом и передачей данных через uart и больше ничего делать не может. Конечно, можно не зацикливаться, а например периодически раз в 10 милисекунд проверять, не пришли ли нам данные, в остальное время делать что-то своё. Но тогда, если передача идет на большой скорости, можно пропустить байты. Лучше всего эту малину замутить на прерываниях: пришли данные - вызвался обработчик прерывания и все. Для этого в CodeWizard AVR во вкладке USART нужно поставить галочку возле Rx InterraptГенерим код, и получаем #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-порта ПК:
Комментарии - (2)
Добавить комментарийДля отправки комментария вы должны авторизоваться. |