【51单片机】中断、定时器、串口配置代码讲解

一、外部中断

中断初始化(3步)

1、打开中断;
2、打开外部中断开关
3、设置中断的触发方式

直接在主函数中搞吧 简单粗暴一点

main()
{
	LED=0xff;       //P1口初始值 关闭led灯
	EA=1;          //全局中断开 打开总中断
	EX0=1;         //外部中断0开
	IT0=0;         //设置外部中断的触发方式:电平触发
	while(1)
	{
		//在此添加其他程序,中断程序可以跟此处的程序同步执行
	}
}

外部中断程序

void Key_INT(void) interrupt 0 using 1
{
	LED =~LED; //触发中断后,反转当前LED的状态

}

查看手册

在这里插入图片描述
发现外部中断0的触发引脚(开关)是 P32引脚,所以把P_32接地(图中显示 低电平有效嘛,给0不就对了),即可触发外部中断0


二、定时器中断

定时器中断初始化(5步)

1、设置定时器模式
2、设置定时器初值
3、打开中断;
4、打开定时器中断开关;
5、打开定时器开关

定时器中断初始化配置

void Init_Timer0(void)		  //定时器初始化子程序
{
	TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
	TH0=0x0D8;	      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
	TL0=0x0F0;
	EA=1;            //总中断打开
	ET0=1;           //定时器中断打开
	TR0=1;           //定时器开关打开
}

定时器中断程序

interrupt 中断号一定要写 程序是靠识别这个进入的,using写不写无所谓。

中断号可以在开发手册或百度上找到
在这里插入图片描述

void Timer0(void) interrupt 1 using 0
{
	TH0=0x0D8;  //重新赋值,方式1是16位计数器 最大装载值为65536
	TL0=0x0F0;  //每次计时10ms
	cnt++;
	/*用户代码部分*/
	if(cnt == 100)//计时 满1s 执行
	{
		LED=~LED;        //指示灯反相,可以看到闪烁
		cnt = 0;
	}
}

主函数调用定时器初始化函数

main()
{
	Init_Timer0();
	while(1);
}

要先在main函数里先调用定时器0初始化配置,才能正常使用它。
1.待计时达到我们设置的数值时,程序会自动跳入定时器中断程序
在这里插入图片描述
2.进入以后 会重新给TH、TL重新赋值,以便下一次的计数。(程序会一直以设置的时长为周期反复进入中断)这便是定时器中断
在这里插入图片描述

三、串口

涉及寄存器

1、SCON(Serial Control 串口控制)98H

用于设置串行口的工作方式、监视串行口的工作状态、控制发送与接收的状态等。
它是一个既可以字节寻址又可以位寻址8位特殊功能寄存器
其格式如下图

在这里插入图片描述

其中SM2TB8RB8这几位基本没有用到,不用管。
只要:
——SM0SM1RENTIRI 就行啦!
——SerialMode0、ReceiveEnable、TransmitInterrupt、ReceiveInterrupt(展开了记好理解)!
我的理解是:
1、SM0 SM1的位置是和我们的逻辑相反的(SM0=0 SM1=1 是方式一 );
2、方式0 不算串口,它是 移位寄存器 用来扩展IO口用的;
3、并且用的比较多的是方式一 ,我们只要收发数据嘛,一就够了。其它方式的了解一下就行啦;
3、发送完一帧数据后,要用软件把TI清零,才能再发送下一帧;
4、接收完一帧数据后,要用软件把RI清零,才能再接收下一帧;

2、PCON

就一位用到了SMOD,用来设置波特率 加不加倍的。
在这里插入图片描述

3、IE -InterruptEnable 中断允许控制寄存器(A8H)

作用:CPU对中断系统所有中断以及某个中断源的开放和屏蔽是由中断 允许寄存器E控制的。
在这里插入图片描述
EnableAll Interrupt、EnableSeria lnterrupt、EnableTimer Interrupt、EnableExternal Interrupt
使能所有中断、使能串口中断、使能定时\计数器中断、使能外部中断

串口初始化配置(5步)

1、用定时器设置波特率、工作方式
__a.设置T1的工作方式;【TMOD寄存器】
__b.设置T1的初值,装载 TH1、TL1;(波特率)
__c.启动T1;【TCON寄存器中的TR1
2、打开串口接收位;【SCON寄存器REN
3、设置串口工作方式SM0 SM1;【SCON寄存器】

注意SM0 和 SM1的位置 与 我们正常的逻辑相反

如需串行口在中断方式工作时,要进行中断 设置编程IE寄存器
打开总开关EA;打开串口使能为ES

void main()
{
	TMOD=0x20;		   //用定时器--方式2   
	TH1=0xfd;		   //设置串口波特率 9600 
	TL1=0xfd;
	TR1=1;			  //打开定时器
	REN=1;            //串口 接收使能
	SM0=0;			  //SM0  SM1 = 0 1 --串口工作方式1
	SM1=1;
	EA=1;             //开启总中断
	ES=1;			  //串口使能
	while(1)
	{
		if(num==1)    //判断是否有串口数据的传送
		{
			ES=0;     //禁止串口中断
			num=0;    //清空串口数据的传送标志位
			SBUF=a;	 //发送数据a到SBUF,即将单片机的数据发送到计算机
			while(!TI);	//等待串口发送完成
			TI=0; 	//串口发送完成标志位清零
			ES=1;		//允许 串口进行下一次的中断
		}
	}	
}

串口在接收到一帧有效数据后由于硬件置位RI=1。然后会进入到下面的串口中断中。
进入 串口接收中断
1. 先把标志位RI清零,方便接收下一条数据帧;
2. 把接收到的数据从SBUF中取出,赋给a,再把num=1
___explain: 51的SBUF串行口数据缓冲寄存器,具有输入和输出功能(名称相同,但是物理上是独立的,只是占用同一个地址);
—换句话说,SBUF既是接收缓冲器又是发送缓冲器,同一时间只能为一种,要么接收,要么发送。a=SBUF是把接收缓冲器中的数据赋给aSBUF=a是把a中的数据赋给发送缓冲器
!!一句话概括:通过读写缓冲器SBUF实现数据收发功能!!!
3. 回到主函数,此时的串口数据传送标志位num=1 所以 走if分支,此时把串口接收关闭了,再把串口数据的传送标志位num=0清空。在SBUF=a,这就是把单片机接收到的数据给发出来在电脑屏幕上显示给你看,然后进入while(!IT),等待一帧数据发送完成(即发完一帧数据后TI会被(硬件)置1)。退出while后,把TI给清零,方便下一次数据的发送。再ES=1打开串口使能位。等待下一次串口收发。

void ser() interrupt 4
{
	RI=0;			//RI由硬件置为1 表示收到,进入中断以后 就用软件清零 
	a=SBUF;			//把接收到的数据赋给`接收缓存区`
	num=1;			//再把 num置为1
}

什么是波特率(比特率)?

在这里插入图片描述


每天进步一点点 笔记仅供自学,用来回看复习,不一定适合你,如有错误请指出。

  • 16
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
51计算器程序#include #include #define uchar unsigned char #define uint unsigned int sbit lcden=P3^4; sbit lcdrw=P3^6; sbit lcdrs=P3^5; uchar num,temp,jia=0,cheng=0,chu=0,jian=0,qing=0; uint key,key1,shu; uchar fuhao,flag1,flag=0; uchar table[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,}; void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=114;y>0;y--); } bit lcd_bz() { bit result; lcdrs = 0; lcdrw= 1; lcden = 1; _nop_(); _nop_(); _nop_(); _nop_(); result=(bit)(P0&0x80;); lcden=0; return result; } void write_com(uchar com) { while(lcd_bz()); lcdrs=0; lcden=0; lcdrw=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } void write_date(uchar date) { while(lcd_bz()); lcdrs=1; lcden=0; lcdrw=0; P0=date; delay(5); lcden=1; delay(5); lcden=0; } void lcd_init() { lcden=0; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); } void keyscan() { P3=0xfe; temp=P3; temp=temp&0xf0; while(temp!=0xf0) { delay(5); temp=P3; temp=temp&0xf0; while(temp!=0xf0) { temp=P3; switch(temp) { case 0xee:key=1;num=0;break; case 0xde:key=2;num=0;break; case 0xbe:key=3;num=0;break; case 0x7e:num=1;break; //¼ÓºÅ } while(temp!=0xf0) { temp=P3; temp=temp&0xf0; } } } P3=0xfd; temp=P3; temp=temp&0xf0; while(temp!=0xf0) { delay(5); temp=P3; temp=temp&0xf0; while(temp!=0xf0) { temp=P3; switch(temp) { case 0xed:key=4;num=0;break; case 0xdd:key=5;num=0;break; case 0xbd:key=6;num=0;break; case 0x7d:num=2;break; //¼õºÅ } while( temp!=0xf0) { temp=P3; temp=temp&0xf0; } } } P3=0xfb; temp=P3; temp=temp&0xf0; while(temp!=0xf0) { delay(5); temp=P3; temp=temp&0xf0; while(temp!=0xf0) { temp=P3; switch(temp) { case 0xeb:key=7;num=0;break; case 0xdb:key=8;num=0;break; case 0xbb:key=9;num=0;break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KevinGuo457

哈哈哈资助我买两包辣条叭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值