51单片机快速入门之中断的应用
基本函数:
void T0(void) interrupt 1 using 1
{
这里放入中断后需要做的操作
}
void T0(void):
这是一个函数声明,表明函数 T0 不接受任何参数,并且不返回任何值。
interrupt 1:
这是关键字和参数,用于指定这个函数是一个中断服务例程,其中 1 表示中断号。不同的中断号对应不同的中断源.
using 1:
这是另一个关键字和参数,用于指定该中断服务例程使用的工作寄存器组。
在一些微控制器中,允许程序员在中断服务例程中使用不同的工作寄存器组,以避免与主程序中的寄存器冲突。这里的 1 表示使用第1个工作寄存器组。
中断号解释: interrupt
- 外部中断0 (INT0) 中断号0
- 定时器/计数器0 (T0) 中断号1
- 外部中断1 (INT1) 中断号2
- 定时器/计数器1 (T1) 中断号3
- 串行口中断 (串行I/O) 中断号4
使用中断前必要的设置:
串行通信控制寄存器 SCON 简称:串口控制 图片来源于网络
多机通信控制位 (SM2)
SM2 位主要用于多机通信模式(方式2和方式3)。它的功能如下:
方式0:SM2 必须为0。
方式1:SM2 不使用。
方式2和方式3:
如果 SM2 为0,无论接收到的第9位数据(RB8)是什么,
都会将前8位数据送入接收缓冲区 SBUF 并产生中断请求。
如果 SM2 为1,只有当接收到的第9位数据(RB8)为1时,
才会将前8位数据送入接收缓冲区 SBUF 并产生中断请求;否则,丢弃前8位数据。
REN:是串行接收允许位
1时:允许串行接收
0时:禁止串行接收
- REN,允许串行接收位。由软件置REN=1,则启动串行口接收数据;若软件置REN=0,则禁止接收。
快速理解参考:
SM0 SM1 串行通信 模式选择 ,参考前面文章中的传送门
关于 通信模式 设置 的资料 传送门
TI = 1; 表示数据 发送成功 一帧数据 触发中断处理 之后需要手动 =0
RI =1; 表示数据 接收成功 一帧数据 触发中断处理 之后需要手动 =0
复习拓展:
一帧数据的组成
- 起始位(Start Bit) :
- 通常是一个低电平(0),用于标记数据传输的开始。
- 起始位的宽度通常是一个比特时间。
- 数据位(Data Bits) :
- 通常包含8位数据,但也可能是5位、6位、7位或9位。
- 数据位是实际要传输的有效数据。
- 校验位(Parity Bit) (可选):
- 用于检测传输过程中是否发生错误。
- 校验位可以是奇校验或偶校验。
- 奇校验:数据位中1的个数加上校验位后为奇数。
- 偶校验:数据位中1的个数加上校验位后为偶数。
- 停止位(Stop Bit) :
- 通常是一个高电平(1),用于标记数据传输的结束。
- 停止位的宽度可以是一个或两个比特时间。
51单片机快速入门之串口中断的应用
举例说明:通过 串口控制1602 显示文字
1602驱动代码(省略),不会写的参考 之前的文章.
串口通信原理:
- 接收:
RXD串口信息过来,当接收到起始信号,SCON寄存器将打开接收,允许接收,通过T1 计数器/定时器 来产生移位脉冲 由低位到高位 传入移位寄存器 ,再 传输到SBUF(数据缓冲器) 中 中断后可取出其中内容
串口初始化:
SCON = 0x50;
:设置串口工作方式 1(8 位数据,1 位停止位)。PCON = 0x00;
:不使用倍速模式。配置T1 计数器/定时器
定时器初始化:
TMOD = 0x20;
:设置定时器 1 为模式 2(8 位自动重装)。TH1 = 0xA0;
设置初值,计算公式为256 - (晶振频率(
晶振频率需要转换成 Hz(赫兹)1 MHz 等于 (10^6) Hz) / 12 / 波特率)
。对于 11.0592 MHz 的晶振和 9600 bps 的波特率,初值为0xFD
。1 MHz 等于 (10^6) Hz 11.0592x10^6 =11059200 11059200/12/9600=96 256-96=160 1010 0000 A0TL1 = 0xA0;
TR1 = 1;
:启动定时器 1。
- 发送:
只需要把数据写入SBUF中即可发送
串口中断代码:
#include <STC89C5xRC.H>
#include <intrins.h>
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef bit BOOL ;
sbit rs = P3^3;
sbit rw = P3^4;
sbit ep = P3^5;
BYTE *rr= "WELCOME!1602";
BYTE *rt= "2024/11/24";
void delay(BYTE ms); //延时
void lcd_wdat(BYTE dat);//因为不能在声明前使用,这里声明一下函数1602 输出
void lcd_pos(BYTE pos);
void lcd_wcmd(BYTE cmd);
void Uart1_Init(void) //9600bps@18.432MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF6; //设置定时初始值
TH1 = 0xF6; //设置定时重载值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
}
void delay(BYTE ms)
{
while(ms--);
}
void lcd_wcmd(BYTE cmd)
{
rs = 0;
rw = 0;
ep = 1;
P0 = cmd;
delay(500);
ep = 0;
}
void lcd_wdat(BYTE dat)
{
rs = 1;
rw = 0;
ep = 1;
P0 = dat;
delay(500);
ep = 0;
}
lcd_init()
{
lcd_wcmd(0x3c);
delay(50);
lcd_wcmd(0x0f);
delay(50);
lcd_wcmd(0x01);
delay(50);
}
int main(void)
{
unsigned char dtt=33;
P10=0;
lcd_init();
lcd_wcmd(0x01);
delay(50);
lcd_wcmd(0x80);
while(*rr) {
lcd_wdat(*rr);
rr++;
}
lcd_wcmd(0xc0);
while(*rt) {
lcd_wdat(*rt);
rt++;
}
Uart1_Init();
SBUF=dtt;
while(TI==0);
TI=0;
}