OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 577|回复: 0

更正帖,RTthread2种串口接收不定长度数据的方法

[复制链接]

22

主题

49

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
214
金钱
214
注册时间
2014-4-30
在线时间
26 小时
发表于 2023-12-29 11:14:00 | 显示全部楼层 |阅读模式
之前的发表的一篇帖子: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 是用的方法二,节约资源一些


欢迎批评指正!

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-5-15 22:11

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表