STM32F103读取富思i6(i-bus)协议,基于固件库开发的版本(V3.5)

实验准备

i-bus接收机一个,富思i6遥控器(其他也行),我使用的是STM32F103系类的单片机,使用了中断,串口,0.96的OLED(IIC协议),PA12 - SCL,PA11 - SDA。使用的是串口1(PA10)引脚,把ibus的信号线

ibus协议分析

官方发布的协议表,可以自己看看,我们只用十个通道

直接上程序源码

一下是串口判断数据,读取ibus协议,保存在数组

代码有具体注释,自己看看

#include "stm32f10x.h"
#include "sys.h"
#include "usart.h"
#include <stdio.h>

//char rxstring[100];//字符串命令集
uint8_t rxdata[32];//用于存储数据,数组大小,就是字节数
uint8_t txdata[32];//用于发送数据,数组大小,就是字节数
uint8_t rxflag = 0;
uint8_t rx_getflag = 0;
/**
  * @brief  串口初始化函数
  * @param  bit_lv: 参数:波特率
  */
void usart_init(uint32_t bit_lv)
{
	GPIO_InitTypeDef GPIO_Init_usart;
	USART_InitTypeDef USART_Init_1;
	NVIC_InitTypeDef NVIC_init_1;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

	GPIO_Init_usart.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init_usart.GPIO_Pin = GPIO_Pin_9 ;
	GPIO_Init_usart.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Init_usart);

	GPIO_Init_usart.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init_usart.GPIO_Pin = GPIO_Pin_10 ;
	GPIO_Init_usart.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Init_usart);


	USART_Init_1.USART_BaudRate = bit_lv;
	USART_Init_1.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_Init_1.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_Init_1.USART_Parity = USART_Parity_No;
	USART_Init_1.USART_StopBits = USART_StopBits_1;
	USART_Init_1.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1,&USART_Init_1);
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	NVIC_init_1.NVIC_IRQChannel = USART1_IRQn;
	NVIC_init_1.NVIC_IRQChannelCmd = ENABLE;
	NVIC_init_1.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_init_1.NVIC_IRQChannelSubPriority = 1;

	NVIC_Init(&NVIC_init_1);

	USART_Cmd(USART1,ENABLE);
}

/**
  * @brief  发送一个字节的函数
  * @param  bit_lv: 需要发送的数据
  */
void write_bit(uint8_t byte)
{
	USART_SendData(USART1,byte);
	while (USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);

}

/**
  * @brief  发送一个数组的函数
  * @param  array: 传输的数组地址,指针变量,uint_8的
  * @param  length: 数组的长度用于判断循环是否需要结束
  */
void write_arr(uint8_t *array , uint16_t length)
{
	uint16_t i;
	for ( i = 0; i < length; i++)
	{
		write_bit(array[i]);
	}
	
}

/**
  * @brief  发送一个字符的函数
  * @param  string: 传输的字符串
  */
void write_string(char *string)
{
	uint8_t i;
	for(i = 0; string[i] != 0;i++)
	{
		write_bit(string[i]);
	}
}
/**
  * @brief  发送一个字符的函数
  * @param  string: 传输的字符串
  */

uint32_t num_pow(uint32_t x , uint32_t y)
{
	uint8_t result = 1;
	while (y--)
	{
		result *= x;
	}
	return result;
	
}

/**
  * @brief  发送一个字符的函数
  * @param  number: 传输的数字
  * @param  length: 传输数字的长度
  */
 void write_num(uint32_t number,uint8_t length)
 {
	uint8_t i;
	for ( i = 0; i < length; i++)
	{
		write_bit(number / num_pow(10,length - i - 1)%10+'0');
	}
	
 }
/**
  * @brief 重定向printf
  */
int fputc(int ch,FILE *f)
{
	write_bit(ch);
	return ch;
}

void SendOut_data(void)
{
	write_bit(0xff);//数据帧头
	write_arr(txdata,4);//数组长度需要改变
	write_bit(0xfe);
}

/**
  * @brief  串口1中断函数
  */
void USART1_IRQHandler(void) //串口1中断
{
	static uint8_t rxstart = 0; //状态机的标志位
	static uint8_t rx_arr_flag = 0; //保存数据的数组下标
	if(USART_GetFlagStatus(USART1,USART_IT_RXNE) == SET) //判断标志位是否正确
	{
		uint8_t data = USART_ReceiveData(USART1);//将数据1byte数据读取到data
		if (rxstart == 0 ) //状态机
		{
			if(data == 0x20 && rx_getflag == 0) //判断数据的起始位,只是保险使用,还会有2层保险
			{
				rx_arr_flag = 0;
				rxstart = 1;
				rxdata[rx_arr_flag] = data;
				rx_arr_flag++;
			}
		}
		else if (rxstart == 1)
		{
			rxdata[rx_arr_flag] = data;
			rx_arr_flag++;
			if(rx_arr_flag >= 32)
			{
				rxstart = 2;
			}
		}
		else if (rxstart == 2)
		{
			if(rxstart == 2)
			{
				rxstart = 0;
				rxflag = 1;
				rx_getflag = 1;
			}
		}
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}
}

保存的数组读取,校验,还有变换值

#include "read_ibus.h"

uint16_t channel[10] = {0};//保存通道数值
uint16_t checksum_cal, checksum_ibus; //零时存储
uint8_t user_channels = 10;

void read_ibus(uint8_t *arr)
{
    int i=0,j=0;
    uint16_t channel_buffer[IBUS_MAX_CHANNLES] = {0};//通道数据暂存器

		checksum_cal = 0xffff - arr[0] - arr[1];

		for(i = 0; i < IBUS_MAX_CHANNLES; i++)//10个通道,循环十次,保存数据
		{
			channel_buffer[i] = (uint16_t)(arr[i * 2 + 3] << 8 | arr[i * 2 + 2]);//通道数据暂存器
			checksum_cal = checksum_cal - arr[i * 2 + 3] - arr[i * 2 + 2]; 
		}

		checksum_ibus = arr[31] << 8 | arr[30]; //计算校验值

		if(checksum_cal == checksum_ibus) //对比校验值
		{
			for(j = 0; j < user_channels; j++) //将值赋值到通道内
			{
				channel[j] = channel_buffer[j];
				rx_getflag = 1; //状态置1,表示可以读取
			}
		}
}

uint16_t* get_arr_1(void)
{
	return channel;
}

uint16_t get_pwm(uint16_t pwm)
{
	uint16_t rt_pwm = (float)((float)(pwm - 980)/1000.0) * 100;
	return rt_pwm;
}

现在所有的数据全部保存在数组里面了,全部都是1000 - 2000的数字,下标0,是通道一的数据,以此类推。后面的get_pwm是线性映射,全部工程代码,在博客的下载栏下载即可。

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值