内容正文:
项目4 单片机接口技术
任务4-1 开关状态数码显示电路设计与仿真
1.任务分析
单片机制作一个拨码开关状态数码管显示电路,使用4位拨码开关作为输入,1位共阴极数码管作为输出,数码管对应4位拨码开关的二进制输入相应显示十六进制全部字符即0-9、a-f。
2.电路设计
#include <reg51.h> //预处理命令,定义51单片机各寄存器的存储器映射
unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77, 0x7c,0x39,0x5e,0x79,0x71}; //定义数组led存放0-9、a-f的字形码
void delay(unsigned char i); //延时函数声明
void main() //主函数
{
unsigned char i; //定义无符号字符型变量i
while(1) {
P1=0x00; //P1口清0
i=P1; //P1口接收状态赋值给变量i
P0=led[i]; //将数组中字形编码赋值给P0口
delay(200);
}
}
void delay(unsigned char i) //延时函数
{
unsigned char j,k; //定义无符号字符型变量j和k
for(k=0;k<i;k++) //双重for循环语句实现软件延时
for(j=0;j<255;j++);
}
相关知识
4.1数组的概念
数组就是把若干个相同数据类型的元素按一定顺序排列的集合,并把各元素用统一的名字命名,然后用编号进行区分,这个名字称为数组名,编号称为下标。数组中各个元素称为数组的分量,也称为数组元素,每个数组元素由数组名和下标唯一标识。数组可以用相同名字引用一系列变量,当需要处理若干相同类型的数据时,可以缩短和简化程序,便于程序设计。
在C语言中,数组属于构造数据类型。按数组元素的数据类型可分为:数值数组、字符数组、指针数组等;按照数组维度可分为:一维数组、二维数组、多维数组等。
1.一维数组
1)一维数组定义及数组元素的引用
一维数组就象数学中的数列,各元素排成一排,只需一个下标就可以确定数组元素相对位置。程序设计时,要想使用数组,必须先要对其进行定义。
一维数组定义形式为:
类型说明符 数组名[常量表达式];
说明:
(1)类型说明符:定义了数组中每一个元素的数据类型,同一个数组,所有数组元素具有相同的数据类型;
(2)数组名:由用户定义,但不能与其他变量重名。命名规则遵循标识符命名规则(由字母、数字和下划线组成,第一位必须是字母或者下划线,不能是数字);
(3)常量表达式:表示数组长度,即数组元素的总个数,可以为常量和符号常量,不能为变量,数组定义后其长度固定不能改变。
数组元素是组成数组的基本单元,必须先定义数组,才能使用数组元素。C语言中使用数组时不能一次引用整个数组,只能对数组元素进行依次引用。
数组元素的一般表示形式:
数组名[下标]
说明:
(1)下标表示元素在数组中的位置,只能是整型常量或整型表达式;
(2)下标不能越界。
2)一维数组初始化
数组的初始化是指在定义数组时对数组元素进行赋值,一般格式为:
类型说明符 数组名[数组长度]={各数组元素值};
例如:int n[5]={0,1,2,3,4,}; //则 n[0]=0,n[1]=1,...
数组初始化有以下2种方法:
(1)对全部数组元素赋初值。
例如:char a[8]={1,2,3,4,5,6,7,8};
此时数组定义中数组长度可以省略不写,根据数组元素的个数判断其长度。
例如:char b[ ]={1,2,3,4,5}; //等价于char b[5]={1,2,3,4,5};
(2)对部分数组元素赋初值。
例如:char a[8]={1,2,3}; //只给前3个数组元素赋初值,其余元素值为0。
例如:char a[8]={0}; //表示数组元素值全部为0。
2.二维数组
1)二维数组定义及数组元素的引用
二维数组就象数学中的矩阵,各元素先排成排,各排再排成列。需要两个下标才能唯一确定出数组元素。二维数组定义形式为:
类型说明符 数组名[常量表达式1] [常量表达式2];
说明:(1)常量表达式1:表示第一维下标长度(行数)。
(2)常量表达式2:表示第二维下标长度(列数)。
二维数组元素的一般表示形式:
数组名[下标1][下标2]
说明:(1)下标1为行标,下标2为列标共同确定元素在数组中位置,只能是整型常量或整型表达式;
(2)下标不能越界。
2)二维数组初始化
(1)对全部数组元素赋初值。
分行赋值
char b[2][4]={{1,2,3,4},{5,6,7,8}};赋值后数组个元素为
按行连续赋值
char b[2][4]={1,2,3,4,5,6,7,8};赋值后数组个元素为
对全部数组元素赋初值时,可省略第一位长度。
char b[][4]={1,2,3,4,5,6,7,8};赋值后数组个元素为
(2)对部分数组元素赋初值,未赋值元素自动取0。
分行赋值
int c[2][3]={{2,3},{5,6}};赋值后数组个元素为
或int c[2][3]={{2},{1,9}};赋值后数组个元素为
按行连续赋值。
int c[2][3]={0,1,2,3};赋值后数组个元素为
3.字符型数组
字符型数组也是一维或二维数组,它的数组元素都是字符型变量。字符数组的定义、引用和初始化方法与一维数组相同。
例如:
char num[5]; //定义字符型数组num,数组中有5个数组元素
char num[5]={‘h’,‘a’,‘p’,‘p’,‘y’}; //数组初始化
注:数组元素值由‘’括起。若只对部分元素赋值,则未赋值元素系统赋予空格字符‘\0’。
也可用字符串常量赋值,例如:
char num[5]={“happy”};
或char num[5]=“happy”;
4.2单片机与数码管接口
在单片机应用系统中,显示装置是一个重要的人机交互设备之一,是单片机应用系统中最基本的输出设备。常用的显示器件有发光二极管、LED数码管、点阵和LCD液晶显示器等。如果应用系统中只需要显示简单的数字或字母等信息,例如显示时间、日期、温度、运行状态等,LED数码管可谓是最佳选择,它具有成本低廉、显示清晰易懂、配置简单、性能稳定和使用寿命长等特点,在生活和工业中得到了广泛的应用。
LED数码管由多个发光二极管构成,按照包含发光二极管个数分为七段数码管和八段数码管(八段数码管比七段数码管多一个发光二极管即小数点显示)。通过控制二极管的亮灭组合,可以显示各种数字和字符。
1.LED数码管显示原理
下图为八段数码管的引脚图和内部结构图。
(a) 引脚图 (b)共阴极结构 (c)共阳极结构
数码管按照内部连接方式不同可分为共阴极和共阳极两种结构。
表4-1 数码管共阴极和共阳极特点
共阴极结构(见图4-4(b)) 共阳极结构(见图4-4(c))
连接方法 8个发光二极管阴极相连作为公共端,接低电平。 8个发光二极管阳极相连作为公共端,接高电平。
点亮方法 阳极作为段控制端,赋高电平,相应发光二极管导通被点亮。 阴极作为段控制端,赋低电平,相应发光二极管导通被点亮。
使用数码管时仅能将其点亮是不够的,还要能控制其显示出相应的数字或字符,通过分析可知需要对段控制端赋相应的段码(又称字型编码)。常用的字形编码如下表所示,当要显示某字符时,可根据需要进行查找。
显示字符 共阴极段码 共阳极段码 显示字符 共阴极段码 共阳极段码
0 3FH C0H c 39H C6H
1 06H F9H d 5EH A1H
2 5BH A4H E 79H 86H
3 4FH B0H F 71H 8EH
4 66H 99H P 73H 8CH
5 6DH 92H U 3EH C1H
6 7DH 82H T 31H CEH
7 07H F8H y 6EH 91H
8 7FH 80H H 76H 89H
9 6FH 90H L 38H C7H
A 77H 88H “灭” 00H FFH
b 7CH 83H ... ... ...
2.LED数码管显示方法
LED数码管有静态显示和动态显示两种方法。
1)静态显示方法及应用电路
数码管采用静态显示方式时,各位数码管的公共端连接在一起固定的接地或+5V,每个数码管的段控制端(a-dp)分别连接到单片机的一个8位I/O端口。确定显示字符后,由单片机I/O端口输出字型编码,控制数码管显示相应内容,此时各位数码管相互独立,稳定显示,直到接收到新的字型编码为止。
数码管静态显示应用举例。
例:单片机采用静态显示方式控制1位数码管循环显示a、b、c、d。
硬件电路设计:
#include <reg51.h> //预处理命令
void delay(unsigned char i) //延时函数
{
unsigned char j,k; //定义无符号字符型变量j和k
for(k=0;k<i;k++) //双重for循环语句实现软件延时
for(j=0;j<255;j++);
}
unsigned char led[ ]={0x88,0x83,0xC6,0xA1}; //定义数组led
void main() //主函数
{
unsigned char i;
while(1) {
for (i=0;i<4;i++)
{
P1=led [i]; //字型显示码送段控制口P1
delay(200);
}
}
}
2)动态显示方法及应用电路
数码管动态显示方法又称动态扫描,连接时将多位数码管的段选端(a-dp)并联到一起由一个8位I/O端口控制,每个数码管的位选端(公共端com)分别由一位I/O端口控制。通过位选端赋有效电平选择让哪一位数码管点亮,段选端赋字型编码确定被点亮数码管显示的字符。
动态显示方法就是控制各位数码管分时选通,实现依次轮流点亮,在某一时刻只有一位数码管显示,依次循环即可使各位数码管循环显示需要的内容。要想使多位数码管稳定显示,只需减小间隔时间(小于10ms),让循环显示的速度足够快,由于人眼存在视觉暂留效应,会认为所有数码管共同被点亮。
数码管动态显示应用举例。
例:单片机采用动态显示方式控制4位共阳极数码管动态显示a、b、c、d。
硬件电路设计:
#include <reg51.h> //预处理命令
void delay(unsigned char i) //延时函数
{
unsigned char j,k; //定义无符号字符型变量j和k
for(k=0;k<i;k++) //双重for循环语句实现软件延时
for(j=0;j<255;j++);
}
void main() //主函数
{
unsigned char led[]={0x88,0x83,0xC6,0xA1};//设置字符ABCD字型码
unsigned char i,w;
while(1) {
w=0x01; //位选码初值为01H
for(i=0;i<4;i++)
{
P2=~w; //位选码取反后送位控制口P2口
w<<=1; //位选码左移一位,选中下一位LED数码管
P1=led[i]; //显示字型码送P1口
delay(50); //延时
}
}
}
任务4-2 脉冲计数电路设计与仿真
1.任务分析
任务要求采用单片机制作一个脉冲计数电路,利用定时/计数器T0对外部输入脉冲进行计数,并将计数值显示在两位数码管上。
2.电路设计
#include<reg51.h> //预处理命令
sbit P3_0=P3^0; //位定义
sbit P3_1=P3^1;
unsigned char dat1,dat0;
unsigned char code Num[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,}; //定义数组存放0~9字形编码
void delay() //延时函数
{
unsigned int i,j;
for(i=20;i>0;i--) //双重for循环语句实现软件延时
for(j=100;j>0;j--);
}
void display() //显示函数
{
P3_1=0; //选中数码管1
P0=Num[dat0]; //个位数显示
delay();
P3_1=1;
P3_0=0; //选中数码管2
P0=Num[dat1]; // 十位数显示
delay();
P3_0=1;
}
void main(){
TMOD=0x05; //设置T0为计数器,工作方式1
TH0=0x00; //设置计数初值
TL0=0x00;
TR0=1; //启动计数器T0
P0=0xff;
P3=0xff;
while(1){
int dat; //定义整形变量dat
dat=TL0; //将计数值赋给dat
dat1=dat/10; //计数值的十位数
dat0=dat%10; //计数值的个位数
display(); //调用显示函数
}
}
相关知识
4.3定时/计数器
1.定时/计数器结构
51单片机内部有两个16位可编程定时/计数器T0和T1,每个定时/计数器又分别由两个8位特殊功能寄存器组成,T0由高8位TH0和低8位TL0组成,T1由高8位TH1和低8位TL1组成。同时单片机内部还包含一个工作方式控制寄存器TMOD和一个控制寄存器TCON。
2.定时/计数器功能
单片机内部定时/计数器同时具有定时和计数两种功能,都可通过编程实现。
计数功能:单片机定时/计数器可对外部脉冲(外部事件)进行计数。外部脉冲由单片机T0(P3.4)、T1(P3.5)两个引脚输入,输入脉冲下降沿有效,触发加法计数器加1(注:为了保证计数的正确性,要保证输入脉冲高低电平都在一个机器周期以上)。
定时功能:单片机定时/计数器用作定时功能时,也是通过计数实现的,只是对单片机内部机器周期脉冲进行计数。机器周期由震荡脉冲频率决定,如单片机采用6MHZ晶振,一个机器周期为2us; 采用12MHZ晶振,一个机器周期为1us,根据设置计数值,即可确定定时时间(定时时间=机器周期*计数值)。
3.工作方式控制寄存器TMOD
TMOD用于设置定时/计数器的工作方式,是一个8位特殊功能寄存器,其中高4位设置T1,低4位设置T0,设置方式完全相同。TMOD各位含义如下:
控制位 说明
定时/计数器T1 D7 GATE 门控卫 GATE=0:软件启动,设置控制位TR0或TR1为1启动定时器。
GATE=1:软硬件联合启动,在软件启动基础上,还需设置INT0(P3.2)或INT1(P3.3)为1时启动定时器。
D6 C/T 功能选择位 C/T=0:定时器工作方式;
C/T=1:计数器工作方式;
D5 M1 工作方式选择位 M1M0=00,工作方式0,13位计数器;
M1M0=01,工作方式1,16位计数器;
M1M0=10,工作方式2,初值自动重载8位计数器;
M1M0=11,工作方式3,T0分成2个8位计数器,T1停止计数。
D4 M0
定时/计数器T0 D3 GATE 门控卫 同上GATE。
D2 C/T 功能选择位 同上C/T。
D1 M1 工作方式选择位 同上M1、M0。
D0 M0
4.控制寄存器TCON
TCON用于控制定时/计数器启动、停止、溢出及中断。是一个8位特殊功能寄存器,其格式如下:
TCON低4位用于控制单片机中断,这里不作介绍。
1)TF1和TF0:定时/计数器T1和T0的溢出中断标志位。
T0或T1计数计满时,由硬件自动将其置1,并向CPU发出中断,中断响应后由硬件自动清零;该位也可做为查询测试标志,此时要及时以软件方式清0。
2)TR1和TR0: 定时/计数器T1和T0的运行控制位。
TR1或TR0位置1时,启动相应定时/计数器;TR1或TR0位置0时,关闭相应定时/计数器。
D7 D6 D5 D4 D3 D2 D1 D0
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
定时/计数器 中断
5.定时/计数器工作流程
6.定时/计数器工作方式
1)工作方式0
当TMOD中M1M0=00时,定时/计数器被选为工作方式0,13位定时/计数器,计数范围是0~8191,其最大计数值为8192(即213)。
工作在方式0,16位寄存器只用了13位,其中TL0的高3位未用。下面以定时/计数器T0为例介绍其内部结构。
当C/T=0时,T0为定时功能,对内部机器周期进行计数,TL0低5位计满直接向TH0进位,而TH0溢出时向中断标志位TF0进位申请中断。
定时时间=计数值*机器周期
即:t=(8192-T0初值)*12/时钟频率 (机器周期=1/(时钟频率*1/12))
当C/T=1时,T0为计数功能,对外部T0(P3.4)输入脉冲进行计数。当外部信号发生“1”到“0”跳变时,计数器加1。
当GATE=0时,软启动方式。此时或门输出恒为1,TR0=1时,定时/计数器T0启动;TR0=0时,定时/计数器T0停止。
当GATE=1时,软硬件共同启动方式。TR0=1同时还需INT0(P3.2)为高电平才能启动定时/计数器T0。
设置计数初值是定时/计数器应用重点,下面介绍设置计数初值方法:
计数值=定时时间/机器周期
计数初值=最大计数值-计数值
计算出来的结果转换为16进制数后分别写入TL0(TL1)、TH0(TH1)。
2)工作方式1
当TMOD中M1M0=01时,定时/计数器被选为工作方式1,16位定时/计数器,计数范围是0~65535,其最大计数值为65536(即216)。
工作方式1与工作方式0内部结构相同,只是计数位数为16位,TH0占高8位,TL0占低8位。
3)工作方式2
当TMOD中M1M0=10时,定时/计数器被选为工作方式2,初值自动重载8位定时/计数器,下面以定时/计数器T0为例介绍其内部结构。
工作方式2时,TL0为8位计数器,TH0为预置寄存器,用于保存计数初值,因此计数范围是0~255,其最大计数值为256(即28)。
在方式0和方式1中,计数计满产生溢出后,计数器里面的值变为0,要想再次计数,必须通过程序语句重新将计数初值送入计数器中,在循环定时和计数应用时,需要反复预置计数初值,影响定时精度。在需要精确定时的场合,可应用工作方式2,编程时,将初值分别付给TL0和TH0,TL0作为计数器开始计数,当计满溢出时,TH0自动将保存的初值装入TL0,重新开始计数。此种方式省去了软件中重装初值的程序,可达到精确定时。
4)工作方式3
当TMOD中M1M0=11时,定时/计数器被选为工作方式3,T0分成2个8位计数器,T1停止计数(只有T0可以设置为工作方式3)。其T0的内部结构如下。
TL0:即可定时也可计数。占用了原定时器T0的控制位、引脚和中断源。
TH0:简单的内部定时功能。占用了定时器T1的控制位TR1和中断标志位TF1。
定时/计数器T0定义为工作方式3时,T1可定义为方式0、方式1和方式2。
定时器方式应用举例。
例:采用单片机内部定时器制作一个5秒定时器,每计时5秒钟蜂鸣器报警提示,然后重新开始计时。
硬件电路设计:
#include <reg51.h>
sbit P1_0=P1^0; //位定义
unsigned char led[]={0xf9,0xa4,0xb0,0x99,0x92};
void delay1s() //采用定时器1实现1秒延时
{
unsigned char i;
for(i=0;i<20;i++) //设置20次循环次数
{
TH1=0x3c; //设置定时器初值为3CB0H
TL1=0xb0;
TR1=1; //启动T1
while(!TF1); //查询计数是否溢出,即定时50ms时间到,TF1=1
TF1=0; //50ms定时时间到,将T1溢出标志位TF1清零
}
}
void main() //主函数
{
unsigned char i;
TMOD=0x10; //设置定时器1工作于方式1
while(1) {
P1_0=1;
for(i=0;i<5;i++)
{
P2=led[i]; //字型显示码送段控制口P2
delay1s(); //延时1秒
}
P1_0=0; //蜂鸣器报警提示
delay1s();
}
}
任务4-3 点阵显示电路设计与仿真
1.任务分析
任务要求采用单片机制作一个8*8的LED点阵显示电路,该任务通过单片机的P0口和P3口连接一个8*8LED点阵,实现在点阵屏上循环显示A、1、B、2。当单片机上电开始运行时,LED点阵屏显示字母A,在经过一点时间后,依次轮流显示1、B、2、A……,一直循环显示运行。
2.电路设计
#include <reg51.h>
void delay1ms() //1ms延时子函数
{
TH1=(65536-1000)/256; //设置定时器初值
TL1=(65536-1000)%256;
TR1=1; //启动T1
while(!TF1); //查询计数是否溢出,即定时50ms时间到,TF1=1
TF1=0; //1ms定时时间到,将T1溢出标志位TF1清零
}
void main() //主函数
{
unsigned char code led[4][8]={{0xff,0xe7,0xdb,0xbd,0xbd,0x81,0xbd,0xbd}, //A
{0xff,0xe7,0xe3,0xe7,0xe7,0xe7,0xe7,0xe7}, //1
{0xff,0xc1,0xbd,0xbd,0xc1,0xbd,0xbd,0xc1}, //B
{0xff,0xe1,0xcf,0xcf,0xe3,0xf9,0xf9,0xc1}};//2
//定义4*8二维数组存放A、1、B、2字型码
unsigned char i;
unsigned int lie,hang,count;
TMOD=0x10; //设置定时器1工作于方式1
while(1) {
for(hang=0;hang<4;hang++) //第一维下标取值范围0~3
{
count=100;
while(count>0) //控制每个字符显示时间
{
i=0x01;
for(lie=0;lie<8;lie++) //第二维下标取值范围0~7
{
P0=i;
P3=led[hang][lie]; //将指定数组元素赋值给P3口
delay1ms();
i<<=1;
}
count--;
}
}
}
}
相关知识
4.4单片机与点阵接口电路
LED点阵屏按发光原理可分为单色、双色和全彩三类,可显示红、橙、黄、绿、蓝等多种颜色。常用的LED点阵显示模块有4×4、4×8、5×7、5×8、 8×8、16×16等多种结构,每种结构都是由多个LED发光二极管组成,下面以8×8点阵为例进行详细介绍。
1.LED点阵结构
一个数码管是8个LED发光二极管组成,同理,一个8*8的点阵是由64个LED发光二极管组成。
8*8LED点阵内部的64个发光二极管按矩阵形式排列,构成8行8列,共16个引脚,行引脚为0~7,列引脚为A~H。其内部结构图如下:
2.LED点阵显示原理
由内部结构图可知8*8点阵内部的64个发光二极管全部跨接在行线和列线的交叉点上,根据发光二极管的单向导通性,当某个发光二极管连接的行置高电平(1),列置低电平(0)时,该二极管被点亮。通过控制每个二极管发光,完成各种显示内容。
LED点阵显示类似于数码管,也采用动态扫描的显示方式,即依次点亮各行,进行行扫描(或依次点亮各列,进行列扫描)。
下面以显示心形图形为例,进行过程讲解。
无论显示字符、图形还是文字,都是通过控制组成这些字符、图形或文字的各个点所在位置相对应的二极管发光实现的。通常事先要把需要显示的图形文字转换成点阵图形,再按照显示控制的要求以一定格式形成显示数据。当8*8LED点阵需要显示 时,先要建立一个8*8的方格表,在方格表中按照显示要求填好要显示的内容,见与4-20,黑色的格子表示被点亮,当选中第一行(赋高电平)时,给各列赋值11111111B(FFH);当选中第二行(赋高电平)时,给各列赋值10011001B(99H),依次类推,到选中第八行(赋高电平)时,给各列赋值11100111B(E7H),八行全扫描显示1次,再重新扫描显示第一行,如此不断循环,并使循环显示速度足够快时(应保证扫描8行所用时间之和在20ms以内),既能看到稳定显示整个图形。
3.LED点阵接口技术
使用LED点阵作为显示设备时,可单独使用一片进行简单显示,也可同时使用多片相组合进行较大图片或文字显示。
单片机与一片8*8LED点阵接口电路比较简单,其框图如下:
8*8LED点阵共16个引脚,8个行引脚和8个列引脚,需要占用单片机2个P口进行控制,这里以P3口控制行引脚,P0口控制列引脚为例进行说明。
实际应用中,往往需要进行复杂文字或图像的显示,单独使用一片LED不能满足要求,可以多片结合共同使用。多片8*8LED点阵可构成8*16(2片)、16*16(4片)、16*32(8片)和32*32(16片)等多种规格的LED大屏,其显示电路相对复杂,现以8*16LED点阵为例进行电路分析。
2片8*8LED点阵相连,点阵1和点阵2的行引脚并联到一起构成8个行引脚由单片机P3口控制,高电平为有效信号;点阵1和点阵2的列引脚共同组成16个列引脚,由单片机P0口和P1口共同控制,低电平为有效信号。其显示依然采用动态扫描方式,通过P3口赋有效电平依次选通各行,同时给P0口和P1口赋16位的列数据。
任务4-4 单独键盘电路设计与仿真
1.任务分析
单片机采集外界状态常见元器件为按键、传感器和电信号,本任务通过对按键和发光二极管的控制,实现发光二极管显示按键状态的仿真电路设计及控制程序设计。任务要求按键为4个按键,发光二极管也为4个。
2.电路设计
根据任务要求,设计AT89C51单片机的P2.4,P2.5,P2.6,P2.7分别接独立式键盘,P2.0,P2.1,P2.2,P2.3通过电阻接发光二极管,编程实现键状态显示,要求采用去抖动措施,单片机控制单独键盘电路如图所示。
仿真结果
相关知识
单片机应用系统应具有人机对话功能,除了通过LED数码管等设备报告系统运行状态与运行结果外,控制人员还应该能随时向应用系统发出控制命令,以及向系统输入数据。因此,应用系统的硬件电路板上应设有按键或键盘,如按键复位电路中的按镀、功能转换的功能镀以及输入数据的数字键等。
4.5 键盘接口介绍
1.常见开关种类
按键按照结构原理可分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关等;另一类是无触点开关按键,如电气式按键,磁感应按键等。前者造价低,后者寿命长。按键按照接口原理可分为编码键盘与非编码键盘两类,这两类键盘的主要区别是识别键符及给出相应键码的方法。编码键盘主要是用硬件来实现对按键的识别,硬件结构复杂;非编码键盘主要是由软件来实现按键的定义与识别,硬件结构简单,软件编程量大。编码键盘内部带有硬件编码器,它是通过硬件来识别键盘上的闭合键,优点是工作可靠、按键编码速度快且基本不占CPU的时间,但电路复杂,成本较高;
非编码键盘是通过软件来识别键盘上的闭合键,优点是硬件电路简单,成本较低,但占用CPU的时间长。在实际的单片机应用系统设计中,往往为了降低成本,大多采用非编码键盘。
2.按键去抖
键盘是按照一定规则排列起来的一组按键的集合,而每一个按键实质上就是一个开关。目前,无论是按键还是键盘,大多数都是利用机械触点闭合、断开作用,机械触点由于弹性作用的影响,在按键闭合及断开的瞬间都有抖动现象,如图4-26所示。抖动时间的长短与开关的机械特性有关,一般为5~10ms,为了保证CPU对按键的闭合仅作一次键输入处理,就必须去除抖动的影响,也就是去抖问题
独立式按键电路
矩阵式键盘
3.单片机对非编码键盘的控制方式
在单片机应用系统中,对非编码键盘的控制方式一般有程序扫描方式(查询方式)、定时控制扫描方式和中断控制扫描方式三种。
1)程序控制扫描方式
(1)粗扫描
(2) 逐列扫描
(3)求键值
(4)求得键值后,再读取行码X3 X2 Xl X0,若行码为非全1,键未释放,则等待。等键释放以后,根据求得的键值转向相应的键处理子程序。
2)定时控制扫描方式
3)中断控制方式
任务4-5 简单计数器电路设计与仿真
1.任务分析
生活中常常需要计数,如何能用单片机中断系统进行简单计数和清零呢,本任务是设计一个简单计数器,要求能计数位数为3位,同时具有清零功能。
相关知识
4.6 中断系统
1.中断及相关概念
(1)什么叫中断
中断是指CPU正在处理某件事情的时候,外部发生了某一事件,请求CPU迅速处理。或者CPU的快速与外设的慢速发生了矛盾时,CPU暂时中断当前的工作,转而处理所发生的其它事件,处理完以后,再回来继续执行被中止的工作,这个过程称为中断。
(2)什么叫中断系统
实现中断功能的部件称为中断系统。
(3)什么叫中断源
引起中断的原因,或能发出中断申请的来源,统称为中断源。
(4)什么叫主程序
原来正在运行的程序称为主程序,它可以调用其它子程序。
(5)什么叫断点
主程序被断开的位置称为断点。计算机采用中断技术,能够大大提高它的效率和处理问题的灵活性。
2.中断优点
具有同步工作、实时处理和故障处理等优点。
同步工作:计算机有了中断功能后,就能解决快速CPU和慢速外设之间的矛盾,从而可使CPU和外设同步工作。
实时处理:在实时控制中,现场采集的各种数据总是不断变化的。有了中断功能,外界的这些变化的数据就可根据要求,随时向CPU发出中断请求,要求CPU及时响应,加以处理,这样的处理在查询方式下是很难做到的。
故障处理:当计算机在运行过程中,出现一些事先无法预料的故障是难免的,如电源消失、存储数据出错、运算溢出等。当我们有了中断功能,计算机就能自行进行处理,而不必停机。
80C51中断源及中断系统结构图
1)外部中断源
外部中断0请求,通过P3.2脚输入。由IT0(TCON.0)引脚来决定什么情况下有效,是低电平有效还是负跳变有效。当输入有效信号时,当输入有效信号时,由内部硬件置位IE0,即向CPU发出中断申请,以便识别。
外部中断l请求,通过P3.3脚输入。由IT1(TCON.2)引脚来决定什么情况下有效,是低电平有效还是负跳变有效。当输入有效信号时,由内部硬件置位IE1,即向CPU发出中断申请,以便识别。
2)定时器/计数器0、1的溢出中断TF0和TF1
TF0为定时器T0溢出中断请求。当定时器T0产生溢出时,定时器T0中断即请求标志TF0置位,请求中断。
TF1为定时器T1溢出中断请求。当定时器T1产生溢出时,定时器T1中断即请求标志TF1置位,请求中断。
3)串行口中断
RI或TI为串行中断请求。当接收或发送完一串行帧时,置位内部串行口中断即请求标志RI或TI,请求中断。
5.特殊功能寄存器
1)定时器控制寄存器TCON的中断标志
TCON是用来存放两个定时器/计数器的溢出中断请求标志和两个外部中断请求标志,同时也是定时器/计数器0和l的控制寄存器。该寄存器的地址为88H,位地址8FH~88H。TCON寄存器与中断有关的位如下所示:
IE0(IE1) :外部中断请求标志位,当CPU采样到或端出现有效的中断请求时,此位由硬件置1,表示外部事件请求中断。在中断响应完成后转向中断服务时,该标志被内部硬件自动清除。
IT0(IT1):外中断请求信号方式控制位,当IT0(IT1)=1时,选择脉冲触发方式(又称边沿触发方式,分为负跳变和正跳变),负跳变有效;当IT0(IT1)=0时,选择电平触发方式(分为高电平和低电平),低电平有效。该位由用户设置。
TF0(TP1):定时器的中断溢出标志位,当产生溢出时,此位由硬件置1,当定时器/计数器转向中断服务时,由硬件自动清零。
2)串行口控制寄存器SCON的中断标志
串行口控制寄存器SCON低二位用来作为串行口中断请求标志。该寄存器的址是98H,位地址为9FH~98H。串行口控制寄存器SCON与中断有关的位如下所示:
RI:串行口接收中断请求标志位。当硬件置1时,表明80C51接收到一帧串行数据。需要注意的是当CPU转向中断服务程序后,该位应由软件清零。
TI:串行口发送中断请求标志位。当便件置1时,表明80C51发送完一帧串行数据。在转向中断服务程序后,该位也应由软件清零。
3)中断允许控制寄存器IE
在80C51单片机中断系统中,中断的允许或禁止是由片内的中断允许寄存器IE控制的。IE寄存器的地址是A8H,位地址为AFH~A8H。其内容和位地址如下:
EA:中断允许总控制位。EA=0时,表示所有的中断请求被屏敞,即CPU禁止所有中断;EA=1时,则表示CPU开放中断,但每个中断源的中断请求是允许还是禁止,须由各自的允许位来控制和进行。
EX0(EX1):外部中断允许控制位。EX0(EX1)=1,允许外部中断;EX0(EX1)=0,禁止外部中断。
ET0(ETl):定时器/计数器的中断允许控制位。ET0(ET1)=l,允许定时器/计数器中断;ET0(ET1)=0,禁止定时器/计数器中断。
ES:串行中断允许控制位。ES=1,允许串行中断;ES=0,禁止串行中断。
中断允许寄存器中各相应位的状态,可根据要求用指令置位或清零。
4)中断优先级控制寄存器IP
80C51单片机的中断优先级控制,系统只定义了高、低两个优先级。各中断源的优先级由优先级控制寄存器IP来进行设定。
IP寄存器地址是B8H,位地址为BFH~B8H。寄存器的内容及位地址表示如下:
PX0:外部中断0优先级设定位。PX0=1,外部中断0定义为高优先级中断;PX0=0,外部中断0定义为低优先级中断。
PT0:定时器T0中断优先级设定位。PT0=1,定时器T0定义为高优先级中断;PT0=0,定时器T0定义为低优先级中断。
PX1:外部中断1优先级设定位。 PX1=1,外部中断1定义为高优先级中断;PX1=0,外部中断1定义为低优先级中断。
PT1:定时器T1中断优先级设定位。PT1=1,定时器T1定义为高优先级中断;PT1=0,定时器T1定义为低优先级中断。
PS:串行口中断优先级设定位。PS=1,串行口中断定义为高优先级中断;PS=0,串行口中断定义为低优先级中断。
中断响应过程
中断响应过程就是自动调用并执行中断函数的过程。
C51编译器支持在C源程序中直接以函数形式编写中断服务程序。常用的中断函数定义语法如下:
void 函数名() interrupt n
其中n为中断类型号,C51编译器允许0~31个中断,n取值范围0~31。下面给出了8051控制器所提供的5个中断源所对应的中断类型号和中断服务程序入口地址:
$$