从零开始的蓝桥杯单片机之路(b站西风)(一)
在网上看了许多单片机的学习教程,看似大部分通俗易懂,没有门槛,实则还是有许多的潜在前提条件需要你具备。资质平庸的我,根本看不懂那些大佬的东西,还不如自己撰写学习感悟。(本系列全程基于b站西风单片机系列课)
前言:在网上看了许多单片机的学习教程,看似大部分通俗易懂,没有门槛,实则还是有许多的潜在前提条件需要你具备。 资质平庸的我,根本看不懂那些大佬的东西,还不如自己撰写学习感悟。(本系列全程基于b站西风单片机系列课)
这是一份初学者笨重的感悟-----希望能对你有所帮助
一.入门准备
(1)软件准备
一个keil5,一个烧录器,C语言基础,还有仿真图(这个仿真图不要随意下载proteus,去b站西风粉丝群,文件面搜仿真寻找)
前期的工作我们主要是入门,因此可以现用仿真学习,后期再与真实板子对接。
仿真图要用管理员权限打开,不然会报错。
(2)文件创建:
首先在桌面上创建一个文件夹,并为其进行重命名

而后在里面再创造一个文件夹,再次进行重命名

打开keil5

选择左上角的Project,并选择里面的创造新文件选项,点开之后是这个页面
选择刚刚创建的文件,并且给赋予一个Test_1的文件名,而后点击保存

这个点击是否都无所谓,点击否,只不过是将文件''STARTUP.AS1''隐藏了(我通常点击‘’是'')

而后点击左上角的锤子符号

将Output里面的Create HEX File,对号勾选上,这是创造烧录文件的选项。

再选择锤子符号旁边的品字符号,将中间的标题改为User

如果刚刚的文件夹中出现了以下这些文件,则创造成功
二.基础入门
1.led的控制
(1)
如图所示,八个蓝色二极管的右端与VCC(电源电压)相连。因此根据数电知识,二极管左边为高电平1,则为了导通,二极管右边应该是低电平0。
74HC573,是一个典型的锁存器(初学者只需知道其作用是保存信号,便于使用即可),左边与二极管相连。右边DB管脚应是我们赋值的地方。
而DP管脚又与系统中的P1口相连,因此我们可以通过代码给P1口赋值低电平,进而控制二极管的使用

控制led灯的使用我们可以有两种思路,整体赋值和单独赋值。
1.整体赋值:
整体赋值,我们可以用二进制转化为十六进制来对P1进行整体的赋值,而led灯是从右到左进行排序的,犹如中国古代书法写字顺序一样。
举个例子,如果我们想让Led灯第一个灯与第四个灯亮(由上可知,赋值低电平才会亮),因此我们要给led第一个灯,第四个灯赋值0。
而灯的顺序又是从右到左排序的,因此二进制来说P1= 1111 0110.
可二进制在赋值的时候,又太过于繁琐,因此我们可以将二进制转化为十六进制。
使用电脑自带计算机(考试的时候也可以使用),在bin里面输入二进制1111 0110,在HEX中就显示出十六进制的数。

在keil5中编写

在仿真软件中观察图像,可见第一个灯和第三个灯是亮的。

2.单独赋值
对头文件进行扩展,发现单独口是P1_0,P1_1......(部分芯片是P10,要具体看头文件扩展)
因此我们直接对第一个和第四个赋予低电平,P1_0 =0,P1_3=0;结果还是如此。
(2)led流水灯(因为整体赋值比较简单,后面都优先采用整体赋值来进行各项操作)
流水灯的控制,我们首先要有几个前提条件:
1.intrins.h (头文件的引用)
2._cror_ ,_crol_的使用(右,左移)
3,延时函数的使用
因为_cror_ ,_crol_函数的使用 需要头文件定义。因此将''intrins.h''(记不住,可以记''我(i)牛头人了(ntr)ins'')

我们知道,点亮led灯可以给P1口整体赋值低电平,来操作,想让哪个灯亮,就给哪个灯赋0。
因此某一刻的状况,我们可以用整体赋值,可怎么转变为下一个时刻呢?
这时候我们就可以用Delay函数来进行转变。打开sci,选择软件延时函数,将参数转变为上述参数,生成c代码,然后复制。
复制之后,在keil中进行一些改动,将Delay1ms改为Delay(unsigned char xms)并且添加一个while(x--)

这样的话,我们可以直接用Delay(x),对x赋值,而能自由选择变化的时间。
赋值unled;让其左移一个单位,一个Delay(1000);令P1 = unled,再来一个Delay。
在仿真图中即可1s左移一个单位

2. 按键读取函数

由图,四个独立按键都是接地的,为零,因此四个管脚在按键按下的时候,也都是低电平0。又看下图,这四个管脚又与P3_4,P3_5,P3_6,P3_7相连。因此当其中一个P3_X接口为零的时候,说明第X个按键已经被按下。

因此,我们可以由此写出来按键读取函数,设一个变量temp,可以用其代指第几个按键,便于后面的使用。
有了按键读取函数,那么接下来我们该如何使用按键呢?
我们可以在主函数里面使用四行代码(这四行代码固定使用,死死记住即可)。
外面给个定义,在主函数里面写这四行代码。


声明完成这四个变量,并且在主函数里面写了这四行代码之后,我们可以直接来使用Key_Down,Key_Up,Key_Old 来进行操作。
Key_Down 是按下按键生效,
Key_Up 是松开按键生效
Key_Old 是一直按着按键生效
如下操作,假如我想按下1号按键,第一个灯亮,送开2号按键,第一个灯灭;一直按着3号按键,第二灯亮,松开3号按键,即灭
该如何操作?看代码!

那么我们可以更高级一点,不控制一个灯了,而是想办法控制流水灯的启动与暂停,我们该如何去做呢?
首先先写流水灯,具备几个条件
1是头文件(未截全),2是Delay函数,3则是左移右移函数,如下
若是要控制流水灯的开始与暂停,则应该设置一个标志位,来进行控制,比如按下1号键,这个标志位就会促使流水灯启动,按下2号键则会促使流水灯暂停。

也可以用switch来写
写完独立按键,我们现在就应该研究矩阵按键。

矩阵键盘上边有十六个小键,扫描的时候是先按行,然后再按列。
原理图上第一行的四个按键都与P3_0相连,第二行的四个按键都与P3_1相连,第三行的四个按键都与P3_2相连,第四行的四个按键都与P3_3相连。
因此我们扫描的时候,可以把Key_Read()函数修改一下,让其一行一行扫描,扫描完第一行四个按键,再扫描第二行的。(注意P3_X之间是分号,不是逗号,并且是 ''P3_X= 0 ‘’ 而不是 ‘’ P3_X = = 0'')

在此基础上可以进行加减速,定义一个整数变量Time。

Delay(1000)改为Delay(Time)

switch中的case 3 与 case 4

即可通过三四键进行加减速。
好了,你已经学会了按键,接下来请写一个题来练练手吧!

#include <REGX52.H>
#include <intrins.h>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms--){
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}}
unsigned char unLed = 0xfe;
unsigned char Key_Val, Key_Down, Key_Up, Key_Old;
bit System_Flag;
unsigned char Led_Mode = 0;
unsigned char Led_Mode2[4] = {0x7e,0xbd,0xdb,0xe7};
unsigned char Index = 0;
unsigned char Key_Read()
{ unsigned char temp = 0;
P3_0 = 0; P3_1 = 1;P3_2 = 1;P3_3 =1;
if(P3_4 == 0 ) temp = 1;
if(P3_5 == 0 ) temp = 2;
if(P3_6 == 0 ) temp = 3;
if(P3_7 == 0 ) temp = 4;
P3_0 = 1; P3_1 = 0;P3_2 = 1;P3_3 =1;
if(P3_4 == 0 ) temp = 5;
if(P3_5 == 0 ) temp = 6;
if(P3_6 == 0 ) temp = 7;
if(P3_7 == 0 ) temp = 8;
P3_0 = 1; P3_1 = 1;P3_2 = 0;P3_3 =1;
if(P3_4 == 0 ) temp = 9;
if(P3_5 == 0 ) temp = 10;
if(P3_6 == 0 ) temp = 11;
if(P3_7 == 0 ) temp = 12;
P3_0 = 1; P3_1 = 1;P3_2 = 1;P3_3 =0;
if(P3_4 == 0 ) temp = 13;
if(P3_5 == 0 ) temp = 14;
if(P3_6 == 0 ) temp = 15;
if(P3_7 == 0 ) temp = 16;
return temp;
}
void main()
{
while(1)
{
Key_Val = Key_Read();//读取键码值
Key_Down = Key_Val & (Key_Val ^ Key_Old);//检测下降沿
Key_Up = ~Key_Val & (Key_Val ^ Key_Old);//检测上升沿
Key_Old = Key_Val;//辅助扫描
switch(Key_Down)
{
case 1:
System_Flag = 1;
break;
case 2:
System_Flag = 0;
break;
case 3:
Led_Mode ++;
if(Led_Mode == 4) Led_Mode = 0;
break;
case 4:
Led_Mode --;
if(Led_Mode == 255) Led_Mode = 3;
break;
}
if(System_Flag ==1)
{
switch(Led_Mode )
{
case 0:
P1 = unLed;
Delay(500);
unLed = _crol_(unLed,1);
break;
case 1:
P1 = unLed;
Delay(500);
unLed = _cror_(unLed,1);
break;
case 2:
P1 =Led_Mode2[Index];
Delay(500);
Index++;
if(Index == 4) Index = 0;
break;
case 3:
P1 = Led_Mode2[Index];
Delay(500);
Index--;
if(Index == 255) Index = 3;
}}}
}
3.数码管

数码管讲究先位选,然后再段选。(该数码管是共阴极数码管)
位选是0选中,段选是1选中
位选:选择第几个数码管
段选:选择数码管上什么区间亮
如何进行位选和段选呢?如下图


从图2可知,位选和段选最终都接到了D0.7口;从图2可知,对应D0.7的是P0口。因此P0口是数据口,数据应该往P0口写。
但是位选和段选都是写入P0口。P0=0xA4,如何设置为段选?利用锁存器实现。

这些我们先基本了解一下,不用过多思考,接下来,我们先考虑简单的应用。
先在变量中定义位选和段选的数据组
unsigned char Seg_Wela[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
unsigned char Seg_Dula[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
直接在程序中设置这样一个void函数
//数码管显示函数
void Seg_Disp(unsigned char wela,dula)
{
P0 = 0x00; //消影
P2_6 = 1;
P2_6 = 0;
P0 = Seg_Wela[wela];
P2_7 = 1;
P2_7 = 0;
P0 = Seg_Dula[dula];
P2_6 = 1;
P2_6 = 0;
}
先消影
令P2.6=1,写入段选数据;令P2.6=0,关闭,数据存进去了。(这里运用了锁存器)
令P2.7=1,写入位选数据;令P2.7=0,关闭,数据存进去了。
而后我们就可以直接在主函数中应用了。
#include <REGX52.H>
#include <intrins.h>
void Delay(unsigned char xms) //@12.000MHz
{
unsigned char i, j;
while(xms --)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
//变量声明界面
unsigned char unLed = 0xfe;
unsigned char Key_Val, Key_Down, Key_Up, Key_Old;
bit System_Flag ;
unsigned int Time = 500;
unsigned char Seg_Wela[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
unsigned char Seg_Dula[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
//数码管显示函数
void Seg_Disp(unsigned char wela,dula)//函数接口
{
P0 = 0x00;
P2_6 = 1;
P2_6 = 0; //消影
P0 = Seg_Wela[wela];
P2_7 = 1;
P2_7 = 0;//位选
P0 = Seg_Dula[dula];
P2_6 = 1;
P2_6 = 0;//段选
}
//按键读取函数
unsigned char Key_Read()
{ unsigned char temp = 0;
P3_0 = 0; P3_1 = 1;P3_2 = 1;P3_3 =1;
if(P3_4 == 0 ) temp = 1;
if(P3_5 == 0 ) temp = 2;
if(P3_6 == 0 ) temp = 3;
if(P3_7 == 0 ) temp = 4;
P3_0 = 1; P3_1 = 0;P3_2 = 1;P3_3 =1;
if(P3_4 == 0 ) temp = 5;
if(P3_5 == 0 ) temp = 6;
if(P3_6 == 0 ) temp = 7;
if(P3_7 == 0 ) temp = 8;
P3_0 = 1; P3_1 = 1;P3_2 = 0;P3_3 =1;
if(P3_4 == 0 ) temp = 9;
if(P3_5 == 0 ) temp = 10;
if(P3_6 == 0 ) temp = 11;
if(P3_7 == 0 ) temp = 12;
P3_0 = 1; P3_1 = 1;P3_2 = 1;P3_3 =0;
if(P3_4 == 0 ) temp = 13;
if(P3_5 == 0 ) temp = 14;
if(P3_6 == 0 ) temp = 15;
if(P3_7 == 0 ) temp = 16;
return temp;
}
void main()
{
while(1)
{
Key_Val = Key_Read();//读取键码值
Key_Down = Key_Val & (Key_Val ^ Key_Old);//检测下降沿
Key_Up = ~Key_Val & (Key_Val ^ Key_Old);//检测上升沿
Key_Old = Key_Val;//辅助扫描
if(System_Flag == 1)
{
unLed = _crol_(unLed,1);
P1 = unLed;
Delay(Time);
}
switch(Key_Down)
{
case 1:
System_Flag = 1;
break;
case 2:
System_Flag = 0;
break;
case 3:
Time += 100;
case 4:
Time -= 100;
}
Seg_Disp(1,1);
}
最终结果:数码管2号管显示1

这是静态数码管,我们该如何让数码管动起来呢?
这就要用到定时器了。


将函数里面改成这个

而后再定义一个函数,并且将初始值复制过去
并且在主函数中声明一下
显示的内容


如果想要轮流显示
可以加一个delay
接下来就开始正式学习!
首先观看视频创建好蓝桥杯的固定模板

(链接:https://pan.baidu.com/s/1cyD_cP-S2IIHHm9oaJcgUg
提取码:c5bs)我已经提前创建好了,用者自取。
简单写个小题
1.




首先考虑题目,因为有多个显示模式,因此我们可以设置一个变量,来表示显示模式的区分。

在数码管中,模式一就可以这么写。

中断设置,从30秒开始倒计时,变量和中断就可以这么写

在写完这些之后,我们要加以限制,比如要按下独立按键1号键之后,才开始倒计时。
首先在按键模块里面进行编写,将按键1与一个标志位联系在一起。
//按键处理函数
void Key_Proc()
{
if( Key_Slow_Down ) return;
Key_Slow_Down = 1;//减速
Key_Val = Key_Read();//读取按键按下键码值
Key_Down = Key_Val & (Key_Val ^Key_Old);//捕捉下降沿
Key_Old = Key_Val;
switch(Key_Down)
{
case 1:
if(Seg_Mode == 0)
System_Flag = 1;
break;
}
}
//定时器中断服务函数
void Timer0Server() interrupt 1
{
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
if(++Seg_Pos == 6) Seg_Pos = 0;
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);
if( System_Flag == 1){
if(++Timer_1000ms == 1000)
{
Timer_1000ms = 0;
Timer_Count--;
}
}
}
随后切换设置界面,为了不扰乱不同模式下的数组,应该多设几个

//按键处理函数
void Key_Proc()
{
if( Key_Slow_Down ) return;
Key_Slow_Down = 1;//减速
Key_Val = Key_Read();//读取按键按下键码值
Key_Down = Key_Val & (Key_Val ^Key_Old);//捕捉下降沿
Key_Old = Key_Val;
switch(Key_Down)
{
case 1://显示
if(Seg_Mode == 0)
System_Flag = 1;
break;
case 3://切换
if(Seg_Mode == 1)
Timer_Count = Set_Dat[Set_Index];//保存
Seg_Mode ^= 1;
break;
case 4://设置
if(Seg_Mode == 1){
if(++Set_Index == 3)
Set_Index = 0;}
break;
}
}
//数码管显示
void Seg_Proc()
{
if( Seg_Slow_Down ) return;
Seg_Slow_Down = 1;//减速
Seg_Buf[0] = Seg_Mode + 1;//数码管一号位显示
if(Seg_Mode == 0)//模式一的时候
{
Seg_Buf[4] = Timer_Count / 10 % 10;
Seg_Buf[5] = Timer_Count %10 ;
}
else//设置界面
{
Seg_Buf[4] =Set_Dat[Set_Index] / 10 % 10;
Seg_Buf[5] = Set_Dat[Set_Index] %10 ;
}
}
//其他显示函数
void Led_Proc()
{
}
等Timer_Count 减到零以后,我们想让它保持零状态。
因此我们应该
Led和蜂鸣器的都挺简单的,就简单写点程序就行
头文件
Led和蜂鸣器的代码

定时器中断服务函数、

2.
进阶题目

此题应该先在数码管中写模式一,再在写模式二
Seg.c与Key.c,Seg.h的底层代码也改一下
Key.c
#include <Key.h>
/* 按键读取函数 */
unsigned char Key_Read()
{
unsigned char temp = 0;
P3_0 = 0;P3_1 = 1;P3_2 = 1;P3_3 = 1;
if(P3_4 == 0) temp = 1;
if(P3_5 == 0) temp = 2;
if(P3_6 == 0) temp = 3;
if(P3_7 == 0) temp = 4;
P3_0 = 1;P3_1 = 0;P3_2 = 1;P3_3 = 1;
if(P3_4 == 0) temp = 5;
if(P3_5 == 0) temp = 6;
if(P3_6 == 0) temp = 7;
if(P3_7 == 0) temp = 8;
P3_0 = 1;P3_1 = 1;P3_2 = 0;P3_3 = 1;
if(P3_4 == 0) temp = 9;
if(P3_5 == 0) temp = 10;
if(P3_6 == 0) temp = 11;
if(P3_7 == 0) temp = 12;
P3_0 = 1;P3_1 = 1;P3_2 = 1;P3_3 = 0;
if(P3_4 == 0) temp = 13;
if(P3_5 == 0) temp = 14;
if(P3_6 == 0) temp = 15;
if(P3_7 == 0) temp = 16;
return temp;
}
Seg.c
#include <Seg.h>
unsigned char Seg_Wela[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
unsigned char Seg_Dula[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
/* 数码管显示函数*/
void Seg_Disp(unsigned char wela,dula,point)
{
P0 = 0x00;
P2_6 = 1;
P2_6 = 0;
P0 = Seg_Wela[wela];
P2_7 = 1;
P2_7 = 0;
if(point == 1)
P0 = Seg_Dula[dula]|0x80;
else
P0 = Seg_Dula[dula];
P2_6 = 1;
P2_6 = 0;
}
Seg.h
#include <REGX52.H>
void Seg_Disp(unsigned char wela,dula,point);
main.c
#include <REGX52.H>
#include <Key.h>
#include <Seg.h>
unsigned char Key_Slow_Down;//按键消抖变量10ms
unsigned int Seg_Slow_Down;//键盘消抖变量500ms
unsigned char Key_Val,Key_Down,Key_Old;//按键扫描专用
unsigned char Seg_Pos;
unsigned char Seg_Buf[6] = {1,2,3,4,5,6};
unsigned char Seg_Mode;//模式0---时钟显示,1----时钟设置,2----闹钟设置
unsigned char Clock_Disp[3] = {23,59,55};//模式一显示
unsigned int Timer_1000ms;//1秒
unsigned char Clock_Set[3];//时钟设置界面新数组
unsigned int Timer_500ms;//周期闪烁
bit Set_Flag;//设置闪烁标志位
unsigned char Clock_Set_Index = 0;//控制切换时--分--秒的
unsigned char Alarm[3] = {0,0,0};
unsigned char Alarm_Set[3];
bit Alarm_Flag;
unsigned char Alarm_enable;
unsigned char ucLed;
unsigned char Seg_Point[6] = {0,1,0,1,0,1};
//按键处理函数
void Key_Proc()
{
if( Key_Slow_Down ) return;
Key_Slow_Down = 1;//减速
Key_Val = Key_Read();//读取按键按下键码值
Key_Down = Key_Val & (Key_Val ^Key_Old);//捕捉下降沿
Key_Old = Key_Val;
switch(Key_Down)
{
case 1:
Clock_Set_Index = 0;
Clock_Set[0] = Clock_Disp[0];
Clock_Set[1] = Clock_Disp[1];
Clock_Set[2] = Clock_Disp[2];
Seg_Mode = 1;
break;
case 2:
Clock_Set_Index = 0;
Alarm_Set[2] = Alarm[2];
Alarm_Set[1] = Alarm[1];
Alarm_Set[0] = Alarm[0];
Seg_Mode = 2;
break;
case 3:
if(Seg_Mode == 1)
{
if(++Clock_Set_Index ==3)
Clock_Set_Index = 0;//切换闪烁
}
break;
case 4:
Alarm_Flag ^= 1;
case 5:
if(Seg_Mode == 1)
{ if(++Clock_Set[Clock_Set_Index] == (Clock_Set_Index==0?24:60))
Clock_Set[Clock_Set_Index] = 0;
}
if(Seg_Mode == 2)
{
if(++Alarm_Set[Clock_Set_Index] == (Clock_Set_Index==0?24:60))
Alarm[Clock_Set_Index] = 0;
}
break;
case 6:
if(Seg_Mode == 1)
{
if(--Clock_Set[Clock_Set_Index] ==255)
Clock_Set[Clock_Set_Index] = (Clock_Set_Index==0?23:59);
}
if(Seg_Mode == 2)
{
if(--Alarm_Set[Clock_Set_Index] ==255)
Alarm_Set[Clock_Set_Index] = (Clock_Set_Index==0?23:59);
}
case 7:
if(Seg_Mode ==1)
{
Clock_Disp[0] = Clock_Set[0];
Clock_Disp[1] = Clock_Set[1];
Clock_Disp[2] = Clock_Set[2];}
break;
case 8:
Seg_Mode = 0;
break;
}
}
//数码管显示
void Seg_Proc()
{ unsigned char i = 0;
if( Seg_Slow_Down ) return;
Seg_Slow_Down = 1;//减速
switch(Seg_Mode)
{
case 0:
for(i;i<3;i++)
{
Seg_Buf[0+2*i] = Clock_Disp[i] / 10 %10;
Seg_Buf[1+2*i] = Clock_Disp[i] %10;
}
break;
case 1:
for(i;i<3;i++)
{
Seg_Buf[0+2*i] = Clock_Set[i] / 10 %10;
Seg_Buf[1+2*i] = Clock_Set[i] %10;
}
Seg_Buf[0+2*Clock_Set_Index ] = Set_Flag?Clock_Set[Clock_Set_Index ] / 10 %10:10;
Seg_Buf[1+2*Clock_Set_Index ] = Set_Flag? Clock_Set[Clock_Set_Index ] %10:10;
break;
case 2:
for(i;i<3;i++)
{
Seg_Buf[0+2*i] =Alarm_Set[i] / 10 %10;
Seg_Buf[1+2*i] =Alarm_Set[i] %10;
}
Seg_Buf[0+2*Clock_Set_Index ] = Set_Flag?Alarm_Set[Clock_Set_Index ] / 10 %10:10;
Seg_Buf[1+2*Clock_Set_Index ] = Set_Flag?Alarm_Set[Clock_Set_Index ] %10:10;
break;
}
}
//其他显示函数
void Led_Proc()
{
if(Alarm_Flag== 1)
{
if(Clock_Disp[0] == Alarm[0] && Clock_Disp[1] == Alarm[1] && Clock_Disp[2] == Alarm[2])
Alarm_enable = 1;
if( Alarm_enable == 1)
{
P2_3 = 0;
P1 =ucLed;
}
else
{
P2_3 = 1;
P1 = 0x00;
}
}
else
{
P2_3 = 1;
P1 = 0x00;
}}
//定时中断函数
void Timer0Init(void) //1毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
//定时器中断服务函数
void Timer0Server() interrupt 1
{
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
if(++Seg_Pos == 6) Seg_Pos = 0;
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
if(++Timer_1000ms == 1000)
{
Timer_1000ms = 0;
Clock_Disp[2]++;
if( Clock_Disp[2] == 60)
{ Clock_Disp[2] = 0;
Clock_Disp[1]++;
if( Clock_Disp[1] == 60)
{Clock_Disp[1] = 0;
Clock_Disp[0]++;
if(Clock_Disp[0] == 24)
{
Clock_Disp[0] =0;
}
}}}
if(++Timer_500ms == 500)
{
Timer_500ms = 0;
Set_Flag ^=1;
if(Clock_Disp[0]>=12)
ucLed ^=0xf0;
else
ucLed ^=0x0f;
}
}
void main()
{
Timer0Init();
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}}
程序提取码:
链接:https://pan.baidu.com/s/1QBs9TWdfgRBzZCm4FkDPzw
提取码:svwp
更多推荐



所有评论(0)