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

news2024/11/22 5:26:28

各种类型的数据传输和存储就涉及到大小端的问题,首先要简单说下芯片的大小端问题,这里主要讨论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.coloradmin.cn/o/1274383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TR转发路由器测评—云企业网实现跨地域跨VPC的网络互通测评实战【阿里云产品测评】

文章目录 一.转发路由器 Transit Router 测评1.1 准备阶段1.2 本文测评收获1.3 什么是云企业网实例、转发路由器实例和云数据传输服务 二.使用云企业网实现跨地域跨VPC的网络互通2.2 **测试连通性**2.3 网络拓扑如下: 心得:总结: 声明&#x…

Vue+SpringBoot解决session跨域问题

做了一个前后端分离,因为前后端的 session id不一致,导致前端请求时,后端的session读取不到对应的值,造成登录问题。 解决方法: SpringBoot项目: 添加一个跨域配置 代码如下: 或者controller使用CrossOrigin Conf…

解决noauth authentication required异常

今天在使用redis数据库的时候,突然给报了个这个错误,上网一查才知道是因为 Redis 服务器需要密码进行身份验证,因此,我们需要通过auth password 进行身份验证。不过我这个密码还是试了很多次才想起来的,哦好像是听网课…

WSL2 docker GUI 界面

在 WSL2 docker 中运行GUI界面。 具体流程和远程显示Ubuntu界面类似,链接, 更简单一点, 少了 ssh 的部分。 安装好wsl2 和 docker wsl2 运行GUI程序,windows 会默认弹出窗口。 可以安装 gedit 测试一下 windows 下载并运行 Xlaunch. 运行 d…

【驱动】SPI驱动分析(二)-SPI驱动框架

SPI驱动框架 SPI驱动属于总线-设备-驱动模型的,与I2C总线设备驱动模型相比,大体框架是一样,他们都是实际的总线。总体框架如下图所示: 从上到下,分为三层,用户空间,内核空间,和硬件…

微信小程序真机调试的时候出现白屏解决办法

我使用uniapp开发微信小程序开发,使用真机调试的时候,出现白屏,页面里面啥都没有,也没有报错,这就让人很纳闷了: 解决办法: 打开真机调试,下面有:切换真机调试1.0&#…

RocketMQ-RocketMQ快速实战及集群原理

一、MQ简介 ​ MQ:MessageQueue,消息队列。是在互联网中使用非常广泛的一系列服务中间件。 这个词可以分两个部分来看,一是Message:消息。消息是在不同进程之间传递的数据。这些进程可以部署在同一台机器上,也可以分布…

虚拟机系列:Oracle VM VirtualBox安装/更新/卸载出现 无法访问你试图使用的功能所在的网络位置

Oracle VM VirtualBox安装/更新/卸载出现 无法访问你试图使用的功能所在的网络位置 Oracle VM VirtualBox安装/更新/卸载出现 无法访问你试图使用的功能所在的网络位置Oracle VM VirtualBox安装/更新/卸载出现 无法访问你试图使用的功能所在的网络位置 在更新Oracle VM Virtua…

泛型和数据结构(树)

一&#xff1a;泛型的基本知识 泛型是用来约束操作的数据类型&#xff0c;并进行检查 基本格式&#xff1a;<数据类型> 注意&#xff1a;泛型只能支持引用数据类型&#xff0c;如果是基本数据类型&#xff0c;需要写他的包装类 先来看一下没有泛型约束的集合 我们发现此时…

【ArcGIS Pro二次开发】(78):批量合并GDB数据库

有些GDB数据库会按分幅或行政区划进行分开储存&#xff0c;尤其是一些地形测绘或国情地理数据。 如下图所示&#xff1a; 数据是完整的&#xff0c;但使用的时候要一个一个拖进地图中&#xff0c;进行分析的时候也需要将其合并后使用。 因此就做了这个合库工具。 一、要实现的…

万界星空科技仓库管理wms系统

企业在管理库存时&#xff0c;尤其是生产制造企业&#xff0c;使用传统方式比如纸笔、Excel 管理库存&#xff0c;由于工具和信息化存在局限&#xff0c;导致在管理库存时出现如下问题&#xff1a; 1、通过纸笔记录出入库申请&#xff0c;人为手动计算易出错&#xff0c;数据易…

[iOS学习笔记]浅谈RunLoop底层

RunLoop是什么&#xff1f; RunLoop是iOS开发中比较重要的知识点&#xff0c;它贯穿程序运行的整个过程。它是线程基础架构的一部分&#xff0c;是一种保障线程循环处理事件而不会退出的机制。同时也负责管理线程需要处理的事件&#xff0c;让线程有事儿时忙碌&#xff0c;没事…

键盘敲入一个字母,操作系统发生了什么?

一、设备控制器 我们的电脑设备可以接非常多的输入输出设备&#xff0c;比如鼠标键盘网卡硬盘打印机等&#xff0c;每个设备的用法和功能都不相同&#xff0c;那操作系统是如何把这些输入输出设备统一管理的呢&#xff1f; 为了屏蔽设备之间的差异&#xff0c;每个设备都有一…

rest_framework_django学习笔记一(序列化器)

rest_framework_django学习笔记一(序列化器) 一、引入Django Rest Framework 1、安装 pip install djangorestframework2、引入 INSTALLED_APPS [...rest_framework, ]3、原始RESTful接口写法 models.py from django.db import models 测试数据 仅供参考 INSERT INTO de…

我与开源的历程

我在2000年开始接触开源&#xff0c;当时在松下航空电子美国总部工作。我负责将 IFE 系统从 Win31 迁移到 Linux。作为一个完全不懂 Linux 的小白&#xff0c;我不得不找到一台笔记本电脑安装并自学 Redhat Linux 6.1。2003年回到新加坡后&#xff0c;我发现没有一个凝聚 Linux…

Java数据结构之《链式线性表的插入与删除》问题

一、前言&#xff1a; 这是怀化学院的&#xff1a;Java数据结构中的一道难度中等偏下的一道编程题(此方法为博主自己研究&#xff0c;问题基本解决&#xff0c;若有bug欢迎下方评论提出意见&#xff0c;我会第一时间改进代码&#xff0c;谢谢&#xff01;) 后面其他编程题只要我…

Rust std fs 比 Python 慢!真的吗!?

作者&#xff1a;Xuanwo Databend Labs 成员&#xff0c;数据库研发工程师 https://github.com/xuanwo 我即将分享一个冗长的故事&#xff0c;从 OpenDAL 的 op.read()开始&#xff0c;以一个意想不到的转折结束。这个过程对我来说非常有启发性&#xff0c;我希望你也能感受到。…

记RocketMQ本地开发环境搭建始末

前言 最近工作中涉及到了RocketMQ的应用&#xff0c;为方便开发决定本地搭建一套RocketMQ的使用环境。 果然实践是个好东西... VMware虚拟环境搭建 这个网上有很多教程&#xff0c;只会比我写的详细有条理&#xff0c;这里就不在赘述了。 虚拟机搭建好之后每次重启电脑都无…

flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级

flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级 在之前的开发过程中&#xff0c;需要实现卡片轮播效果&#xff0c;但是卡片轮播需要中间大、两边小一些的效果&#xff0c;这里就使用到了Swiper。具体效果如视频所示 添加链接描述 这里需要的效果是中间大、两边…

golang 函数选项模式

一 什么是函数选项模式 函数选项模式允许你使用接受零个或多个函数作为参数的可变构造函数来构建复杂结构。我们将这些函数称为选项&#xff0c;由此得名函数选项模式。 例子&#xff1a; 有业务实体Animal结构体&#xff0c;构造函数NewAnimal&#xff08;&#xff09;&…