硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2537|回复: 7
收起左侧

[UART] 分享个简单的串口FIFO实现数据结构体收发处理案例

  [复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106726
QQ
发表于 2022-5-24 01:50:06 | 显示全部楼层 |阅读模式
【问题由来】
实战技能分享,各种数据类型的SPI, UART, I2C,FDCAN等方式的通信传输以及存储到EEPROM, Flash等设备的简易实现方法
https://www.armbbs.cn/forum.php?mod=viewthread&tid=109659

但坛友反应使用有没有个完整可参考的例子,特地制作了个分享下。

【例子下载】
串口结构体数据收发处理.7z (1.31 MB, 下载次数: 280)

【硬件说明】
测试方便起见,我这里直接使用了串口1,串口2和串口3.

TTL串口1的PA9发送引脚发送数据给串口2的PA3接收数据引脚,串口3是485接口,作为printf输出使用。

【代码实现】


结构体数据如下:
[C] 纯文本查看 复制代码
typedef struct
{
    uint8_t ucStart;                        

    uint16_t usCO2;
    uint16_t usPM25;        
    uint16_t usHumidity;         
    float    Temprature;
    uint32_t ulParam;
    uint8_t  ucEnd1;           
    uint8_t  ucEnd2;   
}
USART_T;

USART_T g_tUartParam; /* 串口1发送数据使用 */
USART_T *pUartParam;  /* 串口2接数据使用 */
uint8_t buf[128];     /* 接收记录缓冲 */


数据收发处理:
[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*        函 数 名: main
*        功能说明: c程序入口
*        形    参: 无
*        返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
        uint8_t ucKeyCode;        
        uint8_t read;
        uint8_t ucStatus = 0;  /* 状态机标志 */
        uint8_t ucCount=0;
        float ftest = 0.11f;
        pUartParam = (USART_T *)buf;
        
        
        bsp_Init();                /* 硬件初始化 */
        
        PrintfLogo();        /* 打印例程名称和版本等信息 */
        PrintfHelp();        /* 打印操作提示 */


        bsp_StartAutoTimer(0, 100); /* 启动1个100ms的自动重装的定时器 */
        
        memset(buf, 0, 128);
        
        /* 进入主程序循环体 */
        while (1)
        {
                bsp_Idle();                /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */

                /* 判断定时器超时时间 */
                if (bsp_CheckTimer(0))        
                {
                        /* 每隔100ms 进来一次 */  
                        bsp_LedToggle(2);                        
                }
                
                /* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */
                ucKeyCode = bsp_GetKey();        /* 读取键值, 无键按下时返回 KEY_NONE = 0 */
                if (ucKeyCode != KEY_NONE)
                {
                        switch (ucKeyCode)
                        {
                                case KEY_DOWN_K1:                        /* K1键按下,串口1发送数据给串口2 */
                                        g_tUartParam.ucStart = '$';
                                        g_tUartParam.usCO2 = 1;
                                        g_tUartParam.usPM25 = 2;
                                        g_tUartParam.usHumidity = 3;
                                        g_tUartParam.Temprature = ftest++;
                                        g_tUartParam.ulParam = 5;        
                                        g_tUartParam.ucEnd1 = '\r';        
                                        g_tUartParam.ucEnd2 = '\n';
                                        comSendBuf(COM1, (uint8_t *)&g_tUartParam, sizeof(UART_T));
                                        printf("发送数据完成\r\n");
                                        break;

                                default:
                                        /* 其它的键值不处理 */
                                        break;
                        }
                }
                
                /* 串口2接收数据解析处理 */
                if (comGetChar(COM2, &read))
                {
                        switch (ucStatus)
                        {
                                /* 状态0保证接收到0x01 */
                                case 0:
                                        if(read == '$')
                                        {
                                                ucStatus = 1; 
                                                buf[ucCount++] = read;
                                        }
                                        break;

                                case 1:
                                        buf[ucCount] = read;
                                   
                                        /* 接收够15个数据 */
                                        if((buf[ucCount-1] == '\r')&&(buf[ucCount] == '\n'))
                                        {
                                                /* 打印接收到的数据值 */
                                                printf("接收到的数据:\r\n");
                                                printf("pUartParam->usCO2 = %d\r\n", pUartParam->usCO2);
                                                printf("pUartParam->usPM25 = %d\r\n", pUartParam->usPM25);
                                                printf("pUartParam->usHumidity = %d\r\n", pUartParam->usHumidity);
                                                printf("pUartParam->Temprature = %f\r\n", pUartParam->Temprature);
                                                printf("pUartParam->ulParam = %d\r\n", pUartParam->ulParam);                                                
                                                printf("\r\n");
                                                
                                                memset(buf, 0, 128);
                                                ucStatus = 0;
                                                ucCount=0;
                                        }
                                        else
                                        {
                                                ucCount++;
                                        }
                                        break;
                                
                                default:
                                        break;
                        }
                }
        }
}



【测试效果】
image.png

评分

参与人数 1金币 +10 收起 理由
chenjiawei + 10 很给力!

查看全部评分

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106726
QQ
 楼主| 发表于 2022-5-24 01:53:39 | 显示全部楼层
整理完毕
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2022-6-1 10:48:57 | 显示全部楼层
这个方法在实际编程的时候经常用,确实好用。
回复

使用道具 举报

1

主题

35

回帖

38

积分

新手上路

积分
38
发表于 2022-6-1 11:03:26 | 显示全部楼层
一般还会加个校验值
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2022-6-1 11:15:27 | 显示全部楼层
这个会不会有结构体内存对齐的问题呢?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106726
QQ
 楼主| 发表于 2022-6-1 11:27:18 | 显示全部楼层
WangPengGuy 发表于 2022-6-1 11:15
这个会不会有结构体内存对齐的问题呢?

有的,要统一使用小端或者大端。
回复

使用道具 举报

0

主题

43

回帖

43

积分

新手上路

积分
43
发表于 2022-7-8 09:13:08 | 显示全部楼层
学习一下                           
回复

使用道具 举报

44

主题

562

回帖

699

积分

金牌会员

积分
699
发表于 2023-3-22 17:26:34 | 显示全部楼层
comGetChar(COM2, &read)这个函数每次就读到一个数据,像这样结构体读多个数据,那不是需要程序多次循环才能读完吗?如果数据比较多,对于需要实时性来说,那不是比较慢吗?
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-2 13:55 , Processed in 0.185775 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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