DMC.23 · Приём управления · ATmega328P
Задача
Принять кадр SBUS по UART и распаковать 16 каналов по 11 бит.
Алгоритм
UART 100000 бод, 8E2. Кадр: 0x0F старт, 22 байта данных (16×11 бит упакованы), флаги, 0x00 конец. Битовая распаковка.
Исходный код (C, avr-gcc)
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
static void uart_sbus_init(void){
UBRR0 = (F_CPU/(8UL*100000UL))-1; // 100000 бод, U2X
UCSR0A=(1<<U2X0);
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00)|(1<<UPM01)|(1<<USBS0); // 8E2
UCSR0B=(1<<RXEN0);
}
static uint8_t rx(void){ while(!(UCSR0A&(1<<RXC0))); return UDR0; }
void sbus_unpack(uint8_t *b, uint16_t ch[16]){
ch[0]=((b[1]|b[2]<<8)&0x07FF);
ch[1]=((b[2]>>3|b[3]<<5)&0x07FF);
ch[2]=((b[3]>>6|b[4]<<2|b[5]<<10)&0x07FF);
ch[3]=((b[5]>>1|b[6]<<7)&0x07FF);
/* ... остальные каналы аналогично ... */
}
int main(void){
uint8_t f[25]; uint16_t ch[16];
uart_sbus_init();
DDRB|=(1<<PB5);
for(;;){
if(rx()==0x0F){
for(uint8_t i=1;i<25;i++) f[i]=rx();
sbus_unpack(f, ch);
if(ch[2]>1000) PORTB|=(1<<PB5); else PORTB&=~(1<<PB5);
}
}
}
Сборка: avr-gcc -mmcu=atmega328p -DF_CPU=16000000UL -Os файл.c -o файл.elf
Пояснения
SBUS инвертирован — нужен внешний инвертор перед RX. Здесь настройка UART и распаковка каналов.