嵌入式数据传输及存储的C语言实现

各种类型的数据传输和存储就涉及到大小端的问题,首先要简单说下芯片的大小端问题,这里主要讨论Cortex-M内核。

M内核支持大端或者小端,实际应用中大部分内核都是小端。以STM32为例,全部都是小端,而且是芯片设计之初就固化进去的,不可修改

市面上其他厂家基本也都固化的小端格式。

F1编程手册

F3和F4编程手册

F7和H7编程手册

各种数据类型编程EEPROM,SPI Flash等存储器的简易方法,一般这些存储器都是字节编程,写入浮点等数据类型时不太方便。这里分享一个方法,定义一个结构体,将各种数据类型封装进去

写入的时候采用下面方式:

读取时可以采用下面方式:

各种数据类型的SPI,UART,I2C等传输问题。这里我们以串口通信为例,比如主机要发送如下格式数据给从机:

我们可以做一个如下结构体格式:

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;   
}
UART_T;UART_T g_tUartParam;

主机发送的时候我们就可以采用如下方法:

comSendBuf(COM1, (uint8_t *)&g_tUartParam, sizeof(UART_T));

从机工程也定义一个同样的结构体变量,比如我们把接收到一帧数据存到缓冲uint8_t buf[50]里面了。

我们就可以定义一个结构体指针变量:

UART_T *pUartParam;
pUartParam = (UART_T *)buf;

那么我们就可以pUartParam->usCO2,pUartParam->Temprature等方式来访问,非常方便。

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linuxc/c++高级开发【直播公开课】

零声白金VIP体验卡:零声白金VIP体验卡(含基础架构/高性能存储/golang/QT/音视频/Linux内核)

代码实现

结构体数据如下:

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];     /* 接收记录缓冲 */

数据收发处理:

/*
*********************************************************************************************************
*        函 数 名: 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;}}}
}

测试效果

原文作者:eric2013

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/234522.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

半同步复制与MHA高可用架构设计

各位道友好,鼠鼠我呀校招刚通过了移动的面试 ,但是安排的岗位是偏远县城里面的岗位,各位能给给建议吗?鼠鼠我啊真不想有时候变成销售员去卖产品!!! 半同步复制与MHA高可用架构设计 一、半同步复…

Flutter应用程序的加固原理

在移动应用开发中,Flutter已经成为一种非常流行的技术选项,可以同时在Android和iOS平台上构建高性能、高质量的移动应用程序。但是,由于其跨平台特性,Flutter应用程序也面临着一些安全风险,例如反编译、代码泄露、数据…

Python正则表达式:match()和search()函数全面解读

更多资料获取 📚 个人网站:ipengtao.com 在Python中,正则表达式是强大的工具,能够用于文本匹配、搜索和替换。re模块提供了许多函数来处理正则表达式,其中match()和search()是两个常用的函数。本文将深入探讨这两个函…

力扣刷题-122买卖股票的最佳时机

题目要求如上,这里可以有两种解题思路,一种是利用动态规划去求解,一种是用贪心去求解。 首先看下动态规划的方法。 用动归去解决 动态规划最重要的就是要想出来递推公式(这个真的很难),但是一旦想清楚递推…

EasyExcel生成多sheet页的excel

一、controller层 ApiOperation(value "明细查询导出") PostMapping(value "/SummaryDetailExport") public void summaryDetailExport(RequestBody SearchDTO dto, HttpServletResponse response) throws IOException {reportService.deptPackagingSum…

Python函数装饰器的用法

Python函数装饰器的用法 文章目录 1.装饰器的优点2. 使用装饰器前3. 使用装饰器后 装饰器是Python中一种强大的语法特性,它允许在不修改已有代码的情况下,对函数或类进行增强或修改。装饰器的本质是一个函数,它接受一个函数作为参数&#xf…

软件测试面试最全八股文

请你说一说测试用例的边界 参考回答: 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界。 常见的边界值 1)对16-bit 的整数而言 32…

故障排查:rpm安装报错事务锁定(can‘t create transaction lock on /var/lib/rpm/.rpm.lock)

博客主页:https://tomcat.blog.csdn.net 博主昵称:农民工老王 主要领域:Java、Linux、K8S 期待大家的关注💖点赞👍收藏⭐留言💬 目录 故障详情故障原因解决办法 故障详情 自己编写spec文件,制…

《C++ Primer》第10章 算法(二)

参考资料: 《C Primer》第5版《C Primer 习题集》第5版 10.4 再探迭代器(P357) 除了为每个容器定义的迭代器外,头文件 iterator 中还定义了额外的几种迭代器: 插入迭代器(insert iterator)&…

AMESim与MATLAB联合仿真demo

本文是AMESim与MATLAB联合仿真的demo,记录一下如何进行联合仿真。 AMESim与MATLAB联合仿真可以大幅度提高工作效率。 author:xiao黄 缓慢而坚定的生长 csdn:https://blog.csdn.net/Python_Matlab?typeblog主页传送门 博主的联合仿真环境如下&#xff…

数字图像处理(实践篇)十五 基于傅里叶变换的高通滤波和低通滤波

目录 一 Numpy 实现傅里叶变换 1 涉及的函数 2 实践 二 OpenCV 实现傅里叶变换 1 涉及的函数 2 实践 为了有效地和快速地对图像进行处理和分析,常常需要将原定义在图像空间的图像以某种形式转换(正变换)到另外一些空间,并利…

物业报修管理系统

物业报修管理系统是一种能够提高物业管理效率和服务质量的软件,它可以帮助物业公司和业主之间实现快速、方便、高效的报修沟通和处理。 但是很多物业公司还在使用传统的报修方式,比如电话、纸质表格、微信群等,这些方式存在很多问题&#xff…