【52】单片机编程核心技巧:sizeof 宏函数的深度解析与实战应用

【51】单片机编程核心技巧:sizeof 宏函数的深度解析与实战应用

七律 · 字节计算巧

字节计算巧运用,宏函数功不可没。
内存分配无差错,数组合并自成说。
编译预处理妙,代码优化显神通。
单片机编程利器,宏的精髓在其中。


关键字

sizeof宏函数, 内存管理, 数组合并, C语言, 模块化编程


引言

在单片机开发中,精准控制内存占用是优化程序性能的关键。sizeof宏函数通过编译期计算变量或数组的字节大小,避免人工计算的繁琐与错误。本文系统阐述sizeof宏函数在单片机编程中的核心作用,涵盖基础原理、代码实现及工程应用。通过数组合并案例,演示如何利用sizeof实现动态内存管理,提升代码可维护性。文档提供分层代码架构、详细注释及测试流程,帮助开发者快速掌握内存优化技巧。


硬件设计

内存结构与寄存器配置
  1. 内存分区
    • ROM:存储代码及常量数据(如code unsigned char d[9];)。
    • RAM:存储变量数据(如unsigned char a[2];)。
  2. 寄存器配置
    • 端口初始化需配置GPIO方向寄存器(如P0SEL控制端口功能)。
    • 串口通信需配置SCON寄存器(SCON=0x50启用模式1)。
硬件连接示例
单片机P0口
LED指示灯
单片机UART_TX
USB转TTL模块

软件配置

分层架构设计
  1. BSP层
    • bsp_uart.c:串口初始化与数据发送函数。
  2. 驱动层
    • drv_merge_array.c:数组合并逻辑实现。
  3. 应用层
    • main.c:调用驱动函数并验证结果。
依赖关系
main.c
drv_merge_array.c
bsp_uart.c

代码实现

核心代码示例
#include "reg52.h"  // 定义原始数组(BSP层)  
unsigned char array_a[2] = {1, 2};  
unsigned char array_b[3] = {3, 4, 5};  
unsigned char array_c[4] = {6, 7, 8, 9};  // 自动计算合并数组容量(驱动层)  
unsigned char merged_array[sizeof(array_a) + sizeof(array_b) + sizeof(array_c)];  /**  * @brief 串口数据发送函数  * @param data 待发送字节  */  
void bsp_uart_send(unsigned char data) {  SBUF = data; // 写入发送缓冲区  while (!TI); // 等待发送完成  TI = 0;      // 清除发送标志  
}  void main() {  unsigned char i;  // 合并数组逻辑(应用层)  for (i = 0; i < sizeof(array_a); i++) {  merged_array[i] = array_a[i]; // 直接写入array_a  }  for (i = 0; i < sizeof(array_b); i++) {  merged_array[i + sizeof(array_a)] = array_b[i]; // 偏移array_a的字节数  }  for (i = 0; i < sizeof(array_c); i++) {  merged_array[i + sizeof(array_a) + sizeof(array_b)] = array_c[i]; // 累加偏移量  }  // 验证输出  for (i = 0; i < sizeof(merged_array); i++) {  bsp_uart_send(merged_array[i]); // 发送数据到电脑  }  while (1); // 无限循环  
}  
代码规范说明
  1. 变量命名
    • array_amerged_array:英文小驼峰命名。
    • g_uart_baud:全局变量加g_前缀。
  2. 函数注释
    • 使用/** */格式描述功能、参数及返回值。

测试验证

硬件连接要求
  1. 硬件准备
    • STC89C52单片机开发板。
    • USB转TTL模块(连接UART_TX至电脑)。
  2. 配置步骤
    • 确保SCON=0x50启用串口模式1。
    • 波特率设置为9600bps(TH1=0xFD)。
预期结果

通过串口助手观察输出:

1 2 3 4 5 6 7 8 9  
调试方法
  1. 数据不完整:检查merged_array容量计算是否正确。
  2. 偏移错误:验证sizeof累加逻辑(如sizeof(array_a) + sizeof(array_b))。

文件结构建议

STC8_Project/  
├── Projects/          // Keil工程文件(.uvproj)  
├── Drivers/           // 驱动层代码  
│   ├── BSP/           // 硬件抽象  
│   │   └── bsp_uart.c // 串口驱动  
│   └── Module/        // 功能模块  
│       └── drv_merge_array.c // 数组合并逻辑  
├── User/              // 应用层代码  
│   └── main.c         // 主程序  
├── Inc/               // 头文件  
│   └── config.h       // 宏定义配置  
└── Core/              // 芯片核心文件  └── reg52.h        // 寄存器定义  

扩展应用

  1. 结构体内存计算

    struct Device {  uint8_t id;      // 1字节  uint16_t data;   // 2字节  uint32_t flags;  // 4字节  
    };  
    printf("结构体占用字节数:%d", sizeof(struct Device)); // 输出7字节  
    
  2. 动态内存分配

    uint8_t *p = (uint8_t*)malloc(sizeof(array_a)); // 分配与array_a相同大小的内存  
    memcpy(p, array_a, sizeof(array_a)); // 复制数据  
    free(p); // 释放内存  
    

总结

sizeof宏函数通过编译期计算,显著提升代码可维护性与效率。本文通过数组合并案例,展示了其在内存管理中的核心作用。掌握这一技巧,开发者可更高效地控制单片机资源,减少人工计算错误,为复杂项目奠定基础。


附录:代码流程图

主函数
初始化数组
计算merged_array容量
合并数组元素
发送数据到串口
无限循环

附录:代码流程图

主函数
初始化数组
计算merged_array容量
合并数组元素
发送数据到串口
无限循环

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

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

相关文章

【CSS3】04-标准流 + 浮动 + flex布局

本文介绍浮动与flex布局。 目录 1. 标准流 2. 浮动 2.1 基本使用 特点 脱标 2.2 清除浮动 2.2.1 额外标签法 2.2.2 单伪元素法 2.2.3 双伪元素法(推荐) 2.2.4 overflow(最简单) 3. flex布局 3.1 组成 3.2 主轴与侧轴对齐方式 3.2.1 主轴 3.2.2 侧轴 3.3 修改主…

百度自动驾驶:我的学习笔记

自动驾驶新人之旅(9.0版) 第一课&#xff1a;初识自动驾驶技术 1. 自动驾驶技术概述 2. 自动驾驶人才需求与挑战 3. 如何使用Apollo学习自动驾驶[上机学习] 4. 如何使用Apollo学习自动驾驶[上车学习] 第二课&#xff1a;入门自动驾驶技术 1. Apollo车云研发流程 2. Lin…

并发编程之FutureTask.get()阻塞陷阱:深度解析线程池CPU飚高问题排查与解决方案

FutureTask.get方法阻塞陷阱&#xff1a;深度解析线程池CPU飚高问题排查与解决方法 FutureTask.get()方法阻塞陷阱&#xff1a;深度解析线程池CPU飚高问题排查与解决方法1、情景复现1.1 线程池工作原理1.2 业务场景模拟1.3 运行结果1.4 发现问题&#xff1a;线程池没有被关闭1.…

记录vite引入sass预编译报错error during build: [vite:css] [sass] Undefined variable.问题

vite.config.ts resolve: {alias: {: path.resolve(__dirname, src),},},css: {// css预处理器preprocessorOptions: {scss: {additionalData: use "/assets/styles/block.scss" as *;,}}},block.scss $colorGreen: #00ff00;index.vue :v-deep .font-size-14{colo…

代码小练习

public class Test3 {public static void main(String[] args) throws ParseException {ArrayList<Integer> listnew ArrayList<>();Scanner scnew Scanner(System.in);while (true){System.out.println("请输入一个整数");String s sc.nextLine();int…

百人会上的蔚小理与「来的刚刚好」的雷军

这就是2025百人会上的蔚小理&#xff0c;努力的李斌、宣扬飞行汽车的何小鹏与大讲开源的李想。那么小米汽车的模式是什么呢&#xff1f;站在蔚小理的肩上。 这就是2025百人会上的蔚小理&#xff0c;努力的李斌、宣扬飞行汽车的何小鹏与大讲开源的李想。那么小米汽车的模式是什么…

日程公布| 第八届地球空间大数据与云计算前沿大会与集中学习(3号通知)

日程公布| 第八届地球空间大数据与云计算前沿大会与集中学习&#xff08;3号通知&#xff09; 日程公布| 第八届地球空间大数据与云计算前沿大会与集中学习&#xff08;3号通知&#xff09;

<em>赚</em><em>钱</em><em>彩</em><em>票</em><em>软</em><em>件</em>

&#xff1c;em&#xff1e;赚&#xff1c;/em&#xff1e;&#xff1c;em&#xff1e;钱&#xff1c;/em&#xff1e;&#xff1c;em&#xff1e;彩&#xff1c;/em&#xff1e;&#xff1c;em&#xff1e;票&#xff1c;/em&#xff1e;&#xff1c;em&#xff1e;软&#xf…

随机2级域名引导页HTML源码

源码介绍 随机2级域名引导页HTML源码,每次点进去都随机一个域名前缀。 修改跳转域名在 350 行代码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行 效果预览 源码免费获取 随机2级域名引导页…

入栈操作-出栈操作

入栈操作 其 入栈操作 汇编代码流程解析如下&#xff1a; 出栈操作 其 出栈操作 汇编代码流程解析如下&#xff1a;

B3637 最长上升子序列

题目链接&#xff1a; 代码如下&#xff1a; #include<bits/stdc.h> #define int long long using namespace std; const int N 5050;int n; int arr[N]; int dp[N]; //dp数组signed main(){cin >> n;for(int i 1; i < n; i) cin >> arr[i];for(int i…

vscode通过root远程连接wsl

参考&#xff1a;vscode远程wsl时默认用root登录_vscode wsl root-CSDN博客

硬件基础--14_电功率

电功率 电功率:指电流在单位时间内做的功(表示用电器消耗电能快慢的一个物理量)。 单位:瓦特(W)&#xff0c;简称瓦。 公式:PUI(U为电压&#xff0c;单位为V&#xff0c;i为电流&#xff0c;单位为A&#xff0c;P为电功率&#xff0c;单位为W)。 单位换算:进位为1000&#xff…

【云服务器 | 下载 FFmpeg】云服务器上下载 ffmpeg + 配置

文章目录 FFmpeg 下载报错&#xff1a;已加载插件&#xff1a;fastestmirror1. 压缩包上传至服务器2. 解压3. 配置4. 添加FFmpeg到环境变量5. FFmpeg的配置5.1 安装 NASM5.2 安装x264 总结 可以看该博客&#xff0c;跟着这个步骤来的&#xff1a;https://blog.csdn.net/Aarstg/…

逆向--ARM64汇编

一、查看寄存器值 bl指令&#xff08;函数调用 bl的时候ret这个才有效&#xff09; 二、 bl 和lr 配合使用才达到函数调用的作用

【wow-rag系列】 task05 Ollama+llamaIndex+流式部署页面

文章目录 1.构建问答引擎2.构建基于FastAPI的后台3.构建流式输出的前端 1.构建问答引擎 新建一个engine.py文件 import os from llama_index.core.node_parser import SentenceSplitter# --------------------- # step 1.设定key、模型url、推理模型名称以及embedding模型名称 …

瑞芯微RKRGA(librga)Buffer API 分析

一、Buffer API 简介 在瑞芯微官方的 librga 库的手册中&#xff0c;有两组配置 buffer 的API&#xff1a; importbuffer 方式&#xff1a; importbuffer_virtualaddr importbuffer_physicaladdr importbuffer_fd wrapbuffer 方式&#xff1a; wrapbuffer_virtualaddr wrapb…

pycharm虚拟环境项目转移后配置解释器

添加解析器提示&#xff1a;无效的 Python SDK 解决方法 在到电脑安装python解析器&#xff0c;复制&#xff1a;python.exe和pythonw.exe 项目虚拟环境venv/Scripts Python解释器添加 项目现有虚拟环境&#xff0c;就可以正常使用

【智能体系统AgentOS】核心九:MCP工具

MCP&#xff08;Master Control Program&#xff09;是计算机控制系统中的核心部分&#xff0c;负责协调和管理整个系统的功能模块。不同的MCP可能会根据具体的应用场景有所不同&#xff0c;但通常有以下几类功能模块&#xff1a; 1. 输入输出&#xff08;I/O&#xff09;模块…

强化学习课程:stanford_cs234 学习笔记(2)introduction to RL

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言5、强化学习课程大纲5.1 课程内容主&#xff1a;5.2 马尔可夫决策过程&#xff1a;5.2.1 马尔可夫性 markov propterty5.2.2 马尔可夫过程 markov process5.2.3…