前言:本系列教程旨在如何将自己的代码写的整洁,同时本系列参考 正点原子 , C++代码整洁之道,编写可读的代码艺术。
#函数的应用规范
#函数作用的功能
函数功能:函数应该只做一件事,做好这件事,只做这一件事,一个函数不应该被应用于多个功能,如果满足前者,这个函数就应该,被二次拆分,出更细致的功能,去简化这个函数,直到划分为每个功能单一的函数。
函数的第一规则是要短小,第二条规则是还要更短小,函数就该小。—————Clean Code
函数封装:将重复调用的代码,封装为功能单一的函数,进行调用,重复的代码,重复写不封装,浪费代码行,浪费阅读时间,封装之后,一行代码,能解决的事情,不用写那么多行,还能提升自己效率,封装函数在主程序循环中调用和没有进行封装调用,循环执行时间是不一样的,前者是比后者快的相对来讲。
函数嵌套:封装函数中,不要进行大量的循环判断嵌套,当在函数体中进行(if for while switch)应用这些语句的大量嵌套,那么别人读懂这个函数,就要思考很多函数对应的情况,如果没有理解这个函数,进行调用,就会出现问题,最后要进行排查,嵌套最好不要超过4层向上。
函数参数:自己定义地多参数函数,别人在调用的时候,可能需要 Ctrl+F仔细看每个参数的取值,是什么,函数的参数越少,在调用的时候,就越傻瓜式,就越省事,当然前提是,减少参数并不会影响功能。
最理想的参数数量是零,其次是单参数函数,在此是双参数函数——————Clean Code
#代码行的应用以及规范
代码长度:每行代码的长度应该限制在 80列,如果超过这个数,这句代码,后半句建议写到下一行 ,如果非要写很长,用很长的变量名,这样可读性会很差,同时在一些编辑器 IDE 里面是由行宽限制的。
perm_count_msg.head.len = NO7_TO_STAT_PERM_COUNT_LEN+ STAT_SIZE_PER_FRAM * sizeof( _UL ); ————————正点原子
函数间隔:调用不同的库函数之间,每个函数之间建议使用回车进行分隔,方便阅读。
int main(void)
{board_init();uart1_init(115200U);printf("start\r\n");PCA9685_Init(60,0); //PCA9685--16路舵机初始化 频率60Hz -- 0度delay_ms(1000);PID servo;//声明PID 结构体 变量PID_Init(&servo,Kp,Ki,Kd);//这几个宏定义在PID.h文件里面。while(1) {}}
声明变量按行写:一行声明多个变量,跟每行声明一个变量,可能有的小伙伴觉得前者比较省事情,但是这样写,不利于他人阅读。
int a = b =0;//不利于观看int a = 0;//推荐写法
int b = 0;
判断语句书写:if while for do case switch default 这些语句单独占一行,后面执行语句,不论有多少条,统一加 {} ,进行表示,判断语句单独占一行。
不规范的写法:
if (p_gpiox->IDR & pinx) return 1; /* pinx 的状态为 1 */
else return 0; /* pinx 的状态为 0 */
应改为:
if (p_gpiox->IDR & pinx)
{
return 1; /* pinx 的状态为 1 */
}
else
{return 0; /* pinx 的状态为 0 */
}
#变量的声明与使用
变量的用途:在声明变量的时候,应该不用或者少用,全局变量,或者使用static声明全局变量,作为文件的私有变量,全部变量应该是模块化的私有数据,不能作用为对外的接口,使用static定义全局变量可以防止,外部文件对定义文件的变量非正常访问。同时一个变量应该只用作一个用途。
一个变量只能有一个特定功能,不能把一个变量作为多用途使用,——————正点原子
int time;
time = 200; /* 表示时间 */
time = getvalue(); /* 用作返回值 */
//应改为下面的
int time,ret;
time = 200;
ret = getvalue();
#宏定义的使用
宏定义作用:大量使用宏定义,方便移植程序,提升程序运行速度,如果使用宏定义写的程序,移植的时候,一般只需要改头文件里面的宏定义就能,进行正常运行工作,同样一段程序,不写宏定义,那么可能每个参数都要从头改到尾,会造成时间上的浪费。
#ifndef _BSP_PCA9685_H_
#define _BSP_PCA9685_H_#include "stm32f4xx.h"//端口移植
#define RCC_PCA9685_GPIO RCC_AHB1Periph_GPIOA
#define PORT_PCA9685 GPIOA#define GPIO_SDA GPIO_Pin_5
#define GPIO_SCL GPIO_Pin_6//设置SDA输出模式
#define SDA_OUT() { \GPIO_InitTypeDef GPIO_InitStructure; \GPIO_InitStructure.GPIO_Pin = GPIO_SDA; \GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; \GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; \GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; \GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; \GPIO_Init(GPIOA, &GPIO_InitStructure); \}
//设置SDA输入模式
#define SDA_IN() { \GPIO_InitTypeDef GPIO_InitStructure; \GPIO_InitStructure.GPIO_Pin = GPIO_SDA; \GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; \GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; \GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; \GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; \GPIO_Init(GPIOA, &GPIO_InitStructure); \}
//获取SDA引脚的电平变化
#define SDA_GET() GPIO_ReadInputDataBit(GPIOA, GPIO_SDA)
//SDA与SCL输出
#define SDA(x) GPIO_WriteBit(GPIOA, GPIO_SDA, (x?Bit_SET:Bit_RESET) )
#define SCL(x) GPIO_WriteBit(GPIOA, GPIO_SCL, (x?Bit_SET:Bit_RESET) )#define PCA_Addr 0x80 //IIC地址
#define PCA_Model 0x00
#define LED0_ON_L 0x06
#define LED0_ON_H 0x07
#define LED0_OFF_L 0x08
#define LED0_OFF_H 0x09
#define PCA_Pre 0xFE //配置频率地址void PCA9685_Init(float hz,uint8_t angle);
void setAngle(uint8_t num,uint8_t angle);
void PCA9685_setFreq(float freq);
void PCA9685_setPWM(uint8_t num,uint32_t on,uint32_t off);#endif
除此之外,宏定义是预处理指令,这种指令的执行,实在程序执行之前,在程序编译之前,大量使用这种指令,会提升程序运行速度,这种指令在程序执行前就已经执行过了,能提升程序整体运行速度。
初次之外,二次封装库中的函数,完全可以用宏定义函数来代替,不用在程序中进行封装,宏定义一行就能搞定的事情,模块文件中,封装在声明,没必要写那么多行。
//错误写法,写了之后还要声明函数。
void SDA(x)
{
GPIO_WriteBit(GPIOA, GPIO_SDA, (x?Bit_SET:Bit_RESET) );
}void SCL(x)
{
GPIO_WriteBit(GPIOA, GPIO_SDA, (x?Bit_SET:Bit_RESET) );
}
//正确写法宏定义声明函数
//这种写发程序执行速度比较块
#define SDA(x) GPIO_WriteBit(GPIOA, GPIO_SDA, (x?Bit_SET:Bit_RESET) )
#define SCL(x) GPIO_WriteBit(GPIOA, GPIO_SCL, (x?Bit_SET:Bit_RESET) )
欢迎指正,希望对你,有所帮助!!!