过往历程
前瞻知识
1.如何生成stc的头文件
直接点保存文件到你建的目录下方就行了,就可以直接使用这个头文件了
定时器工作原理
定时器/计数器是一种能够对内部时钟信号或者外部输入信号进行计数,当计数值达到设定要求时,向CPU提出中断请求,从而实现定时或计数功能的外设。定时器的基本工作原理是进行计数。
举个栗子:你可以把定时器比喻成一个装了水的瓶子,每一次计数理解成向瓶子里面丢一个石子,当丢的石子足够多时,瓶子里面的水就会溢出,产生中断请求。
当作为定时器使用时,计数信号的来源是周期性的内部时钟频率,在单片机的内部,有一个频率为12MHZ的晶振,可以稳定的产生的产生一个周期为12MHZ的时钟信号,那么定时器就可以实现在每隔一段时间加一,实现定时。我们可以来简单的计算一下一个定时器的溢出周期:
单片机的时钟周期:T=1/f(sys) = 1/12MHZ = 0.083us 这是一个时钟周期
单片机的指令周期:单片机的指令周期 = 12*时钟周期=12 * 0.083 = 1us;即定时器在工作的状态下每1us计数器就会加一(每1us向瓶子里面丢一个石子)。
那么最大可以加到多少呢?我们这里以定时器0为例:在单片机内部有两个寄存器TH0和TL0,用来给定时器0计数,那么计数的最大值就是2^16-1 = 65535(最多丢65535个石子,瓶子里的水就会溢出),也就是说定时器可以对时钟信号从0开始计数一直到65535,然后溢出产生中断请求。那么最大的定时周期就是1us*65535 =65.535ms;
当然:65.535ms的定时时间对于我们也许有一些鸡肋,但是我们可以认为的设置定时器初始的值(即可以设置这个瓶子里原来有多少石子),来控制定时的时间。
举个栗子:我们需要定时1ms,则我们可以设置:
TH0 = (65535-1000)/256 = 0xFC;
Tl0 = (65535-1000)%256 = 0x18;
这样,我们就可以控制定时器每1ms溢出一次
PS:STC15系列单片机有两种计数模式,一种是12T模式,每12个时钟周期加一,与传统的8051单片机相同;另一种时1T模式,每一个时钟信号加一,速度时12T模式的12倍,但一般默认是12T模式。
作为计数器使用时计数信号的来源是非周期性的外部输入信号。外部引号可以有对应的引脚的脉冲信号输入,其对应关系如下:
定时器0—>P3.4; 定时器1—>P3.5;定时器2—>P3.1;
2.按键知识
这个是按键的原理图
可以简单的理解成,按下按键的时候,按的那个按键为**“0”**
没按下的“1”就行了
所以我们写程序的时候根据这个逻辑写就行了
写矩阵的时候先行后列或者先列后行的判断是哪一个按键就行了
keyscan是什么
我们只用判断keyscan的值就可以判断是那个按键按下了,这个只是一个变量
你想叫啥就直接命名就行了,不一定要一模一样
列矩阵按键写法
sbit s7=P3^0;
sbit s6=P3^1;
sbit s5=P3^2;
sbit s4=P3^3;
char anjian()
{
int keyscan;
P3=0x0f;P42=P44=0; //注意这种写法,头文件是用stc生成的
if(s4==0||s5==0||s6==0||s7==0)
{
delay(10); //消抖
P34=P35=P42=P44=1;
P44=0; //如果是P44这行按下了
if(s4==0) keyscan=4; //如果是s4这个按键按下了
else if(s5==0) keyscan=5; //如果是s5这个按键按下了
else if(s6==0) keyscan=6; //如果是s6这个按键按下了
else if(s7==0) keyscan=7; //如果是s7这个按键按下了
P42=0;
if(s4==0) keyscan=8;
else if(s5==0) keyscan=9;
else if(s6==0) keyscan=10;
else if(s7==0) keyscan=11;
P35=0;
if(s4==0) keyscan=12;
else if(s5==0) keyscan=13;
else if(s6==0) keyscan=14;
else if(s7==0) keyscan=15;
P34=0;
if(s4==0) keyscan=16;
else if(s5==0) keyscan=17;
else if(s6==0) keyscan=18;
else if(s7==0) keyscan=19;
}
P3=0x0f;P42=P44=0;
while(s4==0||s5==0||s6==0||s7==0); //消抖
return keyscan;
}
}
行矩阵按键写法
//这个和列矩阵差不多
sbit R1=P3^0;
sbit R2=P3^1;
sbit R3=P3^2;
sbit R4=P3^3;
sbit C4=P3^4;
sbit C3=P3^5;
sbit C2=P4^2;
sbit C1=P4^4;
char key_scan()
{
int i;
{
R1=0;
R2=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)i=0;
else if(C2==0)i=1;
else if(C3==0)i=2;
else if(C4==0)i=4;
R2=0;
R1=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)i=5;
else if(C2==0)i=6;
else if(C3==0)i=7;
else if(C4==0)i=8;
R3=0;
R2=R1=R4=1;
C1=C2=C3=C4=1;
if(C1==0) i=8;
else if(C2==0)i=9;
else if(C3==0)i=10;
else if(C4==0)i=11;
R4=0;
R2=R3=R1=1;
C1=C2=C3=C4=1;
if(C1==0)i=12;
else if(C2==0)i=13;
else if(C3==0)i=14;
else if(C4==0)i=15;
}
return i;
}
矩阵键盘写法
void key_scan()
{
R1=0;
R2=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
//自己添加的按键按下后的代码
}
else if(C2==0)
{
while(C2==0);
//自己添加的按键按下后的代码
}
else if(C3==0)
{
while(C3==0);
//自己添加的按键按下后的代码
}
else if(C4==0)
{
while(C4==0);
//自己添加的按键按下后的代码
}
R2=0;
R1=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
//自己添加的按键按下后的代码
}
else if(C2==0)
{
while(C2==0);
//自己添加的按键按下后的代码
}
else if(C3==0)
{
while(C3==0);
//自己添加的按键按下后的代码
}
else if(C4==0)
{
while(C4==0);
//自己添加的按键按下后的代码
}
R3=0;
R2=R1=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
//自己添加的按键按下后的代码
}
else if(C2==0)
{
while(C2==0);
//自己添加的按键按下后的代码
}
else if(C3==0)
{
while(C3==0);
//自己添加的按键按下后的代码
}
else if(C4==0)
{
while(C4==0);
//自己添加的按键按下后的代码
}
R4=0;
R2=R3=R1=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
//自己添加的按键按下后的代码
}
else if(C2==0)
{
while(C2==0);
//自己添加的按键按下后的代码
}
else if(C3==0)
{
while(C3==0);
//自己添加的按键按下后的代码
}
else if(C4==0)
{
while(C4==0);
//自己添加的按键按下后的代码
}
}
独立按键写法1
比较推荐这个写法
sbit s7=P3^0;
sbit s6=P3^1;
sbit s5=P3^2;
sbit s4=P3^3;
char anjian()
{
char keyanjian;
if(s4==0||s5==0||s6==0||s7==0)
{
delay(10);
if(s4==0)keyanjian=4;
else if (s5==0)keyanjian=5;
else if (s6==0)keyanjian=6;
else if (s7==0)keyanjian=7;
}while(s4==0||s5==0||s6==0||s7==0);
return keyanjian;
}
独立按键写法2
sbit s6=P3^1;
void anjian()
{
if(s6 == 0)
{
delay(100);
if(s6==0)
{
EA=~EA;
while(s6 == 0);
{
//自己添加的按键按下后的代码
}
}
}
//后面以此类推
总代码
#include<stc15f2k.h>
char dula[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
char disdula[]={0,0,0,0,0,0,0,0};
sbit s7=P3^0;
sbit s6=P3^1;
sbit s5=P3^2;
sbit s4=P3^3;
bit ms100_flag=0;
int diswei=0;
int s,f,m,a;
void delay(int x)
{
int t;
while(x--)
for(t=0;t<5*123;t++);
}
void buzz(bit on)
{
P2=((P2&0x1f)|0xa0);
if(on)
P0=0x40;
else
P0=0x00;
P2&=0x1f;
P2=((P2&0x1f)|0x80);
P0=0xff;
P2&=0x1f;
}
void din()
{
TMOD=0X10;
TH1=(65536-110592/12)/256;
TL1=(65536-110592/12)%256;
ET1=1;
EA=1;
TR1=1;
}
void display()
{
P2=((P2&0x1f)|0xe0);
P0=0xff;
P2&=0x1f;
P2=((P2&0x1f)|0xc0);
P0=1<<diswei;
P2&=0x1f;
P2=((P2&0x1f)|0xe0);
P0=dula[disdula[diswei]];
P2&=0x1f;
if(diswei++>=8)diswei=0;
}
void display_1()
{
disdula[0]=s/10%10;
disdula[1]=s/1%10;
disdula[2]=10;
disdula[3]=f/10%10;
disdula[4]=f/1%10;
disdula[5]=10;
disdula[6]=m/10%10;
disdula[7]=m/1%10;
}
char anjian()
{
int keyscan;
P3=0x0f;P42=P44=0;
if(s4==0||s5==0||s6==0||s7==0)
{
delay(10);
P34=P35=P42=P44=1;
P44=0;
if(s4==0) keyscan=4;
else if(s5==0) keyscan=5;
else if(s6==0) keyscan=6;
else if(s7==0) keyscan=7;
P42=0;
if(s4==0) keyscan=8;
else if(s5==0) keyscan=9;
else if(s6==0) keyscan=10;
else if(s7==0) keyscan=11;
P35=0;
if(s4==0) keyscan=12;
else if(s5==0) keyscan=13;
else if(s6==0) keyscan=14;
else if(s7==0) keyscan=15;
P34=0;
if(s4==0) keyscan=16;
else if(s5==0) keyscan=17;
else if(s6==0) keyscan=18;
else if(s7==0) keyscan=19;
}
P3=0x0f;P42=P44=0;
while(s4==0||s5==0||s6==0||s7==0);
return keyscan;
}
int key;
void main()
{
din();
buzz(0);
while(1)
{
if(ms100_flag==1)
{
ms100_flag=0;
key=anjian();
if(key==18)
display_1();
}
}
}
void qa() interrupt 3
{
TH1=(65536-11059/12)/256;
TL1=(65536-11059/12)%256;
display();
a++;
if(!(a%100))ms100_flag=1;
if(a>=1000)
{
a=0;
m++;
if(m>=60)
{
m=0;
f++;
if(f>=60)
{
f=0;
s++;
if(s>=24)
{
s=0;
}
}
}
}
}
省赛代码传送门
第三届蓝桥杯单片机省赛
第四届蓝桥杯单片机省赛
第五届蓝桥杯单片机省赛
第六届蓝桥杯单片机省赛
第七届蓝桥杯单片机省赛
第八届蓝桥杯单片机省赛
第九届蓝桥杯单片机省赛
第十届蓝桥杯单片机省赛
第十一届蓝桥杯单片机省赛