说明
摘要:作为一个初学者,如何具有良好的编程风格呢? 以下编辑通过avr单片机介绍其C语言编程风格。
C语言编程风格介绍
1 .变量定义
定义变量时,前缀使用变量类型,然后使用表示变量用途的英语单词或缩写,并将每个单词或缩写的首字母大写。 前缀缩写如下:
无符号变量使用u8、u16、u32; 例如: unsigned char u8Temp;
有符号变量为s8、s16、s32; 例如: char s8Temp;
浮点数使用f32、d64; 例如: float f32Temp;
结构体变量使用st; 示例: struct Temp stTemp;
字符串变量使用s; 例如: char sTemp;
数组变量使用a; 示例: unsigned char aTemp[10];
指针变量使用p; 示例: unsigned char *pTemp;
枚举变量为e; 示例: enum Temp eTemp;
2 .宏定义
如何在宏定义中使用大写下划线。
3 .程序排版
1行程序的开始使用制表键进行对位,1行中途使用空格键进行对位。
这样可以防止在打开不同的编辑工具时代码混乱。
4 .写入注释
这里的注释分为函数头注释、程序中的代码注释,
函数标题注释使用以下格式
/*
*Name :
*描述:
*Created :
*Author :
*/
必须选择这四个项目,其他函数的搬入搬出参数等根据函数的需要适当增加。
5 .测试代码
在编程的同时,需要注意添加相应的测试代码。 这将减少以后测试代码时的工作量。
AVR c语言优秀的编程风格
文件结构
模块化程序应该有很好的程序结构。 AVR C语言程序包含两种类型的用户文件:c程序文件和. h头文件, c文件必须包含. h头文件。 初学者经常在重复包含和头文件中包含错误,我也为这个错误而烦恼。 用我写的电机驱动例程来说明。 很好的编程文件结构。
该项目包含8个文件、1个说明文件,下载程序示例电机控制盒,如下图所示。
我写的成型程序的文件数基本上是偶数。 因为每个结构化函数定义. c文件对应一个. h文件。 main.c对应于config.h。 让我们看看每个文件的包含关系。 让我们看看这些文件的包含关系和内容。 [建议的文件包含顺序和关系]
所有. c文件都包含config.h文件。 例如,#include “config.h”
config.h包含以下代码:
#include “delay.h”
#include “device_init.h”
#include “motor.h”
这样一来,就很难发生错误的包含关系,为了以防万一,还引入了宏定义和预编译。 如下所示。
#ifndef _UNIT_H__
#define _UNIT_H__ 1
//100us
Externvoiddelay100us(uint8n;
//1s
外部1s (uint 16n; //n(=6,when n==7,it is 1。
//1ms
Externvoiddelay1ms(uint16n;
#endif
第一次包含时正确编译,#define _UNIT_H__ 1,第二次包含时#ifndef _UNIT_H__不再成立,跳过文件。
预编译有更多用途,包括可以为每个值编译不同的语句,如下所示:
//#pragma REGPARMS
#if CPU_TYPE==M128
#include 《iom128v.h》
#endif
#if CPU_TYPE==M64
#include 《iom64v.h》
#endif
#if CPU_TYPE==M32
#include 《iom32v.h》
#endif
#if CPU_TYPE==M16
#include 《iom16v.h》
#endif
#if CPU_TYPE==M8
#include 《iom8v.h》
#endif
#include 《filename》和#include “filename”的区别:前者是包含系统目录的include下的文件,后者是程序目录下的文件。
变量名和函数名
还有变量
函数命名应该按照尽量短,按需长,具有实际意义。可以通过下划线或者大小写结合的方法组合动词和名词组成变量函数名。下面对比好的命名方法与不好的命名方法:1.好的: Delay100us();
不好的: Yanshi();
2.好的: init_devices();
不好的: Chengxuchushihua();
3.好的: int temp;
不好的: int dd;
外部调用
1.首先在模块化程序的.h文件中定义extern
//端口初始化
extern void port_init(void);
//T2初始化
void timer2_init(void);
//各种参数初始化
extern void init_devices(void);
2.模块化程序的.c文件中定义函数,不要在模块化的程序中调用程序,及不要出现向timer2_init();这样函数的使用,因为你以后不知道你到底什么地方调用了函数,导致程序调试难度增加。可以在定义函数的过程中调用其他函数作为函数体。
/**************************采用timer2 产生波形***********************/
// PWM频率 = 系统时钟频率/(分频系数*2*计数器上限值))
void timer2_init(void)
{
TCCR2 = 0x00; //stop
TCNT2= 0x01; //set count
OCR2 = 0x66; //set compare
TCCR2 = (1《《WGM20)|(1《《WGM21)|(1《《COM21)|0x06; // start timer 快速pwm模式,匹配清零,溢出置位 256分频
//占空比=高比低为:(OCR2-0X01)/(0XFF-OCR2) OX01++++++(OCR2)__________OXFF (+表示输出高,_表示输出低)
//即OCR2越大,输出越大
}
3.在少数几个文件中调用函数,在main.c中调用大部分函数,在interupts.c中根据不同的中断调用服务函数。
void main(void)
{
/******************************************************************************/
//初始工作
/******************************************************************************/
init_devices();
while(1)
{
for_ward(0); //默认速度运转 正
Delay1s(5); //延时5s
motor_stop(); //停止
Delay1s(5); //延时5s
back_ward(0); //默认速度运转 反
Delay1s(5); //延时5s
speed_add(20); //加速
Delay1s(5); //延时5s
speed_subtract(20); //减速
Delay1s(5); //延时5s
}
}
宏定义
宏定义主要用于两个地方:
1.一是用得非常多的命令或语句,利用宏将其简化。
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
#define MIN(a,b) ((a《b)?(a):(b))
#define MAX(a,b) ((a》b)?(a):(b))
#define ABS(x) ((x》)?(x):(-x))
typedef unsigned char uint8; /* 定义可移植的无符号8位整数关键字 */
typedef signed char int8; /* 定义可移植的有符号8位整数关键字 */
typedef unsigned int uint16; /* 定义可移植的无符号16位整数关键字 */
typedef signed int int16; /* 定义可移植的有符号16位整数关键字 */
typedef unsigned long uint32; /* 定义可移植的无符号32位整数关键字 */
typedef signed long int32; /* 定义可移植的有符号32位整数关键字 */
2.二是利用宏定义方便的进行硬件接口操作,再程序需要修改时,只需要修改宏定义即可,而不需要满篇去找命令行,进行修改。
//PD4,PD5 电机方向控制 如果更改管脚控制电机方向,更改PORTD |= 0x10即可。
#define moto_en1 PORTD |= 0x10
#define moto_en2 PORTD |= 0x20
#define moto_uen1 PORTD &=~ 0x10
#define moto_uen2 PORTD &=~ 0x20
//启动TC2定时比较和溢出
#define TC2_EN TIMSK |= (《《1OCIE2)|(1《《TOIE2)
//禁止TC2再定时比较和溢出
#define TC2_DIS TIMSK &=~ (1《《OCIE2)|(1《《TOIE2)
关于注释
为了增加程序的可读性,方便合作者读动程序,或者程序作者在一段时间之后还能看懂程序,我们需要在程序中写 注释。
在比较特殊的函数使用或者命令调用的地方加单行注释。使用方法为:
Tbuf_putchar(c,RTbuf); // 将数据加入到发送缓冲区并开中断
extern void Delay1s(uint16 n); // n 《= 6 ,when n==7, it is 1.
在模块化的函数中使用详细段落注释:
/***********************
** 函数名称: Com_putchar
** 功能描述: 从串行口输出一个字符c
** 输 入: c:输出字符
** 输出 : 0:失败 1:成功
** 全局变量: 无
** 调用模块:
** 说明:
** 注意:
********************/
在文件头上加文件名,文件用途,作者,日期等信息。
/*********************************************************************************************************
** serial driver
** (c) Copyright 2005-2006, limaokui
** All Rights Reserved
**
** V1.1.0
**
**
**--------------文件信息--------------------------------------------------------------------------------
**文 件 名:sio.c
**创 建 人: 粗暴的水池
**最后修改日期: 2005年7月13日
**描 述: serial driver
**
**--------------历史版本信息----------------------------------------------------------------------------
** 创建人: 粗暴的水池
** 版 本: V1.00
** 日 期: 2005年7月13日
** 描 述: 原始版本
**
*********************************************************************************************************/
要清楚,注释是为了方便阅读,增强程序的可度性,不要本末倒置,不要给很简单大家都能看明白的程序加注释,不要让注释淹没了你的程序结构。对于函数,变量等尽量使用文件名自注释的方法,及通过文件名就可以知道意思。
打开APP阅读更多精彩内容
点击阅读全文