定时器中断"/>
蓝桥杯单片机之矩阵按键+定时器中断
矩阵按键原理图
需要按照红色标记将J5的跳线帽连接
原理图分析
矩阵按键由四行四列组成,连接着P30~P37共8个I/O口。每个按键左边连接着列信号,右边连接着行信号。编程时,可以通过随行与列的扫描来识别哪个按键被按下。
因此,我们可以得到矩阵键盘的基本扫描步骤:
<1> P30输出低电平,P31、P32、P33输出高电平,逐个读取判断列信号,如果都为高电平则P30行上没有按键按下。
<2> P31输出低电平,P30、P32、P33输出高电平,逐个读取判断列信号。
<3> P32输出低电平,P30、P31、P33输出高电平,发现P36列信号为低电平,那么可以判断得P32行的P36列的按键有按下动作。
<4> P33输出低电平,P30、P32、P33输出高电平,逐个读取判断列信号。
在含有转接板的蓝桥杯高速开发板中,原理图上的P36、P37分别连接的IAP15单片机的P42、P44引脚,编写代码时,注意更换引脚
矩阵按键扫描显示数值代码
#include <reg52.h> //引用芯片头文件
#include "intrins.h" //延时函数所需要的头文件sfr P4 = 0xC0;sbit P30 = P3 ^ 0;
sbit P31 = P3 ^ 1;
sbit P32 = P3 ^ 2;
sbit P33 = P3 ^ 3; sbit P37 = P4 ^ 4;
sbit P36 = P4 ^ 2;
sbit P35 = P3 ^ 5;
sbit P34 = P3 ^ 4;unsigned char button = 0;void Delay500us();
void key16(void);
void close_buzz(void);
void Display(long int number);
void HC_138(unsigned char Y_C);
void Digital_Tube(unsigned char Position, unsigned char Typeface);void Delay500us() //@12.000MHz
{unsigned char i, j;i = 6;j = 211;do{while (--j);} while (--i);
}void Digital_Tube(unsigned char Position,unsigned char Typeface) //Position是数码管第几位(从左到右,0开始),Typeface是显示的字样
{ unsigned char Bit[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; unsigned char SMG_NoDot[19] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0xff}; //0-9、A-F、'-'、'.'P2 = P2 & 0x1f | 0xc0;P0=Bit[Position];P2 = P2 & 0x1f | 0xe0;P0=SMG_NoDot[Typeface];Delay500us();P0=0XFF;P2 = P2 & 0x1f ; //数码管消影
}void Display_right(long int number)
{long int i,a,b;for(i=0;i<8;i++){a=number%10;Digital_Tube(7-i,a);b=number/10;if(b==0) break;number=b;}
}void close_buzz(void)
{P2 = ((P2 & 0x1f) | 0xa0); //关闭Y5控制的全部外设 P0 = 0x00; P2 &= 0x1f;P2 = (P2 & 0x1f) | 0x80; //同理关闭LED模块P0 = 0xff; P2 &= 0x1f;
}void Scan16Keys()
{P37 = 0;P34 = P35 = P36 = 1;P30 = P31 = P32 = P33 = 1;if (P33 == 0){while (P33 == 0);button = 4;}else if (P32 == 0){while (P32 == 0);button = 5;}else if (P31 == 0){while (P31 == 0);button = 6;}else if (P30 == 0){while (P30 == 0);button = 7;}P36 = 0;P34 = P35 = P37 = 1;P30 = P31 = P32 = P33 = 1;if (P33 == 0){while (P33 == 0);button = 8;}else if (P32 == 0){while (P32 == 0);button = 9;}else if (P31 == 0){while (P31 == 0);button = 10;}else if (P30 == 0){while (P30 == 0);button = 11;}P35 = 0;P34 = P36 = P37 = 1;P30 = P31 = P32 = P33 = 1;if (P33 == 0){while (P33 == 0);button = 12;}else if (P32 == 0){while (P32 == 0);button = 13;}else if (P31 == 0){while (P31 == 0);button = 14;}else if (P30 == 0){while (P30 == 0);button = 15;}P34 = 0;P35 = P36 = P37 = 1;P30 = P31 = P32 = P33 = 1;if (P33 == 0){while (P33 == 0);button = 16;}else if (P32 == 0){while (P32 == 0);button = 17;}else if (P31 == 0){while (P31 == 0);button = 18;}else if (P30 == 0){while (P30 == 0);button = 19;}
}void main(void)
{close_buzz();while (1){Scan16Keys();Display_right(button);}
}
STC15F2K60S2系列单片机定时器简介
STC15F2K60S2系列单片机内部设置了3个16位定时器/计数器:16位定时器/计数器T0、T1、T2。3个16位定时器T0、T1、T2都具有计数方式和定时方式两种工作方式。对定时器/计数器TO和T1,用它们在特殊功能寄存器TMOD中相对应的控制位—CT来选择T0或T1为定时器还是计数器。对定时器/计数器T2,用辅助寄存器AUXR中的控制位一T2_CT来选择T2为定时器还是计数器。
定时器/计数器的核心部件是一个加法计数器,其本质是对脉冲进行计数。只是计数脉冲来源不同:如果计数脉冲来自系统时钟,则为定时方式,此时定时器/计数器每12个时钟或者每1个时钟得到一个计数脉冲,计数值加1;如果计数脉冲来自单片机外部引脚(T0为P3.4,T1为P3.5,T2为P3.1),则为计数方式,每来一个脉冲加1。
定时器中断系统相关的寄存器
符号 | 描述 | 地址 | 位地址及符号 | 复位值 | |||||||
MSB | LSB | ||||||||||
IE | Interrupt Enable | A8H | EA | ELVD | EADC | ES | ET1 | EX1 | ET0 | EX0 | 0x00 0000B |
IE2 | Interrupt Enable | AFH | -- | ET4 | ET3 | ES4 | ES3 | ET2 | ESPI | ES2 | 0x00 0000B |
TCON | Timer/Counter 0 and 1Control | 88H | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 | 0000 0000B |
AUXR | 辅助寄存器 | 8EH | T0x12 | T1x12 | UART_M0x6 | T2R | T2_C/T | T2x12 | EXTRAM | S1ST2 | 0000 0000B |
中断控制允许寄存器
中断允许寄存器IE是只有打开全局开关,其它各位的开关才可以开启!!!!!!!!每个位开关赋值为1则开,赋值为0则关。
SFR name | Address | bit | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|---|
IE | A8H | name | EA | ELVD | EADC | ES | ET1 | EX1 | ET0 | EX0 |
EA: CPU的总中断允许控制位,EA=1,CPU开放中断,EA=0,CPU屏蔽所有的中断申请。EA的作用是使中断允许形成多级控制。即各中断源首先受EA控制;其次还受各中断源自己的中断允许控制位控制。
ET1: 定时/计数器T1的溢出中断允许位,ET1=1,允许T1中断,ET1=0,禁止T1中断。
ETO: T0的溢出中断允许位,ETO=1允许TO中断,ETO=0禁止TO中断。
SFR name | Address | bit | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|---|---|---|
IE2 | AFH | name | - | ET4 | ET3 | ES4 | ET3 | ET2 | ESPI | ES2 |
ET2: 定时器2的中断允许位。
ET2=1,允许定时器2产生中断;ET2=0,禁止定时器2产生中断
使用的两种方法:
- 整体赋值(十六进制赋值)
IE=0x82; //( 开启全局中断,打开定时器0中断)
- 单独赋值(寄存器支持位寻址)
EA=1;ET0=1; //(开启全局中断,打开定时器0中断)
定时器相关寄存器
符号 | 描述 | 地址 | 位地址及其符号 | 复位值 | |||||||
MSB | LSB | ||||||||||
TCON | 定时器控制寄存器 | 88H | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 | 0000 0000B |
TMOD | 定时器模式寄存器 | 89H | GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 | 0000 0000B |
AUXR | 辅助寄存器 | 8EH | 0000 0000B | ||||||||
TL0 | Timer Low 0 | 8AH | 0000 0000B | ||||||||
TL1 | Timer Low 1 | 8BH | 0000 0000B | ||||||||
TH0 | Timer High 0 | 8CH | 0000 0000B | ||||||||
TH1 | Timer High 1 | 8DH | 0000 0000B | ||||||||
T2H | Timer High 2 | D6H | 0000 0000B | ||||||||
T2L | Timer Low 2 | D7H | 0000 0000B |
开发手册:
定时器/计数器控制寄存器TCON
截取定时器相关部分:
根据开发手册总结:
定时/计数器的最基本工作原理是进行计数。作为定时器时,计数信号的来源选择周期性的内部时钟脉冲;用作计数器时,计数信号的来源选择非周期性的外部输入信号。 不管是定时器还是计数器,本质上都是计数器。
15系列51单片机有三个定时/计数器T0、T1、T2,为16位加法计数器,由低8位TL0(TL1、T2L)和高8位TH0(TH1、T2H)两个寄存器组成,最大计数值为65535个计数脉冲。
每接收到一个计数脉冲,计数器就会加1,当计数值累计至全为1时(8位255,13位8191,16位65535),再输入一个计数脉冲,计数器便会溢出回零,并且计数器的溢出是TCON寄存器的TF0或TF1位置1,同时向内核提出中断请求。
假如要定时10ms,则相当于计数10000个脉冲后计数器的值就到达65535了,那么开始计数的这个地方就是计数初值。
65535 - 10000 = 55535 = 0xd8ef
把这个计算得到的初值写入TH0和TL0寄存器即可:(12T模式下,即12分频)
THX =12/对应的系统时钟频率(晶振频率)(65535-你所需要的时间)/256
TLX =12/对应的系统时钟频率 (晶振频率)(65535-你所需要的时间)%256
3个定时器的初始化函数以及对应的中断服务函数示例
#include <STC15F2K60S2.h>void Time0_Serve() interrupt 1
{TL0 = 0x00; //设置定时初值TH0 = 0xDC; //设置定时初值i++;if(i == 100){i = 0;Test0 = !Test0;}
}void Time1_Serve() interrupt 3
{TL1 = 0x00; //设置定时初值TH1 = 0xDC; //设置定时初值j++;if(j == 100){j = 0;Test1 = !Test1;}
}void Time2_Serve() interrupt 12
{T2L = 0x00; //设置定时初值T2H = 0xDC; //设置定时初值k++;if(k == 100){k = 0;Test2 = !Test2;}
}
void Timer0Init(void) //10毫秒@11.0592MHz
{AUXR &= 0x7F; //定时器时钟12T模式TMOD &= 0xF1; //设置定时器模式 01TL0 = 0x00; //设置定时初值TH0 = 0xDC; //设置定时初值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时EA = 1;ET0 = 1;TR0 = 1;
}void Timer1Init(void) //10毫秒@11.0592MHz
{AUXR &= 0xBF; //定时器时钟12T模式TMOD &= 0x1F; //设置定时器模式 01TL1 = 0x00; //设置定时初值TH1 = 0xDC; //设置定时初值TF1 = 0; //清除TF1标志TR1 = 1; //定时器1开始计时EA = 1;ET1 = 1;TR1 = 1;
}//跟定时器0、1的方式2一样
void Timer2Init(void) //10毫秒@11.0592MHz
{AUXR &= 0xFB; //定时器时钟12T模式T2L = 0x00; //设置定时初值T2H = 0xDC; //设置定时初值AUXR |= 0x10; //定时器2开始计时EA = 1;IE2 |= 0x04; //IE2寄存器的第三位就是 定时器2的使能位
}
``
更多推荐
蓝桥杯单片机之矩阵按键+定时器中断
发布评论