*******************************************************
论坛上 很多程序 都是 一大 块,没有 把 外设 写成 单独的 头文件,这个例子比较好,将不同模块 写成 了不同的头文件。
该程序有三个模块头文件
LCD1602.H
DS1302.H
DS18B20.H
只需要学习
LCD1602.H
即可。
*******************************************************
函数实现是否放在头文件中?
LCD1602.H 把 函数实现 也包含在其中,这就引出上面的疑问。
网上找到一个类似的问题,
函数实现代码可以写在头文件中吗?http://zhidao.baidu.com/link?url=H-C7XtZYFAAcA1P-Xyqm4n0mippR7zPsFBr8HN8zKVexuqI3kYdRgcD25rQ8m1Ca3-Q6C2IzVelpVQgZUBNTV_
最佳答案是,
对于小的简单程序来说,完全可以不要cpp,除了main所在的cpp,但是很多情况下cpp是更好的选择或者说是必须的
我举几个例子:
1. 当你的项目很大,如果全部都写到h里,则每次改动和编译都需要全部编译,往往大部分代码不需要重新编译,若写到cpp里编译成库,则改动后可以尽可能少编译
2. 当然, 大的项目需要结构清晰,h里放数据结构以及接口定义而不用管实现,往往有利于阅读和维护,就像别人只需要知道你是做什么的,至于如何做到大可不用关心
3. 有种情况似乎更需要把实现分开,比如两个h定义了两个class,它们都相互引用对方,则至少其中一个会用到非完整类型,即只有声明没有定义的类型,试想编译器在不知道完整类型的情况下是不知道如何生成代码的,所以写到cpp里才可以解决。这个例子有点难懂,但遇到的时候就会明白了
是以C++为例子,但基本上也能说清楚问题。 因为 现在的目标是模块化, 可以用在 大项目 或者 要经常维护,所以 需要把 原作者的 LCD1602.H
改为 LCD1602.H 和 LCD1602.C 两个文件。
很简单的工作,但是还要解决 reg52.h 的问题,这个头文件 没有防止 被互相引用的机制,即 #ifndef xxxxxxxxxxx #endif
所以 把 reg52.h 改成了 AT89X52.H 就可以解决问题了。
*********************************************
LCD1602.H
- /**********************************************************
- LCD1602 DRIVER
-
- File Name: LCD1602.H
- **********************************************************/
- #ifndef LCD_CHAR_1602_2009_6_28
- #define LCD_CHAR_1602_2009_6_28
- #include //因为使用了 P2等端口定义,所以需要添加该头文件
- #include
- ***it LcdRs = P2^0; //定义端口
- ***it LcdRw = P2^1;
- ***it LcdEn = P2^2;
- sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
- /********************************************************
- 内部等待函数
- ********************************************************/
- unsigned char LCD_Wait(void);
- /*******************************************************
- 向LCD写入命令或数据
- *******************************************************/
- #define LCD_COMMAND 0 // Command
- #define LCD_DATA 1 // Data
- #define LCD_CLEAR_SCREEN 0x01 // 清屏
- #define LCD_HOMING 0x02 // 光标返回原点
- void LCD_Write(bit style, unsigned char input);
- /*****************************************************
- 设置显示模式
- *****************************************************/
- #define LCD_SHOW 0x04 //显示开
- #define LCD_HIDE 0x00 //显示关
- #define LCD_CURSOR 0x02 //显示光标
- #define LCD_NO_CURSOR 0x00 //无光标
- #define LCD_FLASH 0x01 //光标闪动
- #define LCD_NO_FLASH 0x00 //光标不闪动
- void LCD_SetDisplay(unsigned char DisplayMode);
- /***************************************************
- 设置输入模式
- ***************************************************/
- #define LCD_AC_UP 0x02
- #define LCD_AC_DOWN 0x00 // default
- #define LCD_MOVE 0x01 // 画面可平移
- #define LCD_NO_MOVE 0x00 //default
- void LCD_Setinput(unsigned char InputMode);
- /***************************************************
- 初始化LCD
- ***************************************************/
- void LCD_Initial();
- /***********************************************
- 液晶字符输入的位置
- ************************************************/
- void GotoXY(unsigned char x, unsigned char y);
- /************************************************
- 将字符输出到液晶显示
- ************************************************/
- void Print(unsigned char *str);
- #endif
复制代码
原作者 定义 了很多 指令,例如
#define LCD_COMMAND 0 // Command
#define LCD_DATA 1 // Data
#define LCD_CLEAR_SCREEN 0x01 // 清屏
#define LCD_HOMING 0x02 // 光标返回原点
#define LCD_SHOW 0x04 //显示开
#define LCD_HIDE 0x00 //显示关
#define LCD_CURSOR 0x02 //显示光标
#define LCD_NO_CURSOR 0x00 //无光标
#define LCD_FLASH 0x01 //光标闪动
#define LCD_NO_FLASH 0x00 //光标不闪动
可读性大大加强,非常不错。
*********************************************
LCD1602.C
- #include "LCD1602.H"
- /********************************************************
- 内部等待函数
- ********************************************************/
- unsigned char LCD_Wait(void)
- {
- LcdRs=0;
- LcdRw=1; _nop_();
- LcdEn=1; _nop_();
-
- LcdEn=0;
- return DBPort;
- }
- /*******************************************************
- 向LCD写入命令或数据
- *******************************************************/
- void LCD_Write(bit style, unsigned char input)
- {
- LcdEn=0;
- LcdRs=style;
- LcdRw=0; _nop_();
- DBPort=input; _nop_();//注意顺序
- LcdEn=1; _nop_();//注意顺序
- LcdEn=0; _nop_();
- LCD_Wait();
- }
- /*****************************************************
- 设置显示模式
- *****************************************************/
- void LCD_SetDisplay(unsigned char DisplayMode)
- {
- LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
- }
- /***************************************************
- 设置输入模式
- ***************************************************/
- void LCD_SetInput(unsigned char InputMode)
- {
- LCD_Write(LCD_COMMAND, 0x04|InputMode);
- }
- /***************************************************
- 初始化LCD
- ***************************************************/
- void LCD_Initial()
- {
- LcdEn=0;
- LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵
- LCD_Write(LCD_COMMAND,0x38);
- LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标
- LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
- LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动
- }
- /***********************************************
- 液晶字符输入的位置
- ************************************************/
- void GotoXY(unsigned char x, unsigned char y)
- {
- if(y==0)
- LCD_Write(LCD_COMMAND,0x80|x);
- if(y==1)
- LCD_Write(LCD_COMMAND,0x80|(x-0x40));
- }
- /************************************************
- 将字符输出到液晶显示
- ************************************************/
- void Print(unsigned char *str)
- {
- while(*str!='\0')
- {
- LCD_Write(LCD_DATA,*str);
- str++;
- }
- }
复制代码
**************************************
其它模块 保持不变。