По просьбам трудящихся, было решено продолжить урок по передаче данных через UART. Основной проблемой, на мой взгляд, при общении двух микроконтроллеров является прием данных.
В качестве примера возьмем две Atmega8. Задача первого микроконтроллера переслать массив символов, задача второго принять их и вывести на экран LCD дисплея. Схема будет выглядеть так:
Код передающего микроконтроллера будет выглядеть так:
#include <mega8.h> #include <stdio.h> void main(void) { char massiv[5]={'h','e','l','l','o'}; bit on=0; int i=0; PORTC=0x01; DDRC=0x00; UCSRA=0x00; UCSRB=0x08; UCSRC=0x86; UBRRH=0x00; UBRRL=0x33; while (1) { if(PINC.0==0 && on==0) { UDR=massiv[i]; i++; if(i>4) { i=0; } on=1; } if(PINC.0!=0) { on=0; } }; } |
При нажатии на кнопку передается 1 элемент массива символов, при повторном нажатии — следующий символ и т.д. В результате должен передаться массив «hello». Переменная on нужна для исключения дребезга кнопки (для передачи следующего символа нужно отпустить кнопку и затем нажать).
Второй микроконтроллер принимает данные в прерывании. Код прерывания, CodeWizard создает автоматически. Обработка достаточно большая, пугаться не стоит. Отдельно посмотреть данный код можно выставив галочки как показано на рисунке и щелкнуть File — Program Preview.
Разберемся с нашим алгоритмом, для нас самое главное это само прерывание:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | // 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; }; }; //здесь мы помещаем приходящие данные в массив, заранее известно количество //принимаемых символов = 5 uart_data[i]=data; i++; if(i>4) { i=0; } } |
Прием производится в прерывании, т.е. как только символ пришел срабатывает прерывание — символ записывается в первый элемент массива, инкрементируется счетчик. В следующее прерывание приходит следующий символ и т.д. Сразу оговорюсь, что количество приходящих символов заранее известно.
Теперь осталось только вывести результат на экран, для этого в цикле выводятся все символы на экран.
1 2 3 4 5 6 7 8 | while(j<5) // цикл пока все 5 символов не будут выведены на экран { lcd_gotoxy(j,0); //выбираем место куда будет выводиться символ sprintf(lcd_buffer,"%c",uart_data[j]); //преобразовываем символ в понятный для дисплея вид lcd_puts(lcd_buffer); //выводим на экран j++; //увеличить счетчик } j=0; // обнулить счетчик |
Схема и прошивка доступны тут
Добрый день! Взял передающй микроконтроллер и подключил его к Bluetooth модулю hc05 приконектился с комютера через USB Bluetooth модуль на модуль HC05. Rx микроконтроллера соединил с Tx BT модуля и Tx с Rx. Подал и питание.
Попробовал с терминала Tera Term на компе конектится на порт где висит Bluetooth. Конектится все ок. Но никак не принимаю данные. Пробовал менять скорость на терминале. Как правильно настроить передачу и синхронизироваться??
В протеус все отлично работает. Получаю “Hello” на терминале .
попробуйте отдельно проверить bt и отдельно мк, универсального рецепта нет, может быть проблема с драйверами в винде, может скорости разные может земли не соединены и тп
А как можно проверить передается ли вообще сигнал с Rxd и Txd?
И еще один вопрос UART Atmega8 настроен на скорости 9600. И частота тактирования 8 Mhz
они же тоже должны играть роль в синхорнизации ? Может надо фюзами поиграть ?
и фьюзы и частота и предделители — все играет роль. проверить можно если замкнуть их между собой, должны увидеть эхо
Добрый вечер! Передаю температуру в терминал с 2 датчиков ds18b20 через микроконтроллер.
Скажите пожалуйста, а как бороться с помехами и ошибками?
У меня фюзы прошиты на 8 MHz регистры устанавливал так:
UCSRA=0x00;
UCSRB=0x48;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;
Проволоки вроде короткие и земли соединенны. Выводит на терминал вот эти значения
23 151 23 151 23 23 151 23 151 151 151 23
151 23 23 151 23 151 23 23 23 23 151 151
151 151 151 23 151 151 151 151 151 23 151 23
23 23 23 151 151 151 23 151 23 151 151 23
Правильная температура вроде 23 а другие ошибки…
сложно сказать, может вы датчик часто опрашиваете
Датчики опрашиваются каждые 500ms. При таких настроек регистров все исправилось и ошибок больше нет.
UBRRH=0x00;
UBRRL=0x34;
Добрый день.Прошу помощи по UART.
Пищу так :
if (PINB.0==0){delay_ms(2); sec|=1<<0; }else{sec&= ~(1 << 0);}
if (PINB.1==0){delay_ms(2); sec|=1<<1; }else{sec&= ~(1 << 1);}
if (PINB.2==0){delay_ms(2); sec|=1<<2; }else{sec&= ~(1 << 2);}
if (PINB.3==0){delay_ms(2); sec|=1<<3; }else{sec&= ~(1 << 3);}
UDR=sec;
В протеусе все нормально а вот в живую ошибка . 01 03 0F
0F всегда выскакивает когда любую третью кнопку нажимаю????
В чем может быть проблема????
Уважаемый Админ! Объясните, пожалуйста, почему на микроконтроллере ATMega64a UART0 «заводится» без проблем, а UART1 — нужны «танцы с бубнами»? Пользуюсь CVAVR версия 3.12.
Я честно пытался несколько дней настроить UART1 на прием и до сих пор не могу сообразить, как это сделать. Не реагирует, зараза… CVAVR выдает кучу настроек.
Плюнул. Решил сделать на UART0 — всё отлично пошло с первого пинка.
Сложно сказать, нужно читать даташит что именно не так с уартом1. Я помню что в старших мегах были приколы с уартом, но за давностью времени уже все забылось.