Цифрова послідовність. Приймач (AVR)

На цьому уроці ми з Вами розберемо програмну реалізацію приймача цифрової байт орієнтованої послідовності на мікроконтролері AVR.

Програма працює наступним чином. Після ініціалізації периферії, проводиться пошук першого байта стартової послідовності в потоці даних, що передаються передавачем…

findByte(0b01000001);

Після його знаходження приймаються два наступних біти, які є другим і третім байтами стартової послідовності…

reciveByte();
if (rxBuffer != 0b01000010) continue;

reciveByte();
if (rxBuffer != 0b01000011) continue;

При будь-якому невідповідності прийом стартової послідовності починається заново. Далі приймаються дані, контрольна сума та біт парності.

reciveByte(); //Прийом байта потужності
powerEngine = rxBuffer;

reciveByte(); //Прийом байта commandBuffer
commandBuffer = rxBuffer;

reciveBit(); //Прийом біта парності
if (rxBuffer & (1 << 0)) parityBit = HIGH; else parityBit = LOW;

reciveByte(); //Прийом байта контрольної суми
checkSum = rxBuffer;

В завершенні проводиться прийом трьох стопових байт.

reciveByte();
if (rxBuffer != 0b01000100) continue;

reciveByte();
if (rxBuffer != 0b01000101) continue;

reciveByte();
if (rxBuffer != 0b01000110) continue;

При будь-якому невідповідності прийом кадру починається заново. По завершенню прийому кадру починається перевірка даних: біта парності та контрольної суми…

//Вичисляємо контрольну суму прийнятих даних
controlCheckSum = powerEngine + commandBuffer;

//Перевіряємо парність прийнятих даних
if (controlCheckSum & (1 << 0)) controlParityBit = HIGH; else controlParityBit = LOW;
if (controlParityBit != parityBit) continue;

//Перевіряємо контрольну суму
if (checkSum != controlCheckSum) continue;

При будь-якому невідповідності прийом кадру починається заново. У випадку проходження перевірки виконуємо команди, надіслані пультом управління…
//Завантажуємо значення потужності
OCR2 = powerEngine;

//Виконуємо команди напрямку руху і повороту
if (commandBuffer & (1 << 0)) PORTD |= (1 << PD0); else PORTD &= ~(1 << PD0);
if (commandBuffer & (1 << 1)) PORTD |= (1 << PD1); else PORTD &= ~(1 << PD1);
if (commandBuffer & (1 << 2)) PORTD |= (1 << PD2); else PORTD &= ~(1 << PD2);

Функція пошуку байта працює наступним чином. Очищаємо буфер приймача…

rxBuffer = 0; //Очищаємо буфер приймача

Припустимо, що в даний момент передавач передає логічну одиницю. Перевіряємо це...

if (PINB & (1 << PB0)) {...

...передаємо управління секції прийому логічної одиниці.  Для вимірювання тривалості ми будемо використовувати таймер. Включаємо його…

TCCR1B |= (0 << CS02)|(0 << CS01)|(1 << CS00); //Включити таймер

Чекаємо, поки триває імпульс, і поки значення лічильного реєстра таймера менше вибраної нами тривалості...

while(PINB & (1 << PB0) && TCNT1 < PULSE_DURATION); //Очікування...

Вимикаємо таймер...

TCCR1B &= ~(0 << CS02|0 << CS01|1 << CS00); //Вимкнути таймер

Перевіряємо тривалість імпульса...

if (TCNT1 > PULSE_DURATION) {...

Якщо виміряна тривалість імпульсу відповідає вибраній уставці, реєструємо прийнятий біт...

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

Встановлюємо прапор «дані прийняті»...

dataReceived = TRUE; //Дані прийняті

Обнуляємо лічильник відліків...

TCNT1 = 0; //Очищаємо лічильник відліків

Переходимо до секції порівняння...

//Перевіряємо на збіг...  
if (rxBuffer == byteforComparing) {

rxBuffer = 0; //Очищаємо буфер приймача
break; //При збігу виходимо з циклу
}

Якщо збіг сталося, виконання функції припиняється. Якщо ні, переходимо до секції контролю.

Якщо «дані прийняті»...

//Якщо дані прийняті, але збігу не сталося...    
if (dataReceived == TRUE) {...

Звільняємо новий розряд для прийому наступного біта, очищаємо прапор «дані прийняті»...

rxBuffer  << = 1; //Звільняємо новий розряд
dataReceived = FALSE; //Очищаємо прапор статусу прийому даних

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

Процедура прийому біта працює аналогічно і пояснень не вимагає. Про процедуру прийому байта я взагалі мовчу

Проект з вихідним кодом і симуляція в Proteus у вкладенні!

Прикріплені файли:

Top