第69节:使用static关键字可以减少全局变量的使用
本来这一节打算开始讲液晶屏的,但是昨天经过网友“任军”的点拨,我发现了一个惊天秘密,原来static关键字是这么好的东西我却错过了那么多年。以前就有一些网友抱怨,鸿哥的程序好是好,就是全局变量满天飞,当时我觉得我也没招呀,C语言就全局变量和局部变量,单单靠局部变量肯定不行,局部变量每次进入函数内部数值都会被初始化改变,所以我在很多场合也只能靠全局变量了。但是自从昨天知道了static关键字的秘密后,我恍然大悟,很多场合只要在局部变量前面加上static关键字,就可以大大减少全局变量的使用了。
这一节要教会大家一个知识点:
大家都知道,普通的局部变量在每次程序执行到函数内部的时候,数值都会被重新初始化,数值会发生变化,不能保持之前的数值。但是在局部变量加上static关键字后,系统在刚上电的时候就已经把带static的局部变量赋初始值了,从此程序每次进入函数内部,都不会初始化带static关键字的局部变量,它会保持最近一次被程序执行更改的数值不变,像全局变量一样。跟全局变量唯一的差别是,带static关键字的局部变量的作用域仅仅在函数内部,而普通全局变量的作用域是整个工程。
本程序例程是直接在第八节程序上修改,大大减少了全局变量的使用。具体内容,请看源代码讲解。
(1)硬件平台:
基于朱兆祺51单片机学习板。用矩阵键盘中的S1和S5号键作为独立按键,记得把输出线P0.4一直输出低电平,模拟独立按键的触发地GND。
(2)实现功能:跟前面第八节的功能一模一样,有两个独立按键,每按一个独立按键,蜂鸣器发出“滴”的一声后就停。
(3)源代码讲解如下:
#include "REG52.H"
#define const_voice_short 40
#define const_key_time1 20
#define const_key_time2 20
void initial_myself();
void initial_peripheral();
void delay_long(unsigned int uiDelaylong);
void T0_time();
void key_service();
void key_scan();
sbit key_sr1=P0^0;
sbit key_sr2=P0^1;
sbit key_gnd_dr=P0^4;
sbit beep_dr=P2^7;
unsigned char ucKeySec=0; //一些需要在不同函数之间使用的核心变量,只能用全局变量
unsigned int uiVoiceCnt=0; //一些需要在不同函数之间使用的核心变量,只能用全局变量
void main()
{
initial_myself();
delay_long(100);
initial_peripheral();
while(1)
{
key_service();
}
}
void key_scan()
{
/* 注释一:
(1)大家都知道,普通的局部变量在每次程序执行到函数内部的时候,数值都会被重新初始化,
数值会发生变化,不能保持之前的数值。
(2)但是在局部变量加上static关键字后,系统在刚上电的时候就已经把带static的局部变量
赋初始值了,从此程序每次进入函数内部,都不会初始化带static关键字的局部变量,它会保持
最近一次被程序执行更改的数值不变,像全局变量一样。跟全局变量唯一的差别是,带static关键字
的局部变量的作用域仅仅在函数内部,而普通全局变量的作用域是整个工程。
(3)以下这些变量我原来在第八节是用普通全局变量的,现在改成用static的局部变量了,减少了全局变量
的使用,让程序阅读起来更加简洁。大家也可以试试把以下变量的static去掉试试,结果会发现去掉了static后,
按键就不会被触发了。
*/
static unsigned int uiKeyTimeCnt1=0; //带static的局部变量
static unsigned char ucKeyLock1=0;
static unsigned int uiKeyTimeCnt2=0;
static unsigned char ucKeyLock2=0;
if(key_sr1==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位
{
ucKeyLock1=0; //按键自锁标志清零
uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。
}
else if(ucKeyLock1==0)//有按键按下,且是第一次被按下
{
uiKeyTimeCnt1++; //累加定时中断次数
if(uiKeyTimeCnt1>const_key_time1)
{
uiKeyTimeCnt1=0;
ucKeyLock1=1; //自锁按键置位,避免一直触发
ucKeySec=1; //触发1号键
}
}
if(key_sr2==1)
{
ucKeyLock2=0;
uiKeyTimeCnt2=0;
}
else if(ucKeyLock2==0)
{
uiKeyTimeCnt2++;
if(uiKeyTimeCnt2>const_key_time2)
{
uiKeyTimeCnt2=0;
ucKeyLock2=1;
ucKeySec=2;
}
}
}
void key_service()
{
switch(ucKeySec)
{
case 1:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 2:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
}
}
void T0_time() interrupt 1
{
TF0=0;
TR0=0;
key_scan();
if(uiVoiceCnt!=0)
{
uiVoiceCnt--;
beep_dr=0;
}
else
{
;
beep_dr=1;
}
TH0=0xf8;
TL0=0x2f;
TR0=1;
}
void delay_long(unsigned int uiDelayLong)
{
static关键字全局变 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)