/*************************************************
* @copyright:
* @author:Xupeng
* @date:2022-11-03
* @description:
**************************************************/
#include "sbus.h"
#define DBG_TAG "sbus"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#define SBUS_UART_NAME "uart6" /* 串口设备名称 */
/* 用于接收消息的信号量 */
static rt_device_t sbusSerial;
static rt_uint8_t recBuf[50];
static rt_uint8_t recCnt = 0;
#define INIT_VALUE 992//遥控器中间值
rt_uint16_t sbusVal[SBUS_CH_MAX] = {
INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,\
INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE,INIT_VALUE};
rt_uint8_t sbusIsOk = 0;
static bool findPackageHead = true;//包出错时重新开始寻找包头
/*************************************************
* @function:static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
* @description: 接收数据
* @calls:
* @input:
* @return:
* @others:
*************************************************/
static rt_err_t sbus_input(rt_device_t dev, rt_size_t size)
{
uint8_t readLen;
readLen = rt_device_read(sbusSerial, 0, &recBuf[recCnt], size);//读取一个字节
if(findPackageHead && recBuf[0] == 0x0f)//判断是不是包头
{
recCnt += readLen;
}
if(!findPackageHead && recBuf[0] == 0x00)//判断是不是重新开始寻找包头
findPackageHead = true;
if(recCnt >= 25)
{
if(recBuf[0] != 0x0f || recBuf[23] !=0)//数据帧格式错误
{
recCnt = 0;
recBuf[0] = 0x00;
findPackageHead = false; //重新开始寻找包头
}
else
{
sbusVal[0] = ((rt_uint16_t)recBuf[ 1] >> 0 | ((rt_uint16_t)recBuf[ 2] << 8 )) & 0x07FF;
sbusVal[1] = ((rt_uint16_t)recBuf[ 2] >> 3 | ((rt_uint16_t)recBuf[ 3] << 5 )) & 0x07FF;
sbusVal[2] = ((rt_uint16_t)recBuf[ 3] >> 6 | ((rt_uint16_t)recBuf[ 4] << 2 ) | (rt_uint16_t)recBuf[ 5] << 10 ) & 0x07FF;
sbusVal[3] = ((rt_uint16_t)recBuf[ 5] >> 1 | ((rt_uint16_t)recBuf[ 6] << 7 )) & 0x07FF;
sbusVal[4] = ((rt_uint16_t)recBuf[ 6] >> 4 | ((rt_uint16_t)recBuf[ 7] << 4 )) & 0x07FF;
sbusVal[5] = ((rt_uint16_t)recBuf[ 7] >> 7 | ((rt_uint16_t)recBuf[ 8] << 1 ) | (rt_uint16_t)recBuf[9] << 9 ) & 0x07FF;
sbusVal[6] = ((rt_uint16_t)recBuf[ 9] >> 2 | ((rt_uint16_t)recBuf[10] << 6 )) & 0x07FF;
sbusVal[7] = ((rt_uint16_t)recBuf[10] >> 5 | ((rt_uint16_t)recBuf[11] << 3 )) & 0x07FF;
sbusVal[8] = ((rt_uint16_t)recBuf[12] << 0 | ((rt_uint16_t)recBuf[13] << 8 )) & 0x07FF;
sbusVal[9] = ((rt_uint16_t)recBuf[13] >> 3 | ((rt_uint16_t)recBuf[14] << 5 )) & 0x07FF;
sbusVal[10] = ((rt_uint16_t)recBuf[14] >> 6 | ((rt_uint16_t)recBuf[15] << 2 ) | (rt_uint16_t)recBuf[16] << 10 ) & 0x07FF;
sbusVal[11] = ((rt_uint16_t)recBuf[16] >> 1 | ((rt_uint16_t)recBuf[17] << 7 )) & 0x07FF;
sbusVal[12] = ((rt_uint16_t)recBuf[17] >> 4 | ((rt_uint16_t)recBuf[18] << 4 )) & 0x07FF;
sbusVal[13] = ((rt_uint16_t)recBuf[18] >> 7 | ((rt_uint16_t)recBuf[19] << 1 ) | (rt_uint16_t)recBuf[20] << 9 ) & 0x07FF;
sbusVal[14] = ((rt_uint16_t)recBuf[20] >> 2 | ((rt_uint16_t)recBuf[21] << 6 )) & 0x07FF;
sbusVal[15] = ((rt_uint16_t)recBuf[21] >> 5 | ((rt_uint16_t)recBuf[22] << 3 )) & 0x07FF;
sbusIsOk ++;
recCnt = 0;
recBuf[0] = 0x00;
}
}
return RT_EOK;
}
/*************************************************
* @function:void sbus_init()
* @description: 初始化SBUS
* @calls:
* @input:
* @return:
* @others:
*************************************************/
int sbus_init()
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
rt_err_t res;
sbusSerial = rt_device_find(SBUS_UART_NAME);
if (!sbusSerial)
{
LOG_E("find %s failed!", SBUS_UART_NAME);
return RT_ERROR;
}
config.baud_rate = BAUD_RATE_100000; //修改波特率为 100000
config.data_bits = DATA_BITS_9; //数据位 9
config.stop_bits = STOP_BITS_1; //停止位 1
config.bufsz = 128; //修改缓冲区 buff size 为 128
config.parity = PARITY_EVEN; //偶校验位
res = rt_device_control(sbusSerial, RT_DEVICE_CTRL_CONFIG, &config);
if(res != RT_EOK)
{
LOG_E("commit control err!");
return RT_ERROR;
}
res = rt_device_open(sbusSerial, RT_DEVICE_OFLAG_RDONLY|RT_DEVICE_FLAG_INT_RX);
if(res != RT_EOK)
{
LOG_E("commit open err!");
return RT_ERROR;
}
res = rt_device_set_rx_indicate(sbusSerial, sbus_input);
if(res != RT_EOK)
{
LOG_E("commit set indicate err!");
return RT_ERROR;
}
return RT_EOK;
}
INIT_PREV_EXPORT(sbus_init);
注意
一、初始化
波特率为100Kbit
数据位为9位
停止位为1位(STM32的初始化)
校验位为PARITY_EVEN
二、数据格式错误时一定要重新开始寻找包头0x0f,否则数据会一直错误。实现方法为等包尾0x00,等到包尾后重新开始寻找包头,因为任何通道数据都不可能为0x00。
三、不同遥控器输出值范围不一样,下面是我的数据: