野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 7591|回复: 3

串口环形队列?

[复制链接]
发表于 2022-1-24 00:01:26 来自手机 | 显示全部楼层 |阅读模式
你那列程里面串口环形队列程序看的我头皮发麻,一点头绪都没有,太绕了,能不能回复一下啊
回复

使用道具 举报

发表于 2022-1-24 09:01:56 | 显示全部楼层
例程里面那个比较久之前写的,可以搜搜网上其他有讲解的STM32串口队列代码来用
回复 支持 反对

使用道具 举报

发表于 2022-4-13 19:25:54 | 显示全部楼层
本帖最后由 木羽之灵 于 2022-4-13 19:34 编辑

一、数据类型
1.1 实例化节点数据类型
    QUEUE_DATA_TYPE  node_data[QUEUE_NODE_NUM];
    QUEUE_DATA_TYPE类型实际为
typedef struct
{
    char  *head;     //缓冲区头指针   
    uint16_t len; //接收到的数据长度
}ESP_USART_FRAME;
1.2 实例化队列类型
    QueueBuffer rx_queue;
    QueueBuffer类型为
//队列结构
typedef struct {
    int         size;  /* 缓冲区大小          */
    int         read; /* 读指针              */
    int         write;   /* 写指针  */
    int read_using;    /*正在读取的缓冲区指针*/
    int write_using;        /*正在写入的缓冲区指针*/
    QUEUE_DATA_TYPE    *elems[QUEUE_NODE_NUM];  /* 缓冲区地址                   */
} QueueBuffer;
1.3 队列缓冲区的内存池
__align(4) char node_buff[QUEUE_NODE_NUM][QUEUE_NODE_DATA_LEN] ;

总结:
node_buff才是真正物理上的缓冲区,所以缓冲区就是二维数组,node_buff用于接收一个字符串;
rx_queue包含用于操作缓冲区的指针下标,以及记录的操作状态。
node_data貌似没什么用。

二、编程要点与处理流程
2.1 void rx_queue_init(void)
   初始化node_buff、rx_queue、node_data
2.2 程序状态说明
    程序实际上是根据rx_queue.read、rx_queue.write、rx_queue.read_using、rx_queue.write_using的组合来决定事件的状态。
    rx_queue.write、rx_queue.write_using相同,写入操作已完成,再次写入需要指向新的地址;
    rx_queue.write、rx_queue.write_using不同,写入操作正在进行,且是朝同一个node_buff进行连续写入。
    rx_queue.read、rx_queue.read_using相同,读取操作已完成,再次读取,需要指向新的地址;
    rx_queue.read、rx_queue.read_using不同,读取操作正在进行;
    rx_queue.write、 rx_queue.read相同,表示缓冲区为空,可写;
    rx_queue.write、 rx_queue.read不同,缓冲区可读;
2.3 写操作
    写操作在中断中进行。cbWrite(&rx_queue);函数的作用是修改rx_queue.write_using,进入写操作状态
    当写操作状态不变时,字符串可以连续写入(因为cbWrite不会修改rx_queue.write_using,从而导致rx_queue.elems->head不变),如下图(连续写入缓冲区)所示:
    结束写操作状态,实际上运用了USART的IDLE中断,即串口不工作时产生中断。
此时,调用cbWriteFinish(&rx_queue);函数使得rx_queue.write、rx_queue.write_using相同。
2.4 读操作
    读操作状态不需要设置,因为写完一个数据之后,必然会导致rx_queue.write、 rx_queue.read不同,处于可读状态。
    为了实现读取字符串,在数组中插入'\0',同时也避免了读取到旧数据(因为并没有进行擦除的操作),如下图(插入字符结束符)所示:
    最后就是结束读取状态(cbReadFinish(&rx_queue)函数),并且将rx_queue.len置为0(使得下一个数组能够从头开始写入)

cbWrite函数.PNG
连续写入缓冲区.PNG
插入字符结束符.PNG
回复 支持 反对

使用道具 举报

发表于 2022-4-14 16:54:36 | 显示全部楼层
本帖最后由 木羽之灵 于 2022-4-14 17:01 编辑

补充说明:
   node_data的作用:node_data的作用就是帮助初始化rx_queue.elems。那为什么不直接初始化rx_queue.elems呢?接下来慢慢解释:
   实际上我们都是操作rx_queue。要想修改缓冲区的内容,就需要操作rx_queue.elems->head。该指针需要指向 node_buffer。
   我们可以直接使用如下语句初始化rx_queue.elems->head:
   rx_queue.elems->head = node_buffer[i[;
   现在的问题是 rx_queue.elems本身也是指针,如果我们不初始化它,作为结构体rx_queue的成员,系统默认初始值是NULL。而NULL指针是不允许进行操作的。这就导致,即使你初始化了rx_queue.elems->head也没有用。
   所以程序先初始化node_data,再利用rx_queue.elems=&node_buff,实现 rx_queue.elems的初始化。

   当然,我们也可以通过malloc初始化指针,如下
    rx_queue.elems=(QUEUE_DATA_TYPE  *)malloc(sizeof(QUEUE_DATA_TYPE ));
    这样我们就不需要node_data了。
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-24 01:09 , Processed in 0.027036 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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