嵌入式应用开发之代码整洁之道
前言:本系列教程旨在如何将自己的代码写的整洁,同时也希望小伙伴们懂如何把代码写脏,以备不时之需,同时本系列参考 正点原子 , C++代码整洁之道,编写可读的代码艺术。
#好的代码的特点
好的代码应该都有着几条特性,可读性高(根据函数命名就知道这个函数是干啥的),简单(没有复杂的变量英文名,大量调用库中封装函数)。
方便维护(别人在你的代码上加功能好加,好上手),好移植(头文件大量书写宏定义 移植只需要改宏定义引脚即可),函数功能单一精简(函数定义几百行,参数很多,永远 没有 十几行函数代码的好理解)。
调用函数库统一,(没有二次封装函数,没有带位操作跟库函数混着用),没有带位操作,(程序中统一调用库函数)带位操作确实快,现对于库函数,但是不好上手,没有重新编写函数(如果放着现有的库函数不用,重新赋值寄存器,写新函数,还没有根据功能命名)
上述的这些都是,好的代码的特点,接下来将从,每个类型的变量书写规范开始讲解。
#函数的命名
函数的命名,应该把信息或者注释装进命名里面,同时每个单词使用下划线 "_" 进行连接,,让在读函数命名的同时,就知道你这个函数是什么作用,什么功能,大致看一下函数体,就行了。
void SPI_GPIO_Init(void);
这个函数名,即使不看函数体,也知道这个函数用来将 SPI通信用到的GPIO 初始化,那么如何将代码命名进行规范化。
翻译命名:将这个函数的功能,翻译成英文在命名里面加入英文的缩写,去表示。
外设命名:如果用到对应的外设,可以在命名中加入所用到的外设。
寄存器命名:这个函数里面用到了什么寄存器,什么参数也能写到函数名里面。
#代码注释写给别人看也写给自己看
代码注释不仅仅可以,用来解释这一行代码什么意思做了什么,最重要的是让读你代码的人知道你的写码思想,你此时在关联什么,你在想什么,你要用这些代码去干什么,完成什么,
当自己编写代码的时候,肯定知道自己写这些代码是为了完成什么功能,去怎么应用在需求上,别人读代码,只有眼前每行代码的作用,注释在这个时候,可以是思维,可以是目的。可以是关联应用。
#什么不需要注释
注释在程序中,并不是越多越好的,大量的注释无关紧要的地方,会造成浪费时间,去阅读这些注释,占用屏幕空间,这些注释相对来说是没有价值的。
void Usart_GPIO_Init(void){GPIO_InitTypeDef GPIO_InitStructure;//声明结构体变量 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//开启时钟 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//开启复用功能GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//TX引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//IO口用作串口引脚要配置复用模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//选择速度GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//RX引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//IO口用作串口引脚要配置复用模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//选择速度GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//推挽输出GPIO_Init(GPIOA,&GPIO_InitStructure);
}
上述这些注释是没有价值的,为什么,因为没有提供额外的信息,这些作用能从函数里面读出来,就可以不用去加,写这么多注释是会影响效率的。
总结:不要为代码本身能读出来的信息写注释
同时不要为了写注释,而去注释,总有小伙伴认为,一定要写注释,为了写注释去写注释,从而忽略了写注释本身的作用,写注释是为了更好的理解工程,而不是写没有意义的注释,浪费读你注释的人的时间。
#什么需要注释
注释本身就是一种信息,这种信息不是关于函数功能的信息,这些信息可以加入见解,可以使各种有关经验之谈,可以是别人不知道代码的瑕疵,缺陷,也可以是站在读你代码的人角度写注释,或者解释为什么选择A方案,而不是B方案。
#ifndef _pid_h_
#define _pid_h_
#include <stdio.h>
#include "board.h"
//编写PID应在云台中调用
#define Kp 5.0
#define Ki 5.0
#define Kd 5.0
//这里参数设定有问题,云台抖动
typedef struct
{float Velcity_Kp;float Velcity_Ki;float Velcity_Kd;float Error;float Last_Error;float integral;float derivate;int Control_Velocity;
}PID;
void PID_Init(PID*pid, float Velcity_Kp ,float Velcity_Ki,float Velcity_Kd);
float PID_Calculate (PID*pid,float Current_Velocity ,float TargetVelocity);
#endif
上述这些出函数本身带来的信息,是值得去注释的,这些是对于读你代码的人是有用的,是有价值的信息。
#代码缩进问题
使用TAB进行缩进的时候,这个键的值可能是4位或者是8位,有的小伙伴上面缩进4跟下面8个,随便缩进,反正不会报错,看着确实难受,如果使用文本方式打开,驱动文件,可以发现是跟在KEIL5中阅读的缩进大小是不一样的。
如果代码被不同的编译器打开,缩进效果,也是不一样的,但是如果使用 空格键 代替缩进在大多数编译平台看到的区别都是不大的。

这里在KEIL5中是4位缩进,下面使用VSCODE打开相同的源文件

可以看到这里就变成了8位缩进,只是因为使用的编译器不同,导致效果就不一样了,同时附带着汉字乱码(改编码格式)。
总结:如果代码经常移植,建议缩进使用空格代替。
欢迎指正,希望对你有所帮助!!!
相关文章:
嵌入式应用开发之代码整洁之道
前言:本系列教程旨在如何将自己的代码写的整洁,同时也希望小伙伴们懂如何把代码写脏,以备不时之需,同时本系列参考 正点原子 , C代码整洁之道,编写可读的代码艺术。 #好的代码的特点 好的代码应该都有着几…...
iwconfig iwpriv学习之路
iwconfig和iwpriv是两个常用的wifi调试工具,最近需要使用这两个工具完成某款wifi芯片的定频测试,俗话说好记性不如烂笔头,于是再此记录下iwconfig和iwpriv的使用方式。 -----再牛逼的梦想,也抵不住傻逼般的坚持! ----2…...
【Docker-compose】搭建php 环境
文章目录 Docker-compose容器编排1. 是什么2. 能干嘛3. 去哪下4. Compose 核心概念5. 实战 :linux 配置dns 服务器,搭建lemp环境(Nginx MySQL (MariaDB) PHP )要求6. 配置dns解析配置 lemp Docker-compose容器编排 1. 是什么 …...
【记录】LaTex|LaTex 代码片段 Listings 添加带圆圈数字标号的箭头(又名 LaTex Tikz 库画箭头的简要介绍)
文章目录 前言注意事项1 Tikz 的调用方法:newcommand2 标号圆圈数字的添加方式:\large{\textcircled{\small{1}}}\normalsize3 快速掌握 Tikz 箭头写法:插入点相对位移标号node3.1 第一张图:插入点相对位移3.2 第二张图࿱…...
《框架封装 · Redis 事件监听》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
小白学webgl合集-Three.js加载器
THREE.TextureLoader: 用途: 加载单个图像文件并将其作为纹理应用到材质上。示例: const loader new THREE.DataTextureLoader(); loader.load(path/to/data.bin, function (texture) {const material new THREE.MeshBasicMaterial({ map: texture });const geometry new TH…...
【算法】字符串的排列
难度:中等 给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。 换句话说,s1 的排列之一是 s2 的 子串 。 示例 1: 输入:…...
5-3.损失函数
文章最前: 我是Octopus,这个名字来源于我的中文名–章鱼;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github ;这博客是记录我学习的点点滴滴,如果您对 Python、Java、AI、算法有兴趣,可以关注我的…...
SCSA第四天
ASPF FTP --- 文件传输协议 Tftp --- 简单文件传输协议 FTP协议相较于Tftp协议 ---- 1,需要进行认证 2,拥有一套完整的命令集 用户认证 防火墙管理员认证 ---- 校验登录者身份合法性 用户认证 --- 上网行为管理中的一环 上网用户认证 --- 三层认证…...
品牌策划必读:9本改变游戏规则的营销经典
作为深耕品牌十余年的策划人,这些年自学啃下的书不计其数。 这里特意挑选了几本知名度不高但是却非常有用的“遗珠”优质品牌策划书籍分享出来。 如果你是一位初步了解品牌的人,这些书籍既包含了品牌理论基础,也有实用的实践指导。 这些书…...
泛型
背景 优点 类型绝对安全避免强制类型转换 泛型类 定义 使用 举例 泛型类 // 泛型类 T就是类型参数 public class Generic<T>{// key这个成员变量的类型为T,T的类型由外部指定private T t;public void set(T t){this.t t;}public T get(){return t;} }使用 // 创建一个泛…...
react动态渲染列表与函数式组件
1.如何使用jsx语法动态渲染列表呢,下边我用一个例子来切实总结一下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scal…...
小程序内容管理系统设计
设计一个小程序内容管理系统(CMS)时,需要考虑以下几个关键方面来确保其功能完善、用户友好且高效: 1. 需求分析 目标用户:明确你的目标用户群体,比如企业、媒体、个人博主等,这将决定系统的功…...
HDFS 块重构和RedundancyMonitor详解
文章目录 1. 前言2 故障块的重构(Reconstruct)2.1 故障块的状态定义和各个状态的统计信息2.2 故障文件块的查找收集2.5.2.1 misReplica的检测2.5.2.2 延迟队列(postponedMisreplicatedBlocks)的构造和实现postponedMisreplicatedBlocks中Block的添加postponedMisreplicatedBloc…...
Power BI DAX常用函数使用场景和代码示例
Power BI函数表达式对于没有接触过的朋友可能会有些迷茫,花一点时间了解一下原理在学习一些常用的DAX函数,就可以解决工作中绝大部分问题,函数使用都是共同的。 以下是一些最常用的DAX函数,如聚合,计数,日期…...
机器学习与深度学习:区别与联系(含工作站硬件推荐)
一、机器学习与深度学习区别 机器学习(ML:Machine Learning)与深度学习(DL:Deep Learning)是人工智能(AI)领域内两个重要但不同的技术。它们在定义、数据依赖性以及硬件依赖性等方面…...
大模型/NLP/算法面试题总结5——Transformer和Rnn的区别
Transformer 和 RNN(循环神经网络)是两种常见的深度学习模型,广泛用于自然语言处理(NLP)任务。 它们在结构、训练方式以及处理数据的能力等方面有显著的区别。以下是它们的主要区别: 架构 RNN࿰…...
【RHCE】转发服务器实验
1.在本地主机上操作 2.在客户端操作设置主机的IP地址为dns 3.测试,客户机是否能ping通...
AI提示词:打造爆款标题生成器
打开GPT输入以下内容: # Role 爆款标题生成器## Profile - author: 姜小尘 - version: 02 - LLM: Kimi - language: 中文 - description: 利用心理学和市场趋势,生成吸引眼球的自媒体文章标题。## Background 一个吸引人的标题是提升文章点击率和传播力…...
skywalking-1-服务端安装
skywalking很优秀。 安装服务端 skywalking的服务端主要是aop服务,为了方便查看使用还需要安装ui。另外采集的数据我们肯定要存起来,这个数据库就直接用官方的banyandb。也就是aop、ui、banyandb都使用官方包。 我们的目的是快速使用和体验,…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
