多.C文件+计算机实例
1、多.C文件的初步认识
随着使用的硬件模块的增多,程序量逐步增大,为了方便代码的编写、维护和移植,通常采用多.C文件的形式。将按键、数码管、Lcd1602液晶、I2C等各个模块分别写一个.C文件,里面包含各自的底层驱动代码,再写出对应的头文件。这样在编写main.C文件时,需要使用哪个模块,只需要添加对应的头文件即可。
extern关键字说明
extern
关键字 用于外部变量的声明,而不是定义。我们需要在第一次用到该变量的.c文件中声明并定义该变量,其他的.c文件如果需要再次使用该变量,我们只需要声明即可,告诉系统这个变量是存在的,不需要再重复定义。(否则会报错)
以数码管的真值定义为例,我们只需要在smg.c文件中定义该变量,如下:(假设第一个使用到该变量的是SMG.c文件)
unsigned char code LedChar[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
//共阳极数码管从0到F的真值
如果我们在main.c中也需要使用到这个变量,只需要在main.c中做如下声明(和首次声明保持一致,code
不能少),而不需要再次定义。
extern unsigned char code LedChar[];
2、实例(CT107D开发板)
通过按键和数码管模块写一个简易整数加法计算器,不考虑连加、连减等连续计算,不考虑小数情况。
main.c代码:
#include"key.h"
#include"smg.h"
#include"system.h"
extern u8 LedBuf[] ;
extern u8 code LedChar[];
void main()
{
All_Int();
EA = 1;
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x67;
ET0 = 1;
TR0 = 1;
LedBuf[0] = LedChar[0];
while(1)
{
KeyDriver();
}
}
void InterruptTimer0() interrupt 1
{
TH0 = 0xFC;
TL0 = 0x67;
LedScan();
KeyScan();
}
system.h代码
#include"system.h"
void All_Int()
{
P2 = (P2&0x1F)|0x80;//Y4,关闭LED灯
P0 = 0xFF;
P2 = (P2&0x1F)|0xa0;//Y6,关闭蜂鸣器,继电器
P2 = 0x00;
P2 = (P2&0x1F)|0xe0;//Y7,段选,关闭数码管
P0 = 0xFF;
}
smg.c代码:
#include"smg.h"
u8 code LedChar[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
//共阳极数码管从0到F的真值
u8 LedBuf[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//数码管显示缓冲区
void LedScan()
{
static u8 index = 0;
P2 = (P2&0x1F)|0xe0;//段选
P0 = 0xff;
P2 = (P2&0x1F)|0xc0;//位选
P0 = 0x80>>index;
P2 = (P2&0x1F)|0xe0;//段选
P0 = LedBuf[index];
index++;
index &= 0x07;//加到7之后自动清0
}
void LedShow(u32 num)
{
signed char i;
u8 buf[6];
for(i=0;i<6;i++)
{
buf[i] = num %10;
num = num / 10;
}
for(i=5;i>0;i--)
{
if (buf[i]==0)
LedBuf[i] = 0xFF;
else
break;
}
for(;i>=0;i--)
{
LedBuf[i] = LedChar[buf[i]];
}
}
key.c代码:
#include"key.h"
u8 code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表
{ '1', '2', '3', 0x26 }, //数字键1、数字键2、数字键3、向上键
{ '4', '5', '6', 0x25 }, //数字键4、数字键5、数字键6、向左键
{ '7', '8', '9', 0x28 }, //数字键7、数字键8、数字键9、向下键
{ '0', 0x1B, 0x0D, 0x27 } //数字键0、ESC键、 回车键、 向右键
};
u8 KeySta[4][4] = {
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
};//保存按键值的当前状态
//按键动作函数
void KeyAction(u8 keycode)
{
static u32 result = 0;
static u32 attend;
if(keycode>='0' & keycode<='9')
{
attend = (attend * 10) + (keycode - 0x30);
LedShow(attend);
}
else if(keycode == 0x26)//加法
{
result += attend;
attend = 0;
LedShow(result);
}
else if(keycode == 0x0D)//回车键执行加法运算,实际效果与加号相同
{
result += attend;
attend = 0;
LedShow(result);
}
else if(keycode == 0x1B)//Esc键,清零
{
attend = 0;
result = 0;
LedShow(attend);
}
}
//按键驱动函数,检测是否有按键按下
void KeyDriver()
{
u8 i,j;
static u8 backup[4][4] = {
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
}; //按键备份,保存前一次的值
for(i=0; i<4; i++)
{
for(j=0; j<4; j++)
{
if(backup[i][j] != KeySta[i][j])
{
if(backup[i][j] != 0)
{
KeyAction(KeyCodeMap[i][j]);
}
backup[i][j] = KeySta[i][j];
}
}
}
}
//按键扫描函数,在定时中断中调用,一般使用间隔1ms
void KeyScan()
{
u8 i;
static keyout = 0;
static keybuf[4][4] = {
{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF}
};
keybuf[keyout][0]=(keybuf[keyout][0]<<1) | KeyIn_1;
keybuf[keyout][1]=(keybuf[keyout][1]<<1) | KeyIn_2;
keybuf[keyout][2]=(keybuf[keyout][2]<<1) | KeyIn_3;
keybuf[keyout][3]=(keybuf[keyout][3]<<1) | KeyIn_4;
for(i=0;i<4;i++)
{
if((keybuf[keyout][i] & 0x0F) == 0x00)
{
KeySta[keyout][i] = 0;
}
else if((keybuf[keyout][i] & 0x0F) == 0x0F)
{
KeySta[keyout][i] = 1;
}
}
keyout++;
keyout &= 0x03;
switch(keyout)
{
case 0:KeyOut_4 = 1;KeyOut_1 = 0;break;
case 1:KeyOut_1 = 1;KeyOut_2 = 0;break;
case 2:KeyOut_2 = 1;KeyOut_3 = 0;break;
case 3:KeyOut_3 = 1;KeyOut_4 = 0;break;
default :break;
}
}
system.h代码:
#ifndef __SYSTEM_H
#define __SYSTEM_H
#include"reg52.h"
#include"intrins.h"
typedef unsigned char u8;
typedef unsigned int u16;
//void All_Init();
#endif
smg.h代码:
#ifndef __SMG_H
#define __SMG_H
#include"system.h"
void LedScan();
void LedShow(u32 num);
#endif
key.h代码:
#ifndef __KEY_H
#define __KEY_H
#include"system.h"
sfr P4 = 0xC0;
sbit KeyOut_1 = P3^0;
sbit KeyOut_2 = P3^1;
sbit KeyOut_3 = P3^2;
sbit KeyOut_4 = P3^3;
sbit KeyIn_1 = P4^4;
sbit KeyIn_2 = P4^2;
sbit KeyIn_3 = P3^5;
sbit KeyIn_4 = P3^4;
void KeyDriver();
void KeyScan();
void KeyAction(u8 keycode);
extern void LedShow(u32 num);
#endif
补充: Keil 5模块化编程详细步骤
前一篇: 单片机学习(8)——1602液晶