第五篇 串口(基础篇)

目录

 一、串口相关概念

1.什么是串口

2.串行接口分类(按电器标准及协议)

3.单片机常见的串口

📓标准UART接口

📓I2C总线接口、SPI接口、USB接口等。

 二、串口相关的寄存器

1.串行控制寄存器SCON

(1)SM0/SM1

✒️波特率相关计算

(2)REN

(3)TI和RI

(4)其他位:SM2、TB8、RB8

2.波特率选择特殊功能寄存器PCON

(1) SMOD

(2)其他位(暂略)

3.串口数据缓冲寄存器SBUF

三、串口使用总结

1.配置串口工作模式

2.配置定时器1(实质上,timer1这里作波特率发生器)

3.配置串口接收数据位REN

4.配置串口中断

 四、串口编程

1.每隔一秒发送一个字符'a'(demo1.c)

 📓字符'a'是如何从单片机串口传输到PC上的?

2.每隔一秒发送字符串"C is YYDS"(demo2.c)

(1)串口中断触发行为

(2)串口中断寄存器

(3)串口中断优先级 

(4)使用注意事项

📓使用中断修改后的代码

3. 全双工收发数据(demo3.c)


 一、串口相关概念

1.什么是串口

        串行接口(Serial Interface)简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。(来源于百度)

        ✒️全双工(双向通信)

        ✒️数据一位一位传输

        ✒️设备间的通讯方式

2.串行接口分类(按电器标准及协议)

        串行接口按电气标准及协议来分包括RS-232-C、RS-422、RS485等。RS-232-C、RS-422与RS-485标准只对接口的电气特性做出规定,不涉及接插件、电缆或协议。USB是近年来开发的新接口标准,主要用于高速数据传输领域。(来源于百度)        

3.单片机常见的串口

📓标准UART接口

        UART(Universal Asynchronous Receiver/Transmitter),异步串行接口(常说的串口)

📓I2C总线接口、SPI接口、USB接口等。


 二、串口相关的寄存器

        STC89C51RC/RD+系列单片机的串行口设有两个控制寄存器:串行控制寄存器SCON波特率选择特殊功能寄存器PCON。(芯片手册)

1.串行控制寄存器SCON

(1)SM0/SM1

        SCON的bit7bit6组合共同确认串口工作模式的控制位。

(同前面定时器的使用类似,使用串口前需要配置工作模式,根据芯片手册,串口工作模式的功能波特率有关,而波特率的计算又和定时器1的溢出率SMOD值相关。详见以下芯片手册所述)

✒️波特率相关计算

以9600的波特率为例,选择方式1的模式。如何确定TH1的初值?(SMOD取0波特率不加倍)

 

(2)REN

SCON的bit4,允许或禁止串口接收控制位(置1允许,置0禁止

(3)TI和RI

TISCON的bit1发送数据中断位置1请求中断(硬件),响应中断后软件置0
RISCON的bit0接收数据中断位置1请求中断(硬件),响应中断后软件置0

TI和RI均必须软件清0,否则将出现一次请求多次响应的情况,且中断处理函数中需判断是TI还是RI

(4)其他位:SM2、TB8、RB8

2.波特率选择特殊功能寄存器PCON

(1) SMOD

        PCON的bit7,波特率选择位(置1串行通信方式1、2、3波特率加倍;置0各工作方式波特率不加倍 <这里芯片手册所述有误>

(2)其他位(暂略)

3.串口数据缓冲寄存器SBUF

(见代码理解即可)


三、串口使用总结

1.配置串口工作模式

        1)SM0/EF:SCON的bit6置1——以工作模式1为例,也推荐使用模式1)

        2)SM1:SCON的bit7置0——以工作模式1为例,也推荐使用模式1)

2.配置定时器1(实质上,timer1这里作波特率发生器)

        1)8位自动重载模式(TMOD的bit4置0,bit5置1

        2)允许位TR1

        3)TH1和TL1(根据波特率计算得到)

3.配置串口接收数据位REN

        1)SCON的bit4置1允许接收数据

4.配置串口中断

        1)发生数据中断位TI(硬件置1,需软件置0

        2)接收数据中断位RI(硬件置1,需软件置0

注意在串口中断函数中判断是发送还是接收的中断


 四、串口编程

1.每隔一秒发送一个字符'a'(demo1.c)

#include "reg52.h"
#include <intrins.h>

void uartInit(){
	SCON |= 0x01<<6;			//串口工作模式(8位波特率可变--方式1)
	SCON &= ~(0x01<<7);		
	//PCON |= 0x01<<7;		//波特率选择位PCON的bit7(置1加倍,置0不加倍)
	TMOD |= 0x01<<5;			//定时器1(8位自动重载模式)
	TMOD &= ~(0x01<<4);
	TR1 = 1;							//开启定时器(波特率发生器)
	TH1 = 0xFD;						//计数器初值(通过波特率计算得到)
	TL1 = 0xFD;
}

void Delay1000ms()		//软件延时1s{
	unsigned char i, j, k;
	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do{
		do{
			while (--k);
		} while (--j);
	} while (--i);
}

void main(void){
	uartInit();
	while(1){
		SBUF = 'a';
		Delay1000ms();
	}
}

 📓字符'a'是如何从单片机串口传输到PC上的?

        串口工作模式1,一帧数据包括起始位(0)、数据位、停止位(1);字符a的ASSII码是97,转二进制0101 0001,那么这8位就是数据位。加上起始位和停止位,字符a的一帧数据就是

0 01010001 1。一次从低位到高位发送和接收。

2.每隔一秒发送字符串"C is YYDS"(demo2.c)

 🔖先看以下这段实现发送字符串的代码

🔖使用以上代码发送字符串时,会发现sendString( )调用sendChar( )时候,由于中间执行的时间差,会导致字符串“Hello World”不能正常发送到PC。虽然在sendChar( )中加入10ms的延时会较好地显示,但也有明显的不流畅。此处,利用发送数据中断位TI来处理更好。

🔖所以,我们有必要先了解串口中断再完成demo2的代码

★再识中断—串口中断

        这里已经是第三次学习到中断系统,同前面(定时器中断、外部中断)一样,从中断触发行为、中断寄存器、中断优先级来了解使用串口中断。

(1)串口中断触发行为

(芯片手册图)

触发行为:数据发送或接收完成

 

(2)串口中断寄存器

 🔖ES(IEbit4):串口中断允许位(1允许;0禁止

(3)串口中断优先级 

(4)使用注意事项

        ✒️在SCON寄存器中,有一个发送数据中断位(TI(SCON的bit1)),请求中断时它由硬件置1,响应中断后需要我们手动置0。还有一个接收数据中断位RI,注意将REN(SCON的bit4)置1才可接收数据。

📓使用中断修改后的代码

#include "reg52.h"
#include <intrins.h>
void uartInit(void){
	SCON &= ~(0x01<<7);
	SCON |= 0x01<<6;
	TMOD |= 0x01<<5;
	TMOD &= ~(0x01<<4);
	TR1 = 1;
	TH1 = 0xFD;
	TL1 = 0xFD;
	EA = 1;
	ES = 1;
}
void Delay1000ms(){
	unsigned char i, j, k;
	i = 8;
	j = 1;
	k = 243;
	do{
		do{
			while (--k);
		} while (--j);
	} while (--i);
}
void sendChar(char datas){
	SBUF = datas;
	while(!TI);
	TI = 0;
}
void sendString(char *datas){
	while(*datas != '\0'){
		sendChar(*datas);
		datas++;
	}
}
void main(void){
	uartInit();
	while(1){
		sendString("Hello World\t\n");
		Delay1000ms();
	}
}

3. 全双工收发数据(demo3.c

每隔一秒发送字符串"C is YYDS";当接收到指令o,点亮led;指令c,熄灭led。

#include "reg52.h"
#include <intrins.h>

sbit led1 = P3^7;
sfr AUXR = 0x8E;
char cmd;
void uartInit(void){
	AUXR = 0x01;
	SCON &= ~(0x01<<7);
	SCON |= 0x01<<6;
	TMOD &= ~(0x01<<4);
	TMOD |= 0x01<<5;
	TR1 = 1;
	TH1 = 0xFD;
	TL1 = 0xFD;
	EA = 1;
	ES = 1;
	REN = 1;
}

void Delay1500ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	_nop_();
	i = 11;
	j = 130;
	k = 111;
	do{
		do{
			while (--k);
		} while (--j);
	} while (--i);
}


void sendString(char *datas){
	while(*datas != '\0'){
		SBUF = *datas;
		while(!TI);
		TI = 0;
		datas++;
	}
}
void main(void){
	uartInit();
	led1 = 1;
	while(1){
		Delay1500ms();
		sendString("C is YYDS\t\n");
	}
}

void interruptHandle() interrupt 4{
	if(RI == 1){
		RI = 0;
		cmd = SBUF;
		if(cmd == 'o'){
			led1 = 0;
		}
		if(cmd == 'c'){
			led1 = 1;
		}
	}
}

说明:由于笔者水平有限,文中不可避免有所错漏,敬请各读者斧正 

  

  • 7
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AF_INET6

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值