[失败案例]- 用stm32f103得gpio模拟S.Bus接口

不清楚是代码原因还是逻辑原因, 我用以下代码逻辑, 模拟S.Bus 接口通信失败.

#include <rtthread.h>
#include<drv_common.h>

#define DBG_TAG "app.s_sbus"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

/**
*软件sbus的实现(IO模拟sbus)
* 波特率:100000    2-8-E
* TXD : 
* RXD : PA11
* 使用外部中断对RXD的上升沿进行触发,使用定时器4按照100000波特率进行定时数据接收。
* Demo功能: 接收25个数据,然后把接收到的数据显示出来
*/
typedef unsigned char u8;


#define BuadRate_9600	100
#define BuadRate_100000	10

#define Cur_Buadrate  BuadRate_100000

u8 len = 0;	//接收计数
unsigned short sbus_buf[32];  //接收缓冲区

enum{
	COM_START_BIT,
	COM_D0_BIT,
	COM_D1_BIT,
	COM_D2_BIT,
	COM_D3_BIT,
	COM_D4_BIT,
	COM_D5_BIT,
	COM_D6_BIT,
	COM_D7_BIT,
	COM_D8_BIT,
	COM_PRIMARY,
	COM_STOP_BIT1,
	COM_STOP_BIT2,
};

u8 recvStat = COM_STOP_BIT2;
unsigned short recv_data = 0;

void s_sbus_recv(void*);
static rt_timer_t  timer1;


// 外部中断
static int sbus_exti_pin = 0;
void sbus_exti(void * args)
{
  if(rt_pin_read(sbus_exti_pin) == 1 && recvStat == COM_STOP_BIT2) {
			// LOG_E("sbus_exti %d %d", rt_pin_read(sbus_exti_pin), recvStat);
			rt_pin_irq_enable(sbus_exti_pin, PIN_IRQ_DISABLE);
			recvStat = COM_START_BIT;
			rt_timer_start(timer1);
  }
}

// 显示数据
void print_data(void* arg){
	char buf[200]={0};
	while(1)	{
		if(len > 25)		{
			for(int i = 0; i < 25; i ++){
				rt_sprintf(buf,"%s %#X",buf, sbus_buf[i]);
			}
			LOG_E("print_data: %s", buf);
			buf[0] = '\0';
			len = 0;
		}
	}
}

int sbus_init(void)
{
		sbus_exti_pin = rt_pin_get("PA.11");
		LOG_E("rt_pin_get PA.11 %d", sbus_exti_pin);
    rt_pin_mode(sbus_exti_pin, PIN_MODE_INPUT_PULLUP);
    rt_pin_attach_irq(sbus_exti_pin, PIN_IRQ_MODE_RISING, sbus_exti, RT_NULL);
    rt_pin_irq_enable(sbus_exti_pin, PIN_IRQ_ENABLE);

		timer1 = rt_timer_create("timer1",
				s_bus_recv,
				RT_NULL,
				10,
				RT_TIMER_FLAG_PERIODIC);

		if (timer1 != RT_NULL){
			LOG_E("timer1 init!!");
		}

		rt_thread_t tid = rt_thread_create("sbus data", print_data, RT_NULL,
													 1024, RT_THREAD_PRIORITY_MAX - 2, 20);
		if (tid != RT_NULL)		{
				rt_thread_startup(tid);
		}		else		{
				LOG_E("create sd_mount thread err!");
		}

		return RT_EOK;1
}

void s_bus_recv(void * args)
{
	 recvStat++;
	if(recvStat == COM_STOP_BIT2)	{
		rt_timer_stop(timer1);
		sbus_buf[len++] = recv_data;
    rt_pin_irq_enable(sbus_exti_pin, PIN_IRQ_ENABLE);
		return;
	}
	if(rt_pin_read(sbus_exti_pin))	{
		recv_data &= ~(1 << (recvStat - 1));
	}else{
		recv_data |= (1 << (recvStat - 1));
	}
}
INIT_APP_EXPORT(sbus_init);

注意: 代码只实现了数据接收, 并没有实现代码的奇偶校验.

代码是参考了gpio模拟串口: https://github.com/TonyIOT/SoftWareSerial/blob/master/USER/main.c

该代码得串口逻辑实现 9600 1-8-N. 相对来说, 频率更低一些.

结:

  • 个人认为是gpio 读取频率可能达不到 100K , 毕竟接收后,要对数据进行一些简单得处理需要一部分时延. 当然也可能是因为 使用得 rt-thread 系统接口, 没直接底层,导致系统调用浪费了些资源导致的,
    估计处理速度更快的芯片还是有希望完成gpio的模拟的, 总的来说我还是不推荐这样做.

  • 接下来还是走老路子, 硬件取反,然后串口接收.
    思路参考:

    • px4 的 https://github.com/PX4/PX4-Autopilot/blob/master/src/lib/rc/sbus.cpp 实现
    • https://www.ncnynl.com/archives/201709/2038.html 博客.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值