本专栏适合什么人群?
- 需要找一个项目做毕业设计(学士硕士)的做做,这个项目可以优选,都可以从本专栏中得到实现项目功能的代码,只需要简单的变通,就能实现各式各样的功能!!!
- 需要找一个项目作为课程设计的,可以选用本教程的阶段性成果,在每个阶段都会有现成的代码,可直接使用!!!
- 刚毕业大学生,物联网工程专业、电子工程专业等,对学习的知识不是很了解,想找一个项目练练手,那么这个专栏是你的不二之选。
专栏特色
本专栏涉及到代码的小节,都会以压缩包的形式将代码打包好贡献给各位读者,还会有详细的视频教各位如何运行,由于 CSDN 不允许上传视频,专栏以 QQ 群的方式,向各位读者提供讲解视频和答疑,关注《柴头物联网》公众号,点击“找到柴头”,拿到 QQ 二维码,扫码添加,拉您进群。
1. 本小节介绍?
在嵌入式领域开发,肯定烧不了 C语言的代码编写,从前我们创建文件、编写代码都是一切从简,如何方便如何来,这样的好处是可以快速的完成一个功能,但是会带来代码可读性下降、团队协作困难、代码质量下降等等问题。
在本小节会介绍嵌入式领域开发的规范,从工程命名、文件命名、变量命名多个方面进行介绍。
2. 工程及文件命名
项目的工程名称可以以组织_项目名称_ 单片机
的方式进行命名,比如智能取餐柜,可以翻译为SmartMealBot
,组织为CT
,单片机为STM32
那么工程名称可以为CT_SmartMealBot_STM32
,那么就可以知道,该项目是用 STM32 开发的一个智能取餐柜项目。
在讲到文件的命名之前,我们需要先提到嵌入式软件架构的分层,简单的可以分为:
- 内核层
- 驱动层
- 服务层
如果有使用到操作系统,可以分为:
- 内核层
- 驱动层
- 服务层
- 中间层(操作系统)
每一个层都是直接调用一个或多个下一层,这句话要怎么理解呢?
以下例子都是以简单分层,也就是没有中间层(操作系统)
其实很简单,解释如下:
- 业务层,调用一个或者多个服务层完成一个业务
- 服务层,调用一个或者多个驱动层完成一个服务
- 驱动层,调用一个或者多个内核完成一个驱动
到此,我们已经对软件分层有了一定的了解,接下来我们要大概知道每个层次是干嘛的,同时我们需要创建一些文件,以层_模块名称
命名文件:
- 内核层,一般是厂家提供的,也就是对硬件的最底层控制,可以是寄存器的封装等等
- 驱动层,是我们自己写的第一个层,比如我要初始化控制 LED 灯 IO 引脚的功能,就需要在此处创建文件,
drive_led.h
drive_led.c
,在.c
文件中完成对 IO 引脚的初始化,这个时候肯定是需要调用到内核层的,在这一层,只能做 IO 引脚的初始化,并提供控制函数,例如提供dLedInit()
dLedHigh()
dLedLow()
-
dLedInit
初始化 IO 引脚dLedHigh
将 IO 口输出高电平dLedLow
将 IO 口输出低电平
- 服务层,在服务层就需要调用驱动层中的函数,先创建文件
service_led.c
service_led.h
,接着我们需要调用驱动层中的函数实现我们的功能,在 LED 的服务层中,我们应该是有开灯和关灯的操作,还有 LED 灯的初始化操作,那么需要创建sLedInit()
sLedOpen()
sLedClose()
,也有可能会有一个快闪的操作,比如sLedBlink2
-
sLedInit()
初始化 LED 灯,通过调用dLedInit
sLedOpen()
开启 LED 灯,通过调用dLedHigh
或dLedLow
,这是因为并不是所有的 LED 输出都是高电平触发,有的就是需要输出低电平触发,这取决于硬件电路的设计sLedClose()
关闭 LED 灯sLedBlink2
两次快闪操作
void sLedBink2(){
// ...
}
3. 方法的命名
从上面的例子中,我们可以得出方法的命名规则了如下
按照层次的缩写再加上模块加上功能,层次_模块_功能
,例如sLedBlink
功能为在服务层的 led 闪烁。
层次:
- drive:可以简写为
e
- service:可以简写为
s
当然除了以上提到的层,还有其他的工具层utils
,文件的命名可以如下util_string.c
这样一看就知道是用于 string
字符串的命名了。
4. 函数命名以及变量
那么我们已经知道了,方法的命名,接下来就要开始介绍函数命名已经变量了。
4.1. 总体风格
大小写字母混用,单词连在一起,不同单词间通过单词首字母大写来分开.
按连接后的首字母是否大写,又分: 大驼峰(UpperCamelCase)和小驼峰(lowerCamelCase)
4.2. 标识符命名使用驼峰风格
类型 | 命名风格 |
函数,结构体类型,枚举类型,联合体类型 | 大驼峰 |
变量,函数参数,宏参数,结构体中字段,联合体中成员 | 小驼峰 |
宏,常量,枚举值,goto 标签 | 全大写,下划线分割 |
注意:
上表中常量
是指,全局作用域下,const 修饰的基本数据类型、枚举、字符串类型的变量,不包括数组、结构体和联合体.
上表中变量
是指除常量定义以外的其他变量,均使用小驼峰风格.
4.3. 全局变量
全局变量应增加g
前缀,例如
uint8_t gCount=10;
4.4. 类型命名
类型命名采用大驼峰命名风格,类型包括结构体、联合体、枚举类型名。
例:
struct ColorMessage {
enum Color type;
int msgLen;
};
enum Color {
RED,
GREEN,
BLUE
};
4.5. 宏、常量、枚举命名
宏、枚举值采用全大写,下划线连接的格式,常量推荐采用全大写,下划线连接风格。
作为全局变量,也可以保持与普通全局变量命名风格相同。
这里常量如前文定义,是指基本数据类型、枚举、字符串类型的全局 const 变量,函数式宏,命名风格,采用全大写,下划线连接风格。
宏举例:
#define PI 3.14
#define MAX(a, b) (((a) < (b)) ? (b) : (a))
#ifdef SOME_DEFINE
void Bar(int);
#define Foo(a) Bar(a) // 特殊场景,用大驼峰风格命名函数式宏
#else
void Foo(int);
#endif
常量举例:
const int VERSION = 200; // OK.
const enum Color DEFAULT_COLOR = BLUE; // OK.
const char PATH_SEP = '/'; // OK.
const char * const GREETINGS = "Hello, World!"; // OK.
5. 结语
本小节介绍了嵌入式开发中 C 语言规范的部分内容,在编写代码时有其他的建议和规范,写到再提到。
不过相信读到这里的这位读者,肯定是一位很好的协同开发伙伴,因为你对格式的规范有很高的要求。
好的规范能在开发中提高效率,让人心情愉悦。