没有合适的资源?快使用搜索试试~ 我知道了~
首页嵌入式C语言进阶之道.pdf
资源详情
资源评论
资源推荐

嵌入式 C 进阶之道
版本:V1.0
瓶盖
水羽哥(蝈蝈)
2010-8-31(发布)

前言
C语言的书有一大堆,嵌入 C 语言的书也不少,但都不过是简单介绍一下标准 C 语言的
语法,再讲一下嵌入式 C 语言与标准 C 的区别,讲一下新增加的关键字。这样的书,对于
初学者或许是适合的。问题是,若是我不愿意只是当一个小菜鸟,我想对嵌入式 C 语言有
更多更深的了解时,我突然发现,满图书馆的书,竟找不到一本,能解我心头之惑。
对于在实际工作当中, 你不再是独自编写程序,你要和小组内的成员之间分工合作,你
要学会模块化编程、要写出更规范更安全的代码、做更合理的优化、减少更多的 bug。所有
的这些,都迫使你必须更彻底的理解嵌入式 C 的语法结构,数据细节,与硬件打交道的特
性,使得你必须时时考虑硬件与 C 的对应关系并养成良好的编程习惯。
本文的原意是想尽可能多的解决上述问题,帮助更多的新人深入理解嵌入式 C 语言。
本文是我工作之余整理而来。是对我个人学习嵌入式 C 语言过程的总结。本文涉及的
知识点多数来自于网络,其中加入我个人理解以及自己平时遇到的注意点。
本文从编程风格谈起,讲述了模块化的编程方法,对一些大型项目中常用重点关键字做
了讲解,参照 MISRA C 2004 规范 ,对嵌入式 C 安全编程做了阐述,对一些嵌入式 C 的小技
巧进行了讨论。
在读本文时,我假设你有 C 语言基础、至少理解一种微控制器(51、PIC、AVR、DSP、
ARM 等)、有简单的(这里本想写较深的)汇编基础。
声明:本人不拥有该文档的版权,任何人可随意传播。本人不对文中任何事物负责,(呵呵,
工作比较忙,交流尽量通过邮箱),但会不定期发布新版本以改正前版的不足。希望本文能
帮助一些热爱嵌入式编程的新人们,所以,如果您有更好的建议、发现本文档的错误,请将
以上详细信息发到我邮箱,我会在新版本后面,注明您的名字(或者网名)。希望广大的嵌
入式爱好者们能共同努力,为后来者们铺一个更平坦的大道。
我的邮箱:zhzhchang@126.com
技术博客:http://blog.csdn.net/zhzht19861011
瓶盖
水羽哥
2010-7-9

养成良好的编程风格
1 / 7
一.良好的编程风格
编程的总则: 编程首要是要考虑程序的可行性,然后是可读性、可移植性、健壮性以及
可测试性。大多数程序员只是关注程序的可行性,而忽略了可读性,可移植性和健壮性,其实
我个人认为,程序的可行性和健壮性与程序的可读性有很大的关系,能写出可读性很好的程
序的程序员,他写的程序的可行性和健壮性必然不会差,也会有不错的可移植性.程序的可读
性需要程序员有一个良好的编程风格.
好风格应该成为一种习惯。如果你在开始写代码时就关心风格问题,如果你花时间去审
视和改进它,你将会逐渐养成一种好的编程习惯。一旦这种习惯变成自动的东西,你的潜意
识就会帮你照料许多细节问题,甚至你在工作压力下写出的代码也会更好。
1.排版
a. 代码缩进空格数为4个。若是可能,尽量用空格来代替Tab键,因为有些编译器不支持Tab
键(我自己至今未见过,但确实有这个风险),这给程序的移植带来了问题。在keil中这个
问题很容易解决,只需在在keil主界面的菜单栏点击Edit—Configuration…,弹出
Configuration窗口,点击Editor标签,在其中C/C++ File:、ASM、Other Files栏下,选
中Insert spaces for tab:复选框,Tab对应的框中填4,这样按tab键就相当于按下四个空
格键。
BOOL BufClr(UINT8 * dest,UINT32 size)
{
if(NULL ==dest || NULL==size)
{
return FALSE;
}
}
b. 较长的语句要分2行来书写,并用‘\’符号隔开。
uncrc=calcCRC16(Packet.p,unlen);
if((UINT8) uncrc != Packet.down_ser.mCrc[0] \
||(UINT8)(uncrc>>8)!= Packet.down_ser.mCrc[1])
{
BELL(ON);
}
c. 函数代码的参数过长,分多行来书写。
void UARTSendAndRecv(UINT8 *ucSendBuf,
UINT8 ucSendLength,
UINT8 *ucRecvBuf,
UINT8 ucRecvLength)
{
……
}
d. if、do、while、switch、for、case、default等关键字,必须加上大括号{}。
if(bSendEnd)
{
BELL(ON);

养成良好的编程风格
2 / 7
}
else
{
BELL(OFF);
}
//--------------------------
for(i=0; i< ucRecvLength; i++)
{
ucRecvBuf[i]=i;
}
//--------------------------
switch(ucintStatus)
{
case USB_INT_EP2_OUT:
{
USBCiEP2Send(USBMainBuf,ucrecvLen);
USBCiEP1Send(USBMainBuf,ucrecvLen);
}
break;
case USB_INT_EP2_IN:
{
USBCiWriteSingleCmd (CMD_UNLOCK_USB);
}
break;
……
}
2.注释
a. 边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有
用的注释要删除。
注释应当准确、易懂,防止注释有二义性。错误的注释不但无益反而有害。
尽量避免在注释中使用缩写,特别是不常用缩写。
注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。
b. 说明性文件必选在文件头着重说明,例如*.c、*.h文件
/***************************************************************************
* 定时器+计数器测频
*
* 文 件: frequency.c
* 作 者: 小瓶盖
* 说 明:定时器+计数机测频率
* 编写时间: 2010.3.17
* 版 本:1.0
* 修改日期: 无

养成良好的编程风格
3 / 7
*---------------------------------------------------------------------------
* 注: 本程序定义6个数码管,经过实测,在200HZ~50KHZ时结果较准确,误差小于0.4%,
* 50KHZ以上频率未进行测量.据资料表明,可以测量到120KHZ,本程序未证明.
*****************************************************************************/
#include <xxxx.h>
void func(void)
{
}
c. 函数头应该进行注释,例如函数名称、输入参数、返回值、功能说明。
/**************将所有参数写入 AT24C64,共 4 字节*********************
*说明:将表号和用户电量共四字节数据写入 AT24C64 中
*入口参数:
* 1.数据间接寻址地址-buf
* 2.写入到 AT24C64 的地址字-addh,addrl
* 3.写入字节数-count
*出口参数:1 表示写成功,0 表示写失败
***************************************************************/
bit write_byte(unsigned char * buf,
unsigned char addrh,
unsigned char addrl,
unsigned char count)
{
……
}
d. 全局变量要注释其功能,若为关键的局部变量同样需要注释其功能。
volatile UINT8 __ucSysMsg=SYS_IDLE;
void SYSSetMsgPriority(void)
{
SYSMSG Msgt;//临时存储消息
UINT8 i;
}
e. 复杂的宏定义同样要加上注释。
/* SYS_MSG_MAP 建立一个消息映射
宏参数NAME:消息映射表的名字
宏参数NUM_OF_MSG:消息映射的个数
*/
#define SYS_MSG_MAP(NAME,NUM_OF_MSG) do\
{\
DEFINE_MSG_NAME((NAME));\
UINT8 i;\
for(i=0;i< NUM_OF_MSG;i++)\
{\
ININ_CUR_MSG(i)\
}\
剩余74页未读,继续阅读















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0