|
| |||||||
|
Опубликовано 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-порта ПК:
Если у вашего ПК нет СОМ-портов, то нужно юзать адаптер на микросхеме FT232 - он подключается к USB вашего ПК и в системе появляется виртуальный СОМ порт, а на выводах FT232 соответствующие сигналы UART.
Комментарии - (2)
Добавить комментарийДля отправки комментария вы должны авторизоваться. |
|||||||