基于PRECHIN普中51-实验板学习—串口中断相关学习(9)

概要

学习51单片机中的串口中断

技术名词解释

  • 串行通信:在不同的时间发送不同的高低电平,形成一串数字。一位一位传输。优点是节省串口资源,缺点发送时间长。

  • 并行通信:一次传输多位。优点发送时间短,缺点占用串口资源。

  • 异步通信:主机和从机不使用同一个时钟。每一帧可以在中间加一个校验位(比如记录该帧存放了几个1,当接收设备接收到该帧时,发现校验位有问题,可以退回重发)。形成帧的每个数字可以称为码元

  • 同步通信:主机和从机使用同一个时钟。

  • 单工通信: 只能单向传输数据。类似于上课铃声。
  • 半双工通信:可以双向通信,但不可以同时通信。类似于对讲机。
  • 全双工通信:可以双向同时通信。类似于手机电话。
  • 常见的串行通信应用

配置寄存器

串行口结构

简单理解:A代表CPU,移位寄存器中存放接收到的数据,最高八位。这里给串口配置了特殊功能寄存器SBUF(数据缓冲),它也是一个八位的特殊功能计算器。当移位寄存器存了8位数据后,就由SBUF接收到该八位数据,CPU再从SBUF中读取。同理发送数据,由SBUF从CPU中读取发送。(防止数据丢失的一种方法。当SBUF读取到一个字节的数据后,把允许串口中断ES关掉,就接收不到数据,等将数据读走后,再打开串口中断,这样就保证数据不会丢失)

配置串行口寄存器

        例如:SCON = 0x50;TCON = 0x80;配置方式1,波特率加倍

波特率计算方式

串行口通信初始化

基础练习

通过串口助手向单片机发送1,2,3,4字符,来实现不同灯光的亮灭

#include "reg52.h"

sbit led1 = P0^0;
sbit led2 = P0^1;
sbit led3 = P0^2;
sbit led4 = P0^3;

typedef unsigned int u16;
typedef unsigned char u8;

u8 receivedata;
u8 flag;

void Uart_init()
{
		SCON = 0x50;	//设置串口寄存器模式
		TMOD = 0x20;	//设置定时器工作模式为方式2 T1的TMOD = 0x20自动重装模式
		PCON = 0x80;	//设置波特率加倍
		TH1 = 0xF3;		//设置初值 根据波特率计算公式 (2^MODE/32)*晶振频率/[12*(256-TH1)] 需要赋初值
		TL1 = 0xF3;
		ES = 1;				//打开串口中断
		EA = 1;				//打开总中断
		TR1 = 1;			//打开计数器
}


void main()
{
	Uart_init();
	led1 = 0;
	led2 = 0;
	led3 = 0;
	led4 = 0;
	while(1)
	{
			switch(receivedata)
			{
				case '1':led1 = ~led1;break;
				case '2':led2 = ~led2;break;
				case '3':led3 = ~led3;break;
				case '4':led4 = ~led4;break;
				default:break;
			}

	}	
}


void Usart() interrupt 4
{
		RI = 0;			//接收到了数据,RI置1,要手动清零
		receivedata = SBUF;			//接收发送的数据
		flag = receivedata;			//将接受到的数据重新发送过去
		SBUF = flag;
		while(!TI);							//等待数据发送完成
		TI = 0;
}

注意事项

在串口中断发生时,如果接收到了数据,RI会被自动置1,这时候我们读取数据的同时要自己手动置0;同理在发送数据的时候,TI会被自动置1,我们发送数据的同时也要手动置0;

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是普中51-实验制作的简易作业代码: ```c #include <reg52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int sbit beep = P1^5; // 蜂鸣器 sbit DIO = P2^0; // 点阵屏数据线 sbit CLK = P2^1; // 点阵屏时钟线 sbit SDA = P2^2; // 温度传感器数据线 sbit SCL = P2^3; // 温度传感器时钟线 sbit LATCH = P2^4; // 74HC595锁存器控制线 uchar code DIG_CODE[] = { // 共阴数码管显示代码表 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F }; uchar code LED_CODE[] = { // LED灯显示代码表 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F }; uchar code KEY_CODE[] = { // 矩阵键盘按键代码表 0xEE, 0xDE, 0xBE, 0x7E }; uchar code DIS_CODE[] = { // 显示屏显示代码表 0x38, 0x0C, 0x01, 0x06, 0x1F }; uchar code TEXT[] = "Hello, World!"; // 显示屏显示文本 void delay(uint t) // 延时函数 { while (t--); } void writeByte(uchar dat) // 点阵屏写入一个字节 { uchar i; for (i = 0; i < 8; i++) { DIO = dat & 0x80; dat <<= 1; CLK = 0; _nop_(); CLK = 1; } } void writeCmd(uchar cmd) // 点阵屏写入命令 { LATCH = 0; writeByte(0xC0); writeByte(cmd); LATCH = 1; } void writeData(uchar dat) // 点阵屏写入数据 { LATCH = 0; writeByte(0xC1); writeByte(dat); LATCH = 1; } void initDS18B20() // 初始化温度传感器 { SDA = 1; SCL = 1; delay(2); SDA = 0; delay(80); SDA = 1; delay(2); } void writeDS18B20(uchar dat) // 写入温度传感器一个字节 { uchar i; for (i = 0; i < 8; i++) { SDA = dat & 0x01; dat >>= 1; SCL = 0; delay(2); SCL = 1; delay(2); } } uchar readDS18B20() // 读取温度传感器一个字节 { uchar i, dat = 0; for (i = 0; i < 8; i++) { SCL = 0; delay(2); SCL = 1; delay(2); dat >>= 1; if (SDA) dat |= 0x80; } return dat; } void displayDS18B20() // 显示温度传感器温度 { uchar temp[2]; float t; initDS18B20(); writeDS18B20(0xCC); writeDS18B20(0x44); delay(1000); initDS18B20(); writeDS18B20(0xCC); writeDS18B20(0xBE); temp[0] = readDS18B20(); temp[1] = readDS18B20(); t = (temp[1] << 8) | temp[0]; t /= 16; writeCmd(0x80); writeData(DIG_CODE[(int)(t / 10)]); writeData(DIG_CODE[(int)(t % 10)] | 0x80); writeData(0x39); writeData(DIG_CODE[(int)((t - (int)t) * 10)]); } void main() { uchar i, j, k, key, led, dis; TMOD = 0x01; // 定时器0工作在模式1 TH0 = 0xFC; // 定时器0计数初值 TL0 = 0x66; ET0 = 1; // 开启定时器0中断 EA = 1; // 开启总中断 TR0 = 1; // 开始计数 while (1) { key = 0; P2 = 0xFE; if (P0 != 0xFF) { for (i = 0; i < 4; i++) { P2 = 0xFE >> i; if (P0 != 0xFF) { for (j = 0; j < 4; j++) { if (P0 == KEY_CODE[j]) { key = i * 4 + j + 1; break; } } break; } } } if (key > 0) { led = LED_CODE[key - 1]; dis = DIS_CODE[key - 1]; } else { led = 0xFF; dis = 0xFF; } P1 = led; writeCmd(0x40); for (k = 0; k < 8; k++) { writeData(TEXT[k]); } displayDS18B20(); delay(1000); writeCmd(0x80); writeData(dis); delay(500); beep = 1; delay(50); beep = 0; delay(450); } } void timer0() interrupt 1 // 定时器0中断服务函数 { TH0 = 0xFC; TL0 = 0x66; P0 = DIG_CODE[k]; if (++k >= 8) k = 0; } ``` 其中,点阵屏使用74HC595移位寄存器控制,共阴数码管、LED灯、矩阵键盘、显示屏、蜂鸣器都是直接接口控制,温度传感器使用DS18B20芯片,通过单总线协议控制读取温度数据。代码实现了按键控制LED灯、显示屏显示文本和数码管显示温度,每隔1秒钟更新一次温度数据,并且每隔500毫秒闪烁一次显示屏的显示代码,同时蜂鸣器发出滴声。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值