蓝桥杯单片机第三周笔记
模块化编程
User-用户层(main)
Driver-底层(固定)
底层函数
新建,保存到Driver文件夹,建立工程模板图 - 编写底层函数Key、Seg
.c
引用底层头文件
编写底层函数
.h
引用51单片机头文件
声明底层函数
添加已有文件到Driver
Main函数区
-
头文件
/*头文件声明区域*/ #include <REGX52.H> #include "key.h" #include "Seg.h" -
变量声明
/*变量声明区域*/ unsigned char Key_Slow_Down;//按键减速专业变量 unsigned int Seg_Slow_Down;//数码管减速专业变量 unsigned char Key_Val,Key_Up,Key_Down,Key_Old;//按键扫描专业变量 unsigned char Seg_Pos;//数码管扫描变量 unsigned char Seg_Buf[6]={1,2,3,4,5,6};//数码管显示数据存放数组 -
Key_Proc()
/*按键处理函数*/ 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_Up = ~Key_Val & (Key_Val ^ Key_Old);//检测上升沿 Key_Old = Key_Val;//扫描辅助沿 switch(Key_Down) { } } -
Seg_Proc()
/*信息处理函数*/ void Seg_Proc() { if(Seg_Slow_Down)return; Seg_Slow_Down = 1;//按键减速程序 } -
Led_Proc()
/*其他显示函数*/ void Led_Proc() { } -
Timer0Init
/*定时器0初始化函数*/ void Timer0_Init(void) //1毫秒@12.000MHz { TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0x18; //设置定时初始值 TH0 = 0xFC; //设置定时初始值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; EA = 1; } -
Timer0Sever
/*定时器0中断服务函数*/ void Timer0Sever() 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]); } -
main
/*Main*/ void main() { Timer0_Init(); while(1) { Key_Proc(); Seg_Proc(); Led_Proc(); } }
基于定时器的倒计时程序设计
程序设计
先从数码管显示界面下手,设置显示模式变量,再配合按键
写一步烧录一步,方便查错
-
面对数码管显示里的多个数据切换时,定义一个数组和对应的索引值
unsigned char Set_Dat[3] = {15,30,60};//设置参数数组 unsigned char Set_Dat_Index = 1;//设置参数数组索引值 -
定时器中以秒为单位的倒计时“unsigned char”类型的数据范围0~255,减到0是下一个是255
if(++Timer_1000ms == 1000) { Timer_1000ms = 0; Timer_Count--;//Timer_Count = 60 if(Timer_Count == 255) Timer_Count = 0; } -
数码管闪烁标志位
if(++Timer_500ms == 500) { Timer_500ms = 0; Seg_Flag ^= 1; }
总程序
/*头文件声明区域*/
#include <REGX52.H>
#include "key.h"
#include "Seg.h"
/*变量声明区域*/
unsigned char Key_Slow_Down;//按键减速专业变量
unsigned int Seg_Slow_Down;//数码管减速专业变量
unsigned char Key_Val,Key_Up,Key_Down,Key_Old;//按键扫描专业变量
unsigned char Seg_Pos;//数码管扫描变量
unsigned char Seg_Buf[6]={10,10,10,10,10,10};//数码管显示数据存放数组
unsigned char Seg_Mode;//数码管显示模式0-显示界面 1-设置界面
unsigned int Timer_1000ms;//1s计时变量
unsigned int Timer_500ms;//0.5s计时变量
unsigned char Timer_Count = 30;//计时变量
unsigned char Set_Dat[3] = {15,30,60};//设置参数数组
unsigned char Set_Dat_Index = 1;//设置参数数组索引值
bit System_Flag;//系统标志位0-复位 1-开始倒计时
bit Seg_Flag;//数码管标志位
/*按键处理函数*/
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_Up = ~Key_Val & (Key_Val ^ Key_Old);//检测上升沿
Key_Old = Key_Val;//扫描辅助沿
switch(Key_Down)
{
case 1://按下1系统开始倒计时
if(Seg_Mode == 0)
System_Flag = 1;
break;
case 2://按下2系统复位
if(Seg_Mode == 0)
Timer_Count = Set_Dat[Set_Dat_Index];
break;
case 3://显示界面和设置界面的切换
if(Seg_Mode == 1)
Timer_Count = Set_Dat[Set_Dat_Index];
Seg_Mode ^= 1;
break;
case 4://设置参数切换
if(Seg_Mode == 1)
{
if(++Set_Dat_Index == 3)
Set_Dat_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 //倒计时设置界面
{
if(Seg_Flag == 0)
{
Seg_Buf[4] = Set_Dat[Set_Dat_Index] / 10 % 10;
Seg_Buf[5] = Set_Dat[Set_Dat_Index] % 10;
}
else
{
Seg_Buf[4] = 10;
Seg_Buf[5] = 10;
}
}
}
/*其他显示函数*/
void Led_Proc()
{
if(Timer_Count == 0)
{
P2_3 = 0;
P1 = 0x00;
}
else
{
P2_3 = 0;
P1 = 0xff;
}
}
/*定时器0初始化函数*/
void Timer0_Init(void) //1毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
/*定时器0中断服务函数*/
void Timer0Sever() 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--;
if(Timer_Count == 255)
Timer_Count = 0;
}
}
if(++Timer_500ms == 500)
{
Timer_500ms = 0;
Seg_Flag ^= 1;
}
}
/*Main*/
void main()
{
Timer0_Init();
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
基于定时器的时钟程序设计
程序设计
-
数码管多个数据同时显示时,用数组,方便数组索引值的嵌套
unsigned char Clock_Disp[3] = {23,59,55}//0-小时 1-分 2-秒 -
数码管小数点点亮,小数点0x80,数字+小数点(=数字|0x80)
if(Point == 1) P0 = Seg_Dula[Dula] | 0x80; else P0 = Seg_Dula[Dula]; -
时钟设置和显示数组要分开,两个界面互不干扰
unsigned char Clock_Set[3]时钟显示模式切换到设置模式时,设置数组等于显示数组
//设置时 Clock_Set[0] = Clock_Disp[0]; Clock_Set[1] = Clock_Disp[1]; Clock_Set[2] = Clock_Disp[2]; //保存时 Clock_Disp[0] = Clock_Set[0]; Clock_Disp[1] = Clock_Set[1]; Clock_Disp[2] = Clock_Set[2]; -
选中的数码管闪烁
switch(Clock_Set_Index) { case 0: Seg_Buf[0] = Seg_Flag?Clock_Set[0] / 10 %10 : 10; Seg_Buf[1] = Seg_Flag?Clock_Set[0] %10 : 10; break; case 1: Seg_Buf[2] = Seg_Flag?Clock_Set[1] / 10 %10 : 10; Seg_Buf[3] = Seg_Flag?Clock_Set[1] %10 : 10; break; case 2: Seg_Buf[4] = Seg_Flag?Clock_Set[2] / 10 %10 : 10; Seg_Buf[5] = Seg_Flag?Clock_Set[2] %10 : 10; break; } -
时钟加减的上限值
if(Clock_Set[Clock_Set_Index] == (Clock_Set_Index?24:60)) -
闹钟的显示和设置与时钟的显示和设置思路完全一致
-
进入设置界面时候,要把索引值复位
Clock_Set_Index = 0; -
闹钟使能标志位,否则只有一瞬间满足闹钟条件
bit Alarm_Enable_Flag
总程序
/*头文件声明区域*/
#include <REGX52.H>
#include "key.h"
#include "Seg.h"
/*变量声明区域*/
unsigned char Key_Slow_Down;//按键减速专业变量
unsigned int Seg_Slow_Down;//数码管减速专业变量
unsigned char Key_Val,Key_Up,Key_Down,Key_Old;//按键扫描专业变量
unsigned char Seg_Pos;//数码管扫描变量
unsigned char Seg_Buf[6] = {10,10,10,10,10,10};//数码管显示数据存放数组
unsigned char Seg_Point[6] = {0,1,0,1,0,1};//小数点点亮存放数组
unsigned char Seg_Mode;//数码管显示模式0-时钟显示模式 1-时钟设置界面 2-闹钟设置界面
unsigned char Clock_Dsip[3] = {23,59,55};//时钟显示数组
unsigned int Timer_1000ms;//1s
unsigned int Timer_500ms;//0.5s
unsigned char Clock_Set[3];//时钟设置数组
unsigned char Clock_Set_Index;//时钟设置数组索引值0-时 1-分 2-秒
unsigned char Alarm[3] = {0,0,0};//闹钟显示数组
unsigned char Alarm_Set[3];//闹钟设置数组
unsigned char ucLed;//Led
bit Seg_Flag;//数码管闪烁标志位
bit Alarm_Flag;//闹钟开关标志位
bit Alarm_Enable_Flag;//闹钟使能标志位
/*按键处理函数*/
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_Up = ~Key_Val & (Key_Val ^ Key_Old);//检测上升沿
Key_Old = Key_Val;//扫描辅助沿
if(Key_Down != 0)Alarm_Enable_Flag = 0;
switch(Key_Down)
{
case 1:
Clock_Set_Index = 0;
Clock_Set[0] = Clock_Dsip[0];
Clock_Set[1] = Clock_Dsip[1];
Clock_Set[2] = Clock_Dsip[2];
Seg_Mode = 1;
break;
case 2:
Clock_Set_Index = 0;
Alarm_Set[0] = Alarm[0];
Alarm_Set[1] = Alarm[1];
Alarm_Set[2] = Alarm[2];
Seg_Mode = 2;
break;
case 3:
if(++Clock_Set_Index == 3)
Clock_Set_Index = 0;
break;
case 4:
Alarm_Flag ^= 1;
break;
case 5:
if(Seg_Mode == 1)
{
if(++Alarm_Set[Clock_Set_Index] == (Clock_Set_Index == 0?24:60))
Alarm_Set[Clock_Set_Index] = 0;
}
if(Seg_Mode == 2)
{
if(++Alarm_Set[Clock_Set_Index] == (Clock_Set_Index == 0?24:60))
Alarm_Set[Clock_Set_Index] = 0;
}
break;
case 6:
if(Seg_Mode == 1)
{
if(--Alarm_Set[Clock_Set_Index] == 255)
Alarm_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);
}
break;
case 7:
if(Seg_Mode == 1)
{
Clock_Dsip[0] = Clock_Set[0];
Clock_Dsip[1] = Clock_Set[1];
Clock_Dsip[2] = Clock_Set[2];
}
if(Seg_Mode == 2)
{
Alarm[0] = Alarm_Set[0];
Alarm[1] = Alarm_Set[1];
Alarm[2] = Alarm_Set[2];
}
Seg_Mode = 0;
break;
case 8:
Seg_Mode = 0;
break;
}
}
/*信息处理函数*/
void Seg_Proc()
{
if(Seg_Slow_Down)return;
Seg_Slow_Down = 1;//按键减速程序
switch(Seg_Mode)
{
case 0://时钟显示界面
Seg_Buf[0] = Clock_Dsip[0] / 10 % 10;
Seg_Buf[1] = Clock_Dsip[0] % 10;
Seg_Buf[2] = Clock_Dsip[1] / 10 % 10;
Seg_Buf[3] = Clock_Dsip[1] % 10;
Seg_Buf[4] = Clock_Dsip[2] / 10 % 10;
Seg_Buf[5] = Clock_Dsip[2] % 10;
break;
case 1://时钟设置界面
Seg_Buf[0] = Clock_Set[0] / 10 % 10;
Seg_Buf[1] = Clock_Set[0] % 10;
Seg_Buf[2] = Clock_Set[1] / 10 % 10;
Seg_Buf[3] = Clock_Set[1] % 10;
Seg_Buf[4] = Clock_Set[2] / 10 % 10;
Seg_Buf[5] = Clock_Set[2] % 10;
switch(Clock_Set_Index)
{
case 0:
Seg_Buf[0] = Seg_Flag?Clock_Set[0] / 10 % 10 : 10;
Seg_Buf[1] = Seg_Flag?Clock_Set[0] % 10 : 10;
break;
case 1:
Seg_Buf[2] = Seg_Flag?Clock_Set[1] / 10 % 10 : 10;
Seg_Buf[3] = Seg_Flag?Clock_Set[1] % 10 : 10;
break;
case 2:
Seg_Buf[4] = Seg_Flag?Clock_Set[2] / 10 % 10 : 10;
Seg_Buf[5] = Seg_Flag?Clock_Set[2] % 10 : 10;
break;
}
break;
case 2://闹钟设置界面
Seg_Buf[0] = Alarm_Set[0] / 10 % 10;
Seg_Buf[1] = Alarm_Set[0] % 10;
Seg_Buf[2] = Alarm_Set[1] / 10 % 10;
Seg_Buf[3] = Alarm_Set[1] % 10;
Seg_Buf[4] = Alarm_Set[2] / 10 % 10;
Seg_Buf[5] = Alarm_Set[2] % 10;
switch(Clock_Set_Index)
{
case 0:
Seg_Buf[0] = Seg_Flag?Alarm_Set[0] / 10 % 10 : 10;
Seg_Buf[1] = Seg_Flag?Alarm_Set[0] % 10 : 10;
break;
case 1:
Seg_Buf[2] = Seg_Flag?Alarm_Set[1] / 10 % 10 : 10;
Seg_Buf[3] = Seg_Flag?Alarm_Set[1] % 10 : 10;
break;
case 2:
Seg_Buf[4] = Seg_Flag?Alarm_Set[2] / 10 % 10 : 10;
Seg_Buf[5] = Seg_Flag?Alarm_Set[2] % 10 : 10;
break;
}
break;
}
}
/*其他显示函数*/
void Led_Proc()
{
if(Alarm[0] > 12)
ucLed = 0x0f;
else
ucLed = 0xf0;
if(Alarm_Flag == 1)
{
if(Clock_Dsip[0] == Alarm[0] && Clock_Dsip[1] == Alarm[1] && Clock_Dsip[2] == Alarm[2])
Alarm_Enable_Flag = 1;
if(Alarm_Enable_Flag == 1)
{
P2_3 = 0;
P1 = Seg_Flag?ucLed:0xff;
}
else
{
P2_3 = 1;
P1 = 0xff;
}
}
else
{
P2_3 = 1;
P1 = 0xff;
}
}
/*定时器0初始化函数*/
void Timer0_Init(void) //1毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
/*定时器0中断服务函数*/
void Timer0Sever() 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(Seg_Mode == 0)
{
if(++Timer_1000ms == 1000)
{
Timer_1000ms = 0;
Clock_Dsip[2]++;
if(Clock_Dsip[2] == 60)
{
Clock_Dsip[2] = 0;
Clock_Dsip[1]++;
if(Clock_Dsip[1] == 60)
{
Clock_Dsip[1] = 0;
Clock_Dsip[0]++;
if(Clock_Dsip[0] == 24)
Clock_Dsip[0] = 0;
}
}
}
}
if(++Timer_500ms == 500)
{
Timer_500ms = 0;
Seg_Flag ^= 1;
}
}
/*Main*/
void main()
{
Timer0_Init();
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}

