stm32实现SBUS传输

该文介绍了一个基于STM32的串口配置,使用100k波特率,9位数据位,偶校验和2位停止位。通过DMA空闲中断来接收和处理SBus数据。接收函数检查帧完整性并转换遥控器通道数据。空闲中断函数用于停止DMA接收并更新接收状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 基本配置

串口波特率:100k,9位数据位,校验,2位停止位,利用dma空闲中断进行接收数据和处理数据

在这里插入图片描述
在这里插入图片描述

接收函数

int8_t BSP_UART_IDLE_PollData(UART_HandleTypeDef *huart, struct RF207S_SBUS_DataStructure *rf207_sbus_data)
{

	int8_t nret = 0;
	if (Uart_Receive_Data.rxok == 0) //没有接收完就退出
	{
		nret = -1;

	}
	else
	{
		if (Uart_Receive_Data.rxlen < 25) //帧不完整
		{
			nret = -2;
		}
		else if (Uart_Receive_Data.rxbuf[0] != 0x0f || Uart_Receive_Data.rxbuf[24] != 0x00) //帧错误
		{
			nret = -3;
		}
		if (nret == 0)
		{
			//遥控器的取值范围:-100 ---->100 返回值的范围0----100
			// Min:354    Max:1696   ----->1342    chx-353/1342. == y*100
			rf207_sbus_data->ch1 = (((int16_t) Uart_Receive_Data.rxbuf[2] << 8) + ((int16_t) Uart_Receive_Data.rxbuf[1])) & 0x07ff;
			rf207_sbus_data->ch1 = (rf207_sbus_data->ch1-353)*100/1342.;
			rf207_sbus_data->ch2 = (((int16_t) Uart_Receive_Data.rxbuf[3] << 5) + ((int16_t) Uart_Receive_Data.rxbuf[2] >> 3))& 0x07ff;
			rf207_sbus_data->ch2 = (rf207_sbus_data->ch2-353)*100/1342.;
			rf207_sbus_data->ch3 = (((int16_t) Uart_Receive_Data.rxbuf[5] << 10) + ((int16_t) Uart_Receive_Data.rxbuf[4] << 2) + ((int16_t) Uart_Receive_Data.rxbuf[3] >> 6)) & 0x07ff;
			rf207_sbus_data->ch3 = (rf207_sbus_data->ch3-353)*100/1342.;
			rf207_sbus_data->ch4 = (((int16_t) Uart_Receive_Data.rxbuf[6] << 7) + ((int16_t) Uart_Receive_Data.rxbuf[5] >> 1))& 0x07ff;
			rf207_sbus_data->ch4 = (rf207_sbus_data->ch4-353)*100/1342.;
			rf207_sbus_data->ch5 =(((int16_t)Uart_Receive_Data.rxbuf[9]<<9) + ((int16_t)Uart_Receive_Data.rxbuf[8]<<1) + ((int16_t)buf[7]>>7)) & 0x07ff;
			rf207_sbus_data->ch5 = (rf207_sbus_data->ch5-353)*100/1342.;
			rf207_sbus_data->ch6 =(((int16_t)Uart_Receive_Data.rxbuf[10]<<6) + ((int16_t)Uart_Receive_Data.rxbuf[9]>>2)) & 0x07ff;
			rf207_sbus_data->ch6 = (rf207_sbus_data->ch6-353)*100/1342.;
			rf207_sbus_data->ch7 =(((int16_t)Uart_Receive_Data.rxbuf[11]<<3) + ((int16_t)Uart_Receive_Data.rxbuf[10]>>5)) & 0x07ff;
			rf207_sbus_data->ch7 = (rf207_sbus_data->ch7-353)*100/1342.;
			rf207_sbus_data->ch8 =(((int16_t)Uart_Receive_Data.rxbuf[13]<<8) + (int16_t)Uart_Receive_Data.rxbuf[12]) & 0x07ff;
			rf207_sbus_data->ch8 = (rf207_sbus_data->ch8-353)*100/1342.;
			rf207_sbus_data->ch9 =(((int16_t)Uart_Receive_Data.rxbuf[14]<<5) + ((int16_t)Uart_Receive_Data.rxbuf[13]>>3)) & 0x07ff;
			rf207_sbus_data->ch9 = (rf207_sbus_data->ch9-353)*100/1342.;
			rf207_sbus_data->ch10 =(((int16_t)Uart_Receive_Data.rxbuf[16]<<10) + ((int16_t)Uart_Receive_Data.rxbuf[15]<<2) + ((int16_t)Uart_Receive_Data.rxbuf[14]>>6)) & 0x07ff;
			rf207_sbus_data->ch10 = (rf207_sbus_data->ch10-353)*100/1342.;
		}
		Uart_Receive_Data.rxok = 0;
		__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE); //使能串口空闲中断
		memset(Uart_Receive_Data.rxbuf, 0, UART_RECEIVE_IDLE_RX_MAXLEN);
		HAL_UART_Receive_DMA(huart, Uart_Receive_Data.rxbuf, UART_RECEIVE_IDLE_RX_MAXLEN); //开启串口DMA接收
	}

	return nret;
}

空闲中断函数(将函数放在默认的空闲中断之前)记得在it中断文件中包含该函数的头文件

void BSP_UART_IDLE_CallBack(UART_HandleTypeDef *huart)
{
	if ((__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET))
	{
		HAL_UART_DMAStop(huart);
		__HAL_UART_CLEAR_IDLEFLAG(huart);
		Uart_Receive_Data.rxlen = UART_RECEIVE_IDLE_RX_MAXLEN - __HAL_DMA_GET_COUNTER(huart->hdmarx);
		Uart_Receive_Data.rxok = 1;
	}
}

在这里插入图片描述

避坑指南:

用串口调试sbus:

串口用的是小端模式,是低位先发,刚好sbus一个通道的值是16位,所以在串口里显示的应该是两个16进制的数,后面的16进制数是高位

建议直接用调试直接看内存数据

### STM32SBUS 的相关用法及配置 #### 一、SBUS 协议简介 S.BUS 是一种由 Futaba 开发的双向通信协议,广泛应用于遥控模型领域。它采用 UART 接口传输数据,具有高效率和低延迟的特点。每帧数据长度固定为 25 字节,其中包含多达 18 路通道的信息以及一个错误检测字节。 对于 STM32 微控制器而言,可以通过其 USART 外设来接收并解析 S.BUS 数据流[^1]。具体实现方式依赖于硬件串口中断机制或者 DMA 技术完成连续的数据采集工作。 #### 二、STM32SBUS 解析方法概述 在基于 STM32 平台开发支持 S.BUS 输入功能的应用时,通常会经历以下几个主要环节: - **初始化USART模块**:设置波特率至标准值 (通常是 100kbps),启用 RX 引脚作为输入端,并开启相应的中断服务函数。 - **捕获起始位同步信号**:由于 S.Bus 帧是以特殊的标志序列开头,因此需要特别注意识别这些特征以便后续处理逻辑能够正确启动。 - **读取有效载荷部分**:一旦确认进入新消息周期,则按照既定顺序逐字节提取各路PWM宽度数值直至结束标记为止。 下面给出一段简单的伪代码用于演示上述过程的核心思路: ```c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ static uint8_t buffer[25]; static uint8_t index=0; if(huart->Instance==UARTx){ // Replace with your actual used uart instance name. buffer[index++]=*pRxData; if(index>=sizeof(buffer)){ Process_SBUS_Frame((uint8_t*)buffer); index=0; } HAL_UART_Receive_IT(&huartX,(uint8_t*)&pRxData,1); } } ``` 此回调函数会在每次接收到单个字符之后被调用一次,在这里我们将它们累积存入缓冲区直到凑齐整个报文结构再统一交予高层算法进一步分析计算[^2]。 #### 三、注意事项 当实际部署该方案前还需考虑一些额外因素可能影响最终效果的好坏程度: - 确认所选针脚确实连接到了发射器输出侧; - 如果存在多个设备共享同一条总线的情况则需妥善安排优先级避免冲突发生; - 对抗外界干扰源可能导致误码现象采取适当措施加以缓解比如增加滤波电路等等;
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值