郭天祥十天带你精通弹单片机学习笔记第三弹

第三课,数码管显示原理和中断
在这里插入图片描述
了解80C51各个引脚的功能,如图,主要注意P0口都外接了10K的上拉电阻,将使1为输出稳定为高电平。

用数码管显示数字。
LED灯由八段灯管组成,为构成八字形的七段灯管a~g和小数点h.
在这里插入图片描述
LED显示器有两种接法,共阴极和共阳极。共阴极即阴极接0,由单片机决定阳极的0和1来决定哪些段亮,单片机输出1时亮;共阳极反之,阳极都接Vcc,阴极由单片机决定,单片机输出0时亮
数码管的静态显示:每个数码管的段选必须接一个8位数据线来保持显示的字形码,当送入一次字形后,显示字形可以一直保持,直到送入新的字形。

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x5d,0x7d,0x07,
0x6f,0x77,0x7c,0x39,
0x5e,0x79,0x71,0x00}; // 使用数组,中括号中输入某个数值,返回对应第几个元素,这里数组中为从0到9,a到f,全灭对应P0口应该输出的十六进制数值
sbit wela=P2^7
sbit dula=P2^6
uint x,y,z,num;
void delay(uint);
void main()
{
	wela=1;
	P0=0xfc; //此时WEI1和WEI2为0(共阴极),即LED1和2都亮
	wela=0;
	for(num=0;num<16;num++)
	{
		dula=1;
		P0=table[num];  //根据num选择数组中第几个元素
		dula=0;
		delay(100);
	}
}
void delay(uint z)
{
	for(x=z;x>0;x--)
		for(y=100,y>0;y--);
}

这里不同数码管同时显示只能是相同的字形,如果要实现不同数码管显示不同字形,比如第一个1,第二个2,可以每次只控制一个数码管,delay时间极短时,由于视觉暂留,看起来就像是所有数码管同时显示,这就是动态扫描。

80C51中断系统结构(是魔鬼吗,学了好几遍)
是什么?
CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生),CPU暂停事件A去处理B(中断响应和服务),处理完B后返回原来事件A被暂停的地方,继续处理事件A的过程就是中断。

C51有五个中断源,即能请求中断的引脚
在这里插入图片描述
这张图很重要,这里把端口看做是开关,置1和置零表示接入或断开,或者双向选择。EA为总开关,控制所有的中断发生。左边表示5个中断源,从上至下分别为外部中断0,定时/计数器0,外部中断1,定时计数1,串行口。外部中断0通过IT0置1或0来控制中断信号是下降沿还是低电平触发。下降沿为电平由高跳变到低的瞬间触发中断,中断程序执行完后自动回到主程序;**低电平则需要人为使电平回到高电平后才能继续主程序,**否则一直处于中断。
在这里插入图片描述
TCON是各种中断控制,低四位中IE0和IE1是外部中断0和1的中断请求控制,IT0和IT1是触发方式控制;高四位中一般只需操作TF0和TF1,是定时计数中断请求控制。
一个栗子

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x5d,0x7d,0x07,
0x6f,0x77,0x7c,0x39,
0x5e,0x79,0x71,0x00}; 
sbit dula=P2^6;
sbit wela=P2^7;
sbit d1=P1^0;
uint x,y,z,num,tt;
void delay(uint);
void main()
{
	EA=1;//打开总中断控制
	EXO=0;//打开外部中断0允许
	IT0=0;//设置外部中断触发为低电平
	wela=1;
	P0=0xc0; //位选置数,打开LED1和LED2
	wela=0;
	while(1)
	{
		if(tt==20)
		{
			tt=0;
			num++;
			if(num==16)
			{num=0;}
			dula=1;
			P0=table[num];
			dula=0;
			delay(100);
		};
	}
}
void delay(uint z)
{
	for(x=z;x>0;x--)
		for(y=600;y>0;y--);
}	
void exter0() interrupt 0 // 中断服务程序,0是优先级第一级,即外部中断0,优先级参见下图
{
	d1=0;
}

在这里插入图片描述
INT0口接低电平会触发中断程序,其他条件都满足时运行进入中断服务程序。

定时/计数器
在这里插入图片描述
定时计数器是16位加1计数器,由高八位(THX)低八位(TLX)两个寄存器组成,原理可以看数电中各种计数器,总之就是每来一个脉冲信号计数器加1,直到满了进位同时清零
TMOD控制定时计数器的工作方式,高八位为TI方式,低八位为T0方式(两者好像没啥区别),T!和T0都有以下四个位
GATE一般设置为0即可
C/T 置0时是定时模式,置1计数模式
M1M0 决定工作方式:
00:13位定时计数器
01:16位定时计数器
10:8位自动重复定时
11:T0分为两个独立的8位定时计数器,T1没有此模式
在这里插入图片描述

定时计数器的启动由TCON的TR0和TR1控制,置1时对应的定时计数器工作。

如何初始设置
在这里插入图片描述
相关说明
1、TMOD没有特殊位定义,所以得整体赋值
2、置入初值,由于16位寄存器全部计满有65536,故从0计数直到溢出的时间约为65毫秒(以晶振频率12兆,则晶振周期为1/12微秒,机器周期为1微秒,65536个机器周期为65毫秒)。如果要实现小于65毫秒的定时,需要置入初始值。例如50毫秒,则应该置入的数值为:
高八位THX:(65536-50000)/256(求模)
第八位TLX:(65536-50000)%256(取余)
3、IE是中断允许控制
EX0:外部中断0允许位
ET0:定时计数器0中断允许位
EX1:外部中断1允许位
ET1:定时计数器1中断允许位
ES:串行口
4、TR0或TR1在TCON中,可以直接用位操作

再来一个栗子

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x5d,0x7d,0x07,
0x6f,0x77,0x7c,0x39,
0x5e,0x79,0x71,0x00};
sbit dula=P2^6;
sbit wela=P2^7;
uint x,y,z,num,tt;
void delay(uint);
void main()
{
	TMOD=0x01;//设置定时器0位工作方式
	TH0=(65536-50000)/256;// 高八位
	TL0=(65536-50000)%256;// 低八位
	EA=1;//中断总开关
	ET0=1;//定时计数器0中断允许
	TR0=1;//启动定时计数器0
	wela=1;
	P0=0xc0; 
	wela=0;
	while(1)
	{
		if(tt==20)
		{
			tt=0;
			num++;
			if(num==16)
			{num=0;}
			dula=1;
			P0=table[num];
			dula=0;
			delay(100);
		};
	}
}
void delay(uint z)
{
	for(x=z;x>0;x--)
		for(y=600;y>0;y--);
}	
void exter0() interrupt 1//1表示定时计数器0
{
	TH0=(65536-50000)/256;
	TL0=(65536-20000)%256;
	tt++;
}

程序运行顺序,进入主函数后,启动定时器,开始计数,50毫秒后计满溢出请求中断,进入中断服务程序,此时重新置初值,又进行计数,重复进入中断服务程序,直至tt=20(即经过1s),进行if函数,tt被置零,数码管显示一个数字,重复此过程,实际上就是每隔1秒显示一下数字,用定时器相对于用程序来延时更加精确。注意这里主程序运行时,定时计数也是在运行的,只不过这里主程序中只有当tt满足条件是才有操作。
if函数中还使用了delay延时会造成一些影响,具体还要实操检验一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值