14. Программа SerialRegUART – программный UART с выводом байта на регистр.Программа
SerialRegUART— приём по последовательному каналу байта (скорость
9600, по-умолчанию для модулей
HC-06) и вывод его через программный
SPI на регистр
74HC595.
Фьюзы —
3F-FF-7A. (Фьюзы микроконтроллера по-умолчанию
3F-FF-6A, меняется только состояние фьюза
LF-CKDIV8 — снимается делитель на 8 (
6A-->7A), частота мк
9,6 мГц).
- Код: выделить все
//MCU = ATtiny13a
//F_CPU = 9600000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
/* Подключение файла с различными обьявлениями макросов
* для дальнейшего использования их в программе.
*/
#include "definitions.h"
#define SPEED 100 //период опроса входного сигнала
void loadByte(uchar byte); // передать байт на регистр
static void byte_received(uchar data); // функция приема байта по UART
static void byteReceive(); // обработка принятого байта
// обработчик прерывания PCINT0
ISR(PCINT0_vect, ISR_BLOCK) {
if(bit_is_clear(PINB, RX)) {
RECEIVE_START; // запретить прерывания PCINT0 на время приёма
byteReceive(); // начать прием байта
}
}
int main(void) {
PORTB = 0b11101000;
DDRB = 0b00000111;
GIMSK = (1 << PCIE);
PCMSK = (1 << RX); //PCINT на RX
sei();
for(;;) {}
}
// передать байт на регистр
void loadByte(uchar byte) {
uchar i;
for(i = 0; i < 8; ++i) { // Последовательная передача 8 бит на регистр
if((byte & 0x80) == 0)
DATA_LOW;
else
DATA_HIGH;
SHIFT_CLOCK; // Тактирующий импульс после каждого бита
byte <<= 1;
}
}
// функция приема байта по UART
void byteReceive(void) {
sei();
uchar buf = 0; // байт в который будут последовательно записываться биты
uchar i;
_delay_us(SPEED/2);
if(bit_is_clear(PINB, RX)) // Проверка, точно ли это был стартовый бит
buf = 0;
else { // Если все же помеха, то закончить прием
RECEIVE_END;
return;
}
for(i = 0; i < 8; i++) { // Прием 8 бит по UART
_delay_us(SPEED);
buf >>= 1;
if(bit_is_set(PINB, RX))
buf |= 0b10000000;
}
_delay_us(SPEED);
RECEIVE_END;
byte_received(buf); // Обработка полученного байта
}
// обработка принятого байта
void byte_received(uchar data) {
loadByte(data); // Загрузить полученный байт в регистр
STATE_LOAD;
}
Дмитрий Лиман (студент
НИЯУ МИФИ)
Настройка приёма : Строка программы “
#define SPEED 100” отвечает за качество приёма байта. Величина
SPEED зависит от скорости приёма (здесь
9600) и рабочей частоты микроконтроллера, которая может несколько отличаться от паспортной частоты
9,6 мГц.
Например, отправляем число
64 (
01000000) и смотрим на приём.
Установлено, что для скорости
9600 величина
SPEED менялась от
94 до
105, обеспечивая достоверность приёма (для микроконтроллера, оказавшегося под рукой). Соответственно для
SPEED выбрана средняя величина равная
100.
Что наблюдалось на приёме за пределами диапазона (
94-105) :
При установке
SPEED =
92 (уменьшенный период опроса входного сигнала) принималось не число
64 (01000000), а число
128 (10000000).
Объясните почему ?При установке
SPEED =
107 (увеличенный период опроса входного сигнала) принималось не число
64 (01000000), а число
160 (32+128, 10100000). То есть, происходит смещение в другую сторону, где
32 – это информация от принятого байта, а
128 – это от стопового бита.
Объясните почему ?В случае с микроконтроллером, который окажется у Вас, величина
SPEED может несколько отличаться (не
100, а например
96 или
104) и она определяется экспериментальным путём, учитывая вышеизложенную информацию и правильные ответы на вопросы.
Дополнительно!Как вариант подстройки частоты микроконтроллера, из темы "Примеры для ATtiny13":
19. Подстройка частоты RC-генератора и регистр OSCCAL.