7-2. Односторонняя беспроводная связь для 4-х линий управления.Связь реализована на двух микроконтроллерах
ATtiny13a (передача и приём) и двух блютуз-модулях
HC-05 и
HC-06. Формат данных соответствует формату данных
UART. Так как в
ATtiny13a нет аппаратного
UART, то передача и приём байта данных реализовано программно. Один микроконтроллер передаёт информацию о состоянии четырёх кнопок на блютуз-модуль
HC-05, второй - принимает данные с блютуз-модуля
HC-06, и информация о состоянии кнопок отображается на четырё светодиодах. В байте передаваемых данных используются четыре младших бита.
Для реализации и проверки данного решения необходимо собрать схему, запрограммировать микроконтроллеры, используя
*.hex файлы из архивов в конце сообщения и подготовить модуль
HC-05 (сделать его
Мастером), используя информацию в начальных сообщениях данной темы. Модуль
HC-06 используется с заводскими установками. Скорость передачи данных
9600 бит/сек.
7-2-1. Сборка на макетке :7-2-2. Электрические схемы :Передача. К выводам
PB0-PB3 подключены кнопки
K1-K4. Вывод
PB4 микроконтроллера подключён к входу
Rxd модуля
HC-05 через резистивный делитель
R2/R3 (для согласования уровней напряжения). Вход
KEY модуля
HC-05 подключён к GND (режим Передачи данных), к выводу
LED – токоограничивающее сопротивление
R4 и светодиод
VD для индикации соединения.
D1 – ATTiny13a;
R2-R4 – 1 кОм;
R1 – 10 кОм,
C1 – 0,1 мкФ.
Приём. Выход
Txd модуля
HC-06 подключён к выводу
PB4 микроконтроллера. К выводам
PB0-PB3 через сопротивления
R1-R4 подключены светодиоды индикации
VD1-VD4.
D1 – ATTiny13a;
R1-R4 – 1 кОм;
R5 – 10 кОм,
C1 – 0,1 мкФ.
7-2-3. Общие рекомендации:- Для записи в микроконтроллеры
*.hex файлов пользуйтесь любым доступным способом. Как вариант:
“Плата-переходник для ATtiny13” и
“Программатор USBasp с программой SinaProg”. - После записи программ в микроконтроллеры предварительную проверку связи между микроконтроллерами можно выполнить без установки модулей
HC-05 и
HC-06. Для этого необходимо напрямую соединить длинной перемычкой выводы
3 обоих микроконтроллеров.
- Вместо одного из микроконтроллеров в качестве передатчика или приёмника информации можно использовать программу
“ToothCommandSender_v1.01 для смартфонов с Андроид”; смартфон как управляющее устройство передаёт байт информации через блютуз-модуль на микроконтроллер или смартфон может принимать информацию через блютуз-модуль от микроконтроллера. В обоих случаях необходимо записать программу только в один микроконтроллер, а модуль
HC-06 или
HC-05 используются с заводскими установками.
Как видно на изображении
2 в программе есть возможность наблюдать принимаемым байт и передавать байт.
- В крайних случаях (ошибок в приёме) или проведения экспериментов по передаче-приёму байта код программы предполагает два варианта подстройки; в программе можно использовать константу
DISP или регистр
OSCCAL микроконтроллера. По работе с регистром
OSCCAL можно ознакомиться в
“Пример 19. Подстройка частоты RC-генератора и регистр OSCCAL” из темы
“Примеры для ATtiny13”.
7-2-4. Программа. Передача состояния переключателей (кнопок) c PB0-PB3:Программа работает на частоте
9,6 мГц, соответственно не забудьте снять фьюз-делитель на
8.
- Код: выделить все
//мк ATtiny13a
//F_CPU = 9600000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//Объявление типа unsigned char новым названием uchar (для дальнейшего использования в коде)
typedef unsigned char uchar;
#define TX PB4
#define SPEED 9600 //Скорость передачи
#define DISP 0 //Подстройка скорости; -30/+30
#define SEND_LOW PORTB &= ~(1 << TX) //Послать нуль
#define SEND_HIGH PORTB |= (1 << TX) //Послать единицу
#define ENABLE_TIMER \
TCCR0B &= 0b11111000 ;\
TCCR0B |= 0b00000010;
#define UNENABLE_TIMER \
TCCR0B &= 0b11111000; \
TCNT0 = 0;
uchar uart_buf = 0;
uchar bit_count = 0;
void send_byte(uchar byte);
static void send_bit(void);
//Обработчик прерывания таймера по совпадению
//ISR_BLOCK - блокирует глобальный флаг разрешения прерываний во время выполнения обработчика
ISR(TIM0_COMPA_vect, ISR_BLOCK) {
send_bit();
}
int main(void) {
DDRB = 0b00010000;
DDRB |= (1 << TX); //TX - выход (установка бита TX в регистре DDRB в 1)
PORTB = 0xFF;
//OSCCAL = 107; //???????????
TCCR0A = 0b00000010; //Режим - сброс по совпадению (CTC)
TCCR0B = 0b00000000;
TIMSK0 = (1 << OCIE0A); //Разрешение прерывания по совпадению с OCR0A
OCR0A = (F_CPU/8) / SPEED - 1 + DISP;
sei();
while(1) {
_delay_ms(20);
send_byte(~PINB & 0x0F);
}
}
void send_byte(uchar byte) {
ENABLE_TIMER;
SEND_LOW; //Стартовый бит
uart_buf = byte; //Буфер для отсылки байта
bit_count = 0; //счетчик отправленных битов
}
void send_bit(void) {
if(bit_count == 8) {
UNENABLE_TIMER;
SEND_HIGH; //Стоповый бит
}
else {
if(bit_is_set(uart_buf, 0))
SEND_HIGH;
else
SEND_LOW;
uart_buf >>= 1;
bit_count++;
}
}
Дмитрий Лиман (студент
НИЯУ МИФИ)
7-2-5. Программа. Приём с отображением состояния PB0-PB3 на светодиодах :Программа работает на частоте
9,6 мГц, соответственно не забудьте снять фьюз-делитель на
8.
- Код: выделить все
//мк ATtiny13a
//F_CPU = 9600000
#include <avr/io.h>
#include <avr/interrupt.h>
//Обьявление типа unsigned char новым названием uchar (для дальнейшего использования в коде)
typedef unsigned char uchar;
#define RX PB4 //RX - для приема
#define SPEED 9600 //Скорость передачи
#define DISP 0 //Подстройка скорости; -30/+30
/*
* Начать передачу с отсчета до половины периода.
* TCCR0B |= 0b00000010; - включить таймер с предделителем на 8
* PCMSK &= ~(1 << RX); - запретить прерывания PCINT для RX на время передачи
*/
#define RECEIVE_START \
OCR0A = ((F_CPU/8) / SPEED - 1 + DISP)/2; \
TCCR0B &= 0b11111000; \
TCCR0B |= 0b00000010; \
PCMSK &= ~(1 << RX);
/*
* Завершить передачу, отключить таймер, и включить прерывания PCINT на RX
*/
#define RECEIVE_END \
TCCR0B &= 0b11111000; \
TCNT0 = 0; \
PCMSK |= (1 << RX);
static void bit_received(void);
static void byte_received(uchar data);
ISR(PCINT0_vect, ISR_BLOCK) {
if(bit_is_clear(PINB, RX)) //описать в тексте
RECEIVE_START;
}
//Обработчик прерывания таймера по совпадению
//ISR_BLOCK - блокирует глобальный флаг разрешения прерываний во время выполнения обработчика
ISR(TIM0_COMPA_vect, ISR_BLOCK) {
bit_received();
}
int main(void) {
DDRB = 0b00001111; //PB1-PB4 - выходы
PORTB = 0b11110000;
GIMSK = (1 << PCIE);
PCMSK = (1 << RX); //PCINT на RX
//OSCCAL = 59; //?????????
TCCR0A = 0b00000010; //Режим - сброс по совпадению (CTC)
TCCR0B = 0b00000000;
TIMSK0 = (1 << OCIE0A); //Разрешение прерывания по совпадению с OCR0A
sei();
while(1) {}
}
void bit_received(void) {
static uchar bit_count = 0; //счетчик полученных битов
static uchar buf = 0; //буфер для записи полученной информации
if(bit_count == 0) { //Стартовый бит
if(bit_is_clear(PINB, RX)) { //Проверка, точно ли это был статовый бит
buf = 0;
bit_count++;
OCR0A = (F_CPU/8) / SPEED - 1 + DISP;
}
else { //Если все же помеха, то закончить прием
RECEIVE_END;
bit_count = 0;
}
}
else if(bit_count == 9) { //Стоповый бит, конец передачи байта
RECEIVE_END;
bit_count = 0;
byte_received(buf); //Обработка полученного байта
}
else { //Один из информационных битов
buf >>= 1;
if(bit_is_set(PINB, RX))
buf |= 0b10000000;
bit_count++;
}
}
void byte_received(uchar data) {
sei();
PORTB &= 0b111100000;
PORTB |= 0b00001111 & (data);
}
Дмитрий Лиман (студент
НИЯУ МИФИ)