中级会员
- 积分
- 214
- 金钱
- 214
- 注册时间
- 2014-4-30
- 在线时间
- 26 小时
|
之前的发表的一篇帖子:http://www.openedv.com/forum.php ... d=300874&extra=
存在问题,那个例子是一个接收"\n"的固定格式的数据(按行接收);
现在将整理的方法列下:
方法1:通过定时器超时来判断;
方法2:利用信号量等待超时来判断;
代码如下:
#include <rtthread.h>
#include <rtdevice.h>
#include <stdio.h>
#include <string.h>
static struct rt_semaphore rx_sem1;
#define SENOR_DATA_LEN 9
#define USING_SOFT_TIMEOUT 0
rt_device_t serial_port;
typedef struct
{
uint8_t buf[SENOR_DATA_LEN * 2];
uint8_t len;
uint8_t is_rcv_over;
} samll_senor_rcv_t;
samll_senor_rcv_t serial_rcv = { 0 };
static rt_err_t serial_input(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&rx_sem1);
return RT_EOK;
}
#if USING_SOFT_TIMEOUT
static rt_timer_t serial_rcv_timeout = RT_NULL;
static void serial_rcv_timeout_cb(void *p)
{
rt_timer_stop(serial_rcv_timeout);
serial_rcv.buf[serial_rcv.len] = '\0';
serial_rcv.is_rcv_over = RT_TRUE;
rt_kprintf("timeout\r\n");
}
#endif
static void samll_senor_init(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 配置参数 */
config.baud_rate = 9600; //修改波特率
rt_sem_init(&rx_sem1, "rx_sem1", 0, RT_IPC_FLAG_FIFO);
serial_port = rt_device_find("uart2");
rt_device_control(serial_port, RT_DEVICE_CTRL_CONFIG, &config); // 修改波特率
rt_device_open(serial_port, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
rt_device_set_rx_indicate(serial_port, serial_input);
#if USING_SOFT_TIMEOUT
h2s_rcv_timeout = rt_timer_create("serial_timer", serial_rcv_timeout_cb, RT_NULL, 50,
RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_PERIODIC);
rt_timer_start(serial_rcv_timeout);
#endif
}
static void serial_rcv_thread_entry(void* parameter)
{
char ch;
while (1)
{
#if USING_SOFT_TIMEOUT
while (rt_device_read(serial_port, -1, &ch, 1) != 1)
{
rt_sem_take(&rx_sem1, RT_WAITING_FOREVER);
}
serial_rcv.buf[serial_rcv.len++] = ch;
rt_timer_control(serial_rcv_timeout, RT_IPC_CMD_RESET, RT_NULL);
rt_timer_start(serial_rcv_timeout);
#else
static uint8_t rcv_one_byte_flag = 1;
while (rt_device_read(serial_port, 0, &ch, 1) == 0)
{
rt_sem_control(&rx_sem1, RT_IPC_CMD_RESET, RT_NULL);
if (rcv_one_byte_flag)
rt_sem_take(&rx_sem1, RT_WAITING_FOREVER);
else if (-RT_ETIMEOUT == rt_sem_take(&rx_sem1, 100)) //超时100ms未获得串口数据 100是根据时钟节拍来定 节拍单位是1/RT_TICK_PER_SECOND 秒
{
rcv_one_byte_flag = 1; //收完一帧
serial_rcv.buf[serial_rcv.len] = '\0';
serial_rcv.is_rcv_over = RT_TRUE;
}
}
rcv_one_byte_flag = 0; //正常获取一个字节
serial_rcv.buf[serial_rcv.len++] = ch;
#endif
}
}
static int serial_init(void)
{
samll_senor_init();
return RT_EOK;
}
static void senor_update_entery(void *p)
{
while (1)
{
if (serial_rcv.is_rcv_over == RT_TRUE)
{
for (int i = 0; i < serial_rcv.len; i++)
{
rt_kprintf("%02X ", serial_rcv.buf);
}
// do sth.usr code begin.
memset(&serial_rcv, 0, sizeof(samll_senor_rcv_t));
}
}
}
static rt_thread_t senor_handle = RT_NULL, h2s_rcv_handle;
static int app_start(void)
{
senor_handle = rt_thread_create("senor", senor_update_entery, RT_NULL, 2048, 15, 20);
if (senor_handle != RT_NULL)
rt_thread_startup(senor_handle);
else
return -1;
h2s_rcv_handle = rt_thread_create("serial", serial_rcv_thread_entry, RT_NULL, 2048, 15, 20);
if (h2s_rcv_handle != RT_NULL)
rt_thread_startup(h2s_rcv_handle);
else
return -1;
return RT_EOK;
}
INIT_COMPONENT_EXPORT(serial_init);
INIT_APP_EXPORT(app_start);
-----------------------------------------------------------------------------------------------------------------
可以通过修改这个宏定义来判断用方法1还是方法2
#define USING_SOFT_TIMEOUT 0 是用的方法二,节约资源一些
欢迎批评指正!
|
|