各种数据类型的SPI, UART, I2C等方式的通信传输以及存储到EEPROM、Flash等设备的简易实现方法

news2024/12/23 6:02:30

各种类型的数据传输和存储就涉及到大小端的问题,首先要简单说下芯片的大小端问题,我们这里主要讨论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等方式来访问,非常方便。

代码实现

结构体数据如下:

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

测试效果

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

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

相关文章

Spring Cloud Alibaba Nacos Config - - - >多配置文件/共享配置

源码地址(重点开源码中的 nacos8030 模块):https://download.csdn.net/download/weixin_42950079/87264006 多配置文件 / 共享配置 在一个微服务架构应用系统中可能包含成百上千个微服务。而很多微服务可能都引入相同的中间件,当环境中引入的中间件较多时…

【eth uniswap】uniswap 自动路径(Auto Router)错误导致的swap超大损耗

____tz_zs 2022-06-09 稿 对于同时有v2池子和v3池子的Token,感觉最近uniswap的app的自动路由寻址(Auto Router)有点问题,找的永远是v3的(如示例caw/weth)池子。此时的情况是v3池子很小,只有几十…

用 HarmonyOS ArkUI 来开发一个健康饮食应用

本文演示如果在DevEco Studio 3里面,用HarmonyOS的ArkUI来开发一个健康饮食应用。体验HarmonyOS 3最新API 9! 获取HarmonyOS应用 HarmonyOS的ArkUI来开发一个健康饮食的ArkUI程序“ArkUIHealthyDiet”,基础代码已经有了[1],个人…

【数据结构初阶】八大排序算法+时空复杂度

学会控制自己是人生的必修课 文章目录一、插入排序1.直接插入排序2.希尔排序二、选择排序1.直接选择排序2.堆排序(已经建好堆的基础之上)三、交换排序(Swap)1.冒泡排序(大学牲最熟悉的排序)2.快速排序&…

Python 数据库开发实战-Mac系统下通过homebrew安装Redis数据库

此文章的前置条件是 “Mac系统已安装过Homebrew”,如果未安装,可访问 “Mac 安装 homebrew 详细教程” 一文,详细介绍Homebrew的用法。利用 “Homebrew” 对 “Redis” 进行安装管理,那是一个方便啊。 利用 homebrew 安装 Redis …

【Windows逆向】【Qt】日志信息打印

▒ 目录 ▒🛫 导读需求开发环境1️⃣ 示例程序Demo2️⃣ 编写功能(QtCreator版本)3️⃣ 编写功能(VS版本)🛬 文章小结📖 参考资料🛫 导读 需求 调试是编程中常见的定位手段&#xf…

字节一面,操作系统这题没答好,可惜了

问题引入: 在曾经我们学习Linux的经历中,我们也是多次使用信号的。比如:当我们在使用xshell时,在命令行中按Ctrlc,这个键盘输入产生了一个硬件中断,被操作系统获取,解释成信号,发送…

两百行C++代码实现yolov5车辆计数部署(通俗易懂版)

这周用opencv简单实现了一下基于yolov5检测器的车辆计数功能,方法是撞线计数,代码很简单一共就两百多行,测试视频是在b站随便下载的。注:该代码只能演示视频demo效果,一些功能未完善,离实际工程应用还有距离…

JMeter整体综述

JMeter整体综述1. JMeter体系结构及运行原理1.1 主要的组件1.2 运行原理2. 元件执行顺序和作用域2.1 元件执行顺序2.2 元件执行作用域3. 参考1. JMeter体系结构及运行原理 负载模拟:负责模拟用户请求。如取样器有参数化的需求,可通过配置元件或前置处理器…

15.JavaScript 01

文章目录一、概念二、功能三、 JavaScript发展史四、 ECMAScript:客户端脚本语言的标准1、基本语法1. 与html结合方式2. 注释3. 数据类型4. 变量5. 运算符6. 流程控制语句7. JS特殊语法8. 练习:99乘法表2、基本对象1. Function:函数(方法)对象…

上线3天,下载4万,ChatGPT 中文版VSCode插件来了

ChatGPT 的 Debug 功能,有人应用化了。 ChatGPT 这几天可谓是风头无两。作为一个问答语言模型,它最大的优点就是可以回答与编程相关的问题,甚至回复一段代码。 尽管有人指出 ChatGPT 生成的代码有错误,但程序员们还是对它写代码、…

图像配准开源数据集资源汇总

Brown 数据集 数据集下载链接:http://suo.nz/3042bh 数据集由 1024 x 1024 位图 (.bmp) 图像组成,每个图像包含一个 16 x 16 图像块阵列。每个补丁都被采样为 64 x 64 灰度,具有规范的比例和方向。 ETHZ Toys 数据集下载链接&#xff1a…

Java中的语法糖(真甜)

什么是语法糖(Syntactic sugar) 语法糖是一个计算机数据,特指在编程语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。 糖嘛&#xff0c…

08.DashBoard流监控配置

08.DashBoard流监控配置 每个服务提供者都需要实现actuator&#xff0c;才可以实现流量监控。 导入Maven依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId><…

【图像去噪】空域+频域滤波图像去噪【含GUI Matlab源码 914期】

⛄一、获取代码方式 获取代码方式1&#xff1a; 完整代码已上传我的资源&#xff1a;【图像去噪】基于matlab GUI空域频域滤波图像去噪【含Matlab源码 914期】 获取代码方式2&#xff1a; 通过订阅紫极神光博客付费专栏&#xff0c;凭支付凭证&#xff0c;私信博主&#xff0…

移动端防抓包实践

目录介绍 01.整体概述介绍 1.1 项目背景1.2 思考问题1.3 设计目标1.4 收益分析 02.市面抓包的分析 2.1 Https三要素2.2 抓包核心原理2.3 搞定CA证书2.4 突破CA证书校验2.5 如何搞定加解密2.6 Charles原理2.7 抓包原理图2.8 抓包核心流程 03.防止抓包思路 3.1 先看如何抓包3.2 …

C++计算机视觉库OpenCV在Visual Studio 2022的配置方法

本文介绍在Visual Studio 2022中配置、编译C 计算机视觉库OpenCV的方法。 1 OpenCV库配置 首先&#xff0c;我们进行OpenCV库的下载与安装。作为一个开源的库&#xff0c;我们直接在其官方下载网站&#xff08;https://opencv.org/releases/&#xff09;中进行下载即可&#x…

实现无入侵式C++代码mock工具

为了实现真正无侵入式的mock&#xff0c;我们基于开源Hook框架Frida-gum提供的API&#xff0c;利用C模板进行封装&#xff0c;作者编写了一个简单实用的mock工具&#xff0c;在此开源分享&#xff08;代码详见附录&#xff09;。背景在单元测试中&#xff0c;往往需要减少被测函…

如何实现高性能网络编程-ChatGPT怎么看

hi ,大家好&#xff0c;我是大师兄。听说最近chatgpt特别火&#xff0c;那我们邀请一下chatgpt如何实现&#xff1a;我们先来小试牛刀&#xff1a;刚开始用先用英文交流一下&#xff0c;然后试一下中文&#xff1a;元芳你怎么看&#xff1f;下期直播主题--网络编程 (如何实现高…

用 AWTK 和 AWPLC 快速开发嵌入式应用程序 (7)- 用状态机实现红绿灯

AWPLC 目前还处于开发阶段的早期&#xff0c;写这个系列文章的目的&#xff0c;除了用来验证目前所做的工作外&#xff0c;还希望得到大家的指点和反馈。如果您有任何疑问和建议&#xff0c;请在评论区留言。 1. 背景 AWTK 全称 Toolkit AnyWhere&#xff0c;是 ZLG 开发的开源…