基于stm32f103解析富斯i6遥控器和FS-iA6B接收机的ibus通信

使用stm32解析富斯i6遥控器的ibus通信,这样我们就可以实现自己想要的控制,比如用来控制小车,或者在飞机上面用上其他的功能。

1. 关于ibus通信

IBUS(Intelligent Bus)协议是一种常用于遥控航模(遥控飞机、无人机等)中的数字通讯协议。它由Flysky公司开发,主要用于遥控器与接收机之间的通信。以下是IBUS协议的基本原理和实现过程:

  1. 串行通讯:IBUS协议是一种串行通讯协议,通常基于TTL电平(0-5V)。它使用一条数据线进行双向通信,数据传输采用异步串行模式。

  2. 数据帧结构:IBUS协议的数据传输方式包括一个数据帧,其中包括开始位、数据位、校验位等。每个数据帧包含多个频道的信息,每个频道的数据值以数字形式表示。

  3. 数据格式:IBUS的数据包通常由固定的帧头、数据区域和帧尾组成。数据区域包含多个频道的信息,通常以16位或8位的格式传输。数据的具体格式和长度可以根据协议的版本和实现有所不同。

通过串行数据传输和高效的数据帧结构,IBUS协议能够提供快速、可靠的遥控信号传输,为航模控制提供精确的数据支持。

2. 设置富斯i6遥控器的ibus通信

打开富斯i6遥控器长按OK键进入菜单。IBUS通信就在系统->接收机设置->i-bus设置,进入里面选择通道1就可以实现i-bus通道选择了(接收机设置里面的PPM输出要关掉,一般也没开)

 3. FS-iA6B接收机接线

其中信号线接到stm32的串口接收端。

 4. 读取程序

 读取信号串口的配置其使用stm32的UART3串口,设置波特率位115200。

void IBUS_Init()
{
	//GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;//调用结构体
	USART_InitTypeDef USART_InitStructure;//调用结构体
	NVIC_InitTypeDef NVIC_InitStructure;//调用结构体
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能GPIOA时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);	//使能USART3时钟
	
	//UART3_TX   GPIOB10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置速率为50MHz
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
  //UART3_RX	  GPIOB11
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 
	
  //NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;//USART1串口中断地址
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  //USART 初始化设置
	RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);//使能USART1时钟
	USART_InitStructure.USART_BaudRate = 115200;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  //初始化串口
  USART_Init(USART3, &USART_InitStructure); 
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART3, ENABLE);                    //使能串口1 
}

对应的中断读取函数,判断数据的起始位,然后将后面的数据存储在rx_buffer[ ]数组中,接收完成时,对标志位置一。

///****中断函数*****//
void USART3_IRQHandler(void)                	//串口中断服务程序
	{
		unsigned char data;
		static uint8_t rxstart = 0; //状态机的标志位
		static uint8_t rx_arr_flag = 0; //保存数据的数组下标
		uint8_t rx_getflag = 0;
		
		if(USART_GetITStatus(USART3, USART_IT_RXNE)  != RESET) 
		{
			/* 用户代码 */
			data = USART_ReceiveData(USART3);	//读取接收到的数据; 
			
				if (rxstart == 0 ) //状态机
				{
					if(data == 0x20 && rx_getflag == 0) //判断数据的起始位,只是保险使用,还会有2层保险
					{
						rx_arr_flag = 0;
						rxstart = 1;
						rx_buffer[rx_arr_flag] = data;
						rx_arr_flag++;
					}
				}
				else if (rxstart == 1)
				{
					rx_buffer[rx_arr_flag] = data;
					rx_arr_flag++;
					if(rx_arr_flag >= 32)
					{
						rxstart = 2;
					}
				}
				else if (rxstart == 2)
				{
					if(rxstart == 2)
					{
						rxstart = 0;
						IBUS_RX_Finish = 1;
						rx_getflag = 1;
					}
				}
				
				USART_ClearITPendingBit(USART3,USART_IT_RXNE);
		}
		
	}

 IBUS处理函数,这部分放到while()循环里面不断处理,先判断标志位是否置一,在处理过程中要关闭接收中断,不然会出现数据错误。先判断前两位头帧0x20,0x40,然后后面都以两位为一组载入通道缓存数组,checksum_cal用来进行校验防止出错。

void IBUS_Handle()
{
	char txt[16];
	int i = 0,j = 0;
	uint16_t channel_buffer[IBUS_MAX_CHANNLES] = {0};
	
	if(IBUS_RX_Finish==1)
	{
		IBUS_RX_Finish=0;//
		
		NVIC_DisableIRQ(USART3_IRQn);//关闭中断
		
			if(rx_buffer[0] == IBUS_start1 && rx_buffer[1] == IBUS_start2)
			{
				checksum_cal = 0xffff - rx_buffer[0] - rx_buffer[1];

				for( i = 0; i < IBUS_MAX_CHANNLES; i++)
				{
					channel_buffer[i] = (uint16_t)(rx_buffer[i * 2 + 3] << 8 | rx_buffer[i * 2 + 2]);
					checksum_cal = checksum_cal - rx_buffer[i * 2 + 3] - rx_buffer[i * 2 + 2];
				}

				checksum_ibus = rx_buffer[31] << 8 | rx_buffer[30];

				if(checksum_cal == checksum_ibus)   //进行数值校对,校对成功后装入
				{
					for(j = 0; j < IBUS_USER_CHANNELS; j++)
					{
						channel[j] = channel_buffer[j];
					}
				}
			}
			
		NVIC_EnableIRQ(USART3_IRQn);//打开中断
		
	}

}

最后得到的数据在串口打印出来,其中由于我的遥控器只用六个通道,后面的值就不会变。当操作杠拉到最低的时候为1000,推到最高时为3000。这样就可以用来控制舵机等设备。

源码我放到这里面了:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值