В этой статье мы рассмотрим процесс взаимодействия микроконтроллера ATmega8 (семейство AVR) и платформой Arduino Uno через последовательный порт. Взаимодействие будет осуществляться через универсальный асинхронный приемопередатчик (UART - Universal Asynchronous Receiver Transmitter) – это последовательный порт связи. Подобное взаимодействие часто бывает востребовано в различных системах на основе микроконтроллеров.
В этой статье мы рассмотрим общие принципы связи двух микроконтроллеров через универсальный асинхронный приемопередатчик (последовательный порт) и рассмотрим принцип действия программы, реализующей данное взаимодействие. Также данный вопрос рассмотрен в статье про взаимодействие двух AVR ATmega8 через UART.
В рассматриваемом проекте микроконтроллер ATmega8 используется в качестве передатчика, а Arduino Uno – в качестве приемника данных. При последовательной передаче мы будем последовательно передавать один бит за другим до тех пока весь байт данных не будет принят полностью. При рассматриваемом способе можно передавать до 10 бит за один раз, но мы в целях упрощения ограничимся передачей 8 бит.
Необходимые компоненты
Аппаратное обеспечение
- Микроконтроллер ATmega8 (купить на AliExpress).
- Плата Arduino Uno (купить на AliExpress).
- Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
- Конденсатор 1000 мкФ (соединенный по питанию) (купить на AliExpress).
- Конденсатор 100 нФ (соединенный по питанию) (купить на AliExpress).
- Светодиод (купить на AliExpress).
- Резистор 1 кОм (2 шт.) (купить на AliExpress).
- Кнопка.
- Источник питания с напряжением 5 Вольт.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Программное обеспечение
- Atmel Studio версии 6.1 (или выше).
- Progisp или flash magic (необязательно).
- ARDUINO NIGHTLY.
Работа схемы
Схема устройства приведена на следующем рисунке.
Прежде чем рассматривать работу схемы остановимся на принципах последовательной связи между микроконтроллерами. ATmega8 будет передавать данные, а Arduino Uno – принимать их.
Передачу данных между ATmega8 и Arduino Uno можно организовать и другими способами: через коммуникацию MASTER SLAVE, коммуникацию через JTAG, но в данной статье мы рассмотрим их коммуникацию через последовательный порт RS232. Для этого мы соединим контакт TXD (Transmitter) микроконтроллера ATmega8 с контактом RXD (Receiver) Arduino Uno.
Для осуществления успешного взаимодействия между ними необходимо установить следующие параметры последовательного порта:
- Восемь бит данных.
- Два стоповых бита.
- Нет бита проверки на четность.
- Бодовая скорость 9600 бод/с (поскольку двоичная связь, то можно измерять в бит/с).
- Асинхронный режим связи (часы (таймеры) обоих устройств не синхронизированы).
Таким образом, мы должны установить соответствующие значения регистров последовательного порта для микроконтроллера ATmega8. Эти значения следующие:
- Контакт TXD микроконтроллера должен быть задействован в качестве передатчика.
- Поскольку связь последовательная, то мы должны знать когда мы примем весь байт целиком. Поэтому мы не должны останавливать прием данных до тех пока не примем весь байт. Остановка приема данных после приема всего байта производится с помощью соответствующего прерывания.
- Данные передаются и принимаются в 8 битном режиме. Поэтому два символа должны пересылаться единовременно.
- Битов проверки на четность нет, в конце данных передается один стоповый бит.
Для осуществления всех этих функций соответствующим образом должны быть установлены регистры, отвечающие за работу последовательного порта. Рассмотрим этот вопрос более подробно. Состав этих регистров приведен на следующем рисунке.
DARK GREY (темно-серый, UDRE): (сторона передатчика) Этот бит не устанавливается в самом начале, но он используется во время работы последовательного порта чтобы проверить готов ли передатчик к передаче или нет. Более подробно использование этого бита рассмотрено в программе, приведенной ниже.
LIGHT GREY (светло-серый, RXC): (сторона приемника) Этот бит не устанавливается в самом начале, но он используется во время работы последовательного порта чтобы проверить готов ли приемник к приему данных или нет. Более подробно использование этого бита рассмотрено в программе.
VOILET (фиолетовый, TXEN): (сторона передатчика) Этот бит устанавливается чтобы разрешить передачу данных по последовательному порту на стороне передатчика.
RED (красный, RXEN): (сторона приемника) Устанавливается чтобы разрешить прием данных на контакте RXD микроконтроллера.
BROWN (коричневый, RXCIE): Этот бит должен быть установлен для того, чтобы после успешного приема данных генерировалось прерывание. При помощи установки этого бита мы будем знать что очередные 8 бит приняты правильно.
PINK (розовый, URSEL): Этот бит должен быть установлен перед тем как устанавливать другие биты в регистре UCSRC. Но после того как мы установим все необходимые биты UCSRC, бит URSEL должен быть сброшен.
YELLOW(желтый, UCSZ0,UCSZ1,UCSZ2): (сторона приемника и сторона передатчика). Эти три бита используются для выбора числа бит, которые мы будем передавать/принимать за одну попытку (передачи).
Как следует из приведенной таблицы для задействования 8 битного режима связи биты UCSZ0 и UCSZ1 необходимо установить в 1, а бит UCSZ2 – в 0. Мы должны сделать этот как на приемной, так и на передающей стороне.
ORANGE (оранжевый, UMSEL): (сторона приемника и сторона передатчика). Используется для выбора режима связи: синхронный или асинхронный.
Поскольку оба микроконтроллера используют свои собственные внутренние часы (таймеры) и никоим образом не синхронизируют их между собой, то мы должны в соответствии с приведенной таблицей установить бит UMSEL в 0 на обоих микроконтроллерах.
GREEN (зеленый, UPM1, UPM0): (сторона приемника и сторона передатчика). Эти два бита устанавливаются в зависимости от того каким образом мы хотим использовать проверку на четность.
Микроконтроллеры ATMEGA программируются таким образом, чтобы не использовать проверку на четность поскольку длительность передачи данных (8 бит) очень мала, поэтому можно предположить что и вероятность искажения данных (вероятность ошибки) будет очень мала. Поэтому мы должны в соответствии с приведенной таблицей установить биты UPM1 и UPM0 в 0 либо не трогать их вообще, потому что по умолчанию при инициализации микроконтроллера они сброшены.
BLUE (синий, USBS): (сторона приемника и сторона передатчика) Этот бит используется для выбора числа стоповых бит в процессе передачи.
Поскольку мы выбрали асинхронный режим связи, то для более точной (надежной) передачи и приема данных необходимо использовать 2 стоповых бита. Поэтому устанавливаем бит USBS в 1.
Бодовая скорость последовательного порта устанавливается с помощью соответствующего значения в регистре UBRRH. Это значение необходимо определять в зависимости от требуемой бодовой скорости и тактовой частоты микроконтроллера.
Для выбранных нами параметров (скорость 9600 бод/с, тактовая частота 1 МГц) в регистре UBRR необходимо установить значение 6.
Теперь рассмотрим приемную сторону. Для осуществления последовательной связи в Arduino Uno необходимо выполнить следующие две простые команды:
- Serial.begin(9600);
- receiveddata = Serial.read();
Команда ”Serial.begin(9600);” устанавливает бодовую скорость передачи для последовательного порта Arduino Uno, равную 9600 бод/с – это изменяемый параметр.
Теперь нам необходимо запрограммировать прием данных, в Arduino Uno это делается с помощью команды - “receiveddata = Serial.read();”. С помощью этой команды Arduino Uno принимает через последовательный порт число типа integer (целое).
Кнопка на схеме включена на передающей стороне, поэтому когда мы ее нажимаем, то 8 бит данных передаются передатчиком (ATmega8) и принимаются приемником (Arduino Uno). По окончании успешного приема данных Arduino Uno включает светодиод, подключенный к его контакту PD7.
Исходный код программы на языке C (Си) с пояснениями
Программа для рассматриваемой схемы взаимодействия ATmega8 и Arduino Uno через UART представлена следующим фрагментом кода на языке С (Си). Комментарии к коду программу поясняют принцип работы отдельных команд.
Программа на передающей стороне
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 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <avr/io.h> //заголовок чтобы разрешить контроль данных на контактах #define F_CPU 1000000UL //задание тактовой частоты микроконтроллера #include <util/delay.h> //заголовок чтобы задействовать функции задержки в программе int main(void) { DDRD |= 1 << PIND1;//контакт 1 portD устанавливаем на вывод данных DDRD &= ~(1 << PIND0);//контакт 0 portD устанавливаем на ввод данных PORTD |= 1 << PIND0; int UBBRValue = 6;// установка бодовой скорости 9600 бод/с //записываем это значение в верхнюю часть регистра (8 бит из 11) UBRRH = (unsigned char) (UBBRValue >> 8); // записываем оставшуюся часть регистра UBRRL = (unsigned char) UBBRValue; // задействуем передатчик и приемник UCSRB = (1 << RXEN) | (1 << TXEN); //устанавливаем 2 стоповых бита и 8-битную длину передаваемого символа UCSRC = (1 << USBS) | (3 << UCSZ0); while (1) { if (bit_is_clear(PINC,0))// если кнопка нажата { while (! (UCSRA & (1 << UDRE)) ); { UDR = 0b11110000;//когда передатчик готов посылаем 8 бит данных } _delay_ms(220); } } } |
Программа на приемной стороне
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
int receiveddata =0; void setup() { Serial.begin(9600);//serial data rate is set for 9600BPS pinMode(0,INPUT);//RXD pin is set for INPUT pinMode(1,OUTPUT); pinMode(7,OUTPUT);//PIN1,PIN7 are set for output } void loop() { if (Serial.available() > 0) //if data received is available { receiveddata = Serial.read();//read serial data available if (receiveddata == 0)//compare the data received { PORTD^=(1<<7);//id data matches toggle the LED. } } } |
Здравствуйте. С новым годом. Начал изучать программирование на Си, перед собой поставил некую задачу. НО что то не получается реализовать, не хватает знаний, не могли бы Вы согласиться стать мне учителем?
Добрый вечер. Я могу попробовать вам помочь немного, но в режиме обмена комментариями это просто будет не очень быстро. Можете задавать вопросы к любым материалам на сайте, а я буду пробовать на них отвечать. Я, как админ сайта, вижу все новые комментарии на сайте, поэтому один раз в день я смогу на них отвечать