Машинка на ДУ управлении своими руками. Цифровая последовательность. Передатчик и приёмник на PIC

На этом уроке мы с Вами портируем программную реализацию интерфейса передатчика и приёмника с цифровой, байт ориентированной последовательностью на микроконтроллер PIC.

Рассмотрение программы начнём с заголовочного файла передатчика transmitter.h. Единственное изменение состоит в отличительном написании команды задержки…

 __delay_ms(1); //Частота передачи 1000 бод

Настройки портов ввода-вывода и АЦП из файла initHard.c остаются прежними.

Теперь рассмотрим основную программу. Опрашиваем клавиши поворота и заднего хода…

 //Опрос клавиши направление движения. Загрузить полученные данные в commandBuffer if (PORTBbits.RB1 == 0) commandBuffer |= (1 << 0); else commandBuffer &= ~(1 << 0);  //Опрос клавиш направления поворота. Загрузить полученные данные в commandBuffer if (PORTBbits.RB2 == 0) commandBuffer |= (1 << 1); else commandBuffer &= ~(1 << 1); //Влево if (PORTBbits.RB4 == 0) commandBuffer |= (1 << 2); else commandBuffer &= ~(1 << 2); //Вправо 

Сохраняем мгновенное значение мощности в буфер, вычисляем бит паритета и контрольную сумму…

 //Загружаем мгновенное значение мощности powerEngine = ADRESH;  //Вычисляем контрольную сумму checkSum = powerEngine + commandBuffer;  //Проверяем на чётность передаваемые данные if (checkSum & (1 << 0)) parityBit = HIGH; else parityBit = LOW;

В отличии от AVR АЦП МК PIC режима автоматического перезапуска, поэтому…

 GO_DONE = 1; //Начать измерение

В основном цикле передаём данные…

 //Передача стартовых байт transmitString(START_SEQUENCE);  //Передача байта мощности transmitByte(powerEngine);  //Передача байта commandBuffer transmitByte(commandBuffer);  //Передача бита чётности if (parityBit == EVEN) transmitBit(HIGH); else transmitBit(LOW);  //Передача байта контрольной суммы transmitByte(checkSum);  //Передача стоповых байт transmitString(STOP_SEQUENCE); 

Функция transmitBit. Если при вызове аргумент функции равен HIGH, то конструкция…

 if (txBuffer == HIGH) PORTAbits.RA2 = 1; //Формируем фронт

…формирует фронт логической единицы. Далее следует пауза…

 PULSE_DURATION()...

…которая обеспечивает скорость передачи в 1000 бод. Следом формируется безусловный срез…

 PORTAbits.RA2 = 0;  //Формируем срез

В случае, если аргумент функции равен LOW, функция формирует паузу в 1ms.

Функция transmitByte, в качестве аргумента получает один байт, 8 бит которого передаются в цикле…

 for (unsigned char i = 0; i < 8; i++) {...

Проверяем «нулевой» бит, в зависимости от его значения формируем фронт или срез…

 //Формируем фронт/срез if (txBuffer & (1 << 7)) PORTAbits.RA2 = 1; else PORTAbits.RA2 = 0;

…формируем паузу…

 PULSE_DURATION(); //Длительность логического состояния

Сдвигаем переменную txBuffer вправо на один разряд. Эта процедура повторяется 8 раз, для передачи 8 бит.

Функция transmitString, в качестве аргумента получает строку символов. Перед началом передачи вычисляется количество символов в строке, затем в цикле…

 for (unsigned char i = 0; i < strlen(txBuffer); i++) {...

…загружаем первый передаваемый символ в буфер передатчика…

 charBuffer = txBuffer[i];

…происходит передача 8 байт текущего байта…

 for (unsigned char i = 0; i < 8; i++) { //Формируем фронт/срез if (charBuffer & (1 << 7)) PORTAbits.RA2 = 1; else PORTAbits.RA2 = 0;      PULSE_DURATION(); //Длительность логического состояния  charBuffer >>=  1; //Сдвиг вправо на одну позицию }

Эта процедура повторяется для каждого передаваемого символа.

Теперь о приёмнике… После инициализации периферии, производится поиск первого байта стартовой последовательности в потоке данных передаваемых передатчиком. После его нахождения принимаются два следующих бита, которые являются вторым и третьим байтами стартовой последовательности. При любом несовпадении приём стартовой последовательности начинается заново. Далее принимаются данные, контрольная сумма и бит чётности. В завершении производится приём трёх стоповых байт. При любом несовпадении приём кадра начинается заново. По завершению приёма кадра начинается проверка данных: бита чётности и контрольной суммы. При любом несовпадении приём кадра начинается заново. В случае прохождения проверки выполняем команды посланные пультом управления…

 //Загружаем значение мощности OCR2 = powerEngine;  //Выполняем команды направления движения и поворота if (commandBuffer & (1 << 0)) PORTBbits.RB1 = 1; else PORTBbits.RB1 = 0; if (commandBuffer & (1 << 1)) PORTBbits.RB2 = 1; else PORTBbits.RB2 = 0; if (commandBuffer & (1 << 2)) PORTBbits.RB4 = 1; else PORTBbits.RB4 = 0;

Функция findByte. Очищаем буфер приёмника…

 rxBuffer = 0; //Очищаем буффер приёмника

Допустим, что в данный момент передатчик передаёт логическую единицу. Проверяем это…

 if (PORTAbits.RA2 == 1) {...

…передаём управление секции приёма логической единицы. Для измерения длительности мы будем использовать таймер. Включаем его…

 TMR1ON = 1; //Включить таймер

Ждём, пока длится импульс, и пока значение счётного регистра таймера меньше выбранной нами длительности…

 while(PORTAbits.RA2 == 1 && TMR1 < PULSE_DURATION); //Ожидание...

Выключаем таймер…

 TMR1ON = 0; //Выключить таймер

Проверяем длительность импульса…

 if (TMR1 > PULSE_DURATION) {...

Если измеренная длительность импульса соответствует выбранной уставке, регистрируем принятый бит…

 rxBuffer++; //Записываем в буффер "1"

Устанавливаем флаг «данные приняты»…

 dataReceived = TRUE; //Даннее приняты

Обнуляем счётчик отсчётов…

 TMR1 = 0; //Очищаем счётчик отсчётов

Переходим к секции сравнения…

 //Проверяем на совпадение...   if (rxBuffer == byteforComparing) { rxBuffer = 0; //Очищаем буфер приёмника break; //При совпадении выходим из цикла }

Если совпадение произошло, выполнение функции прекращается. Если нет, переходим к секции контроля.

Если «данные приняты»…

 //Если данные приняты, но совпадения не произошло...     if (dataReceived == TRUE) {...

Освобождаем новый разряд для приёма следующего бита, очищаем флаг «данные приняты»…

 rxBuffer   <<  = 1; //Освобождаем новый разряд dataReceived = FALSE; //Очищаем флаг статуса приёма данных 

Эта процедура будет выполняется до тех пор, пока не будет принят заданный байт.

ПРОЕКТ С ИСХОДНЫМ КОДОМ И СИМУЛЯЦИЯ В PROTEUS во вложении.