IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 51单片机-串口通信(串口向电脑发送信息&电脑通过串口控制LED) -> 正文阅读

[嵌入式]51单片机-串口通信(串口向电脑发送信息&电脑通过串口控制LED)


前言

对于51单片机的串口通信学习进行一个总结,把自己的经验分享给大家,在学习过程中遇到了很多困难和不理解的地方,通过多次实践,对串口通信有了一个大概的了解,希望对大家能够有帮助。


一、串行通信口的功能以及串行通信口的结构及原理

1.1 串行通信口的功能

首先来了解什么是数据通信?

数据通信就是指单片机与单片机之间或者单片机和其他设备之间的信息交换

而数据通信又分为串行通信并行通信

  • 并行通信:数据的各位同时进行发送或接收的通信方式。优点是速率高。缺点是需要的传输线多,成本高,只适合近距离的数据通信。

  • 串行通信:一位一位的按顺序的进行发送或接收的通信方式。优点是需要的传输线少,成本低。缺点是传输的速率慢,适合远距离的数据通信。

从上述来看,串行口的功能,就是通过串行口连接的数据传输线大大减少,可以进行远距离的数据通信。
在这里插入图片描述

1.2 51单片机串口的结构

串口的结构如下图所示,
通过定时器T1计时,由T1产生溢出率,作为波特率发生器。

  • 两个数据缓冲器,SBUF。分别是发送数据的发送寄存器,读取数据的接收寄存器。
    串口写入时,写入的是发送寄存器,即数据向发送寄存器SBUF写入。
    向串口读时,读出的是接收寄存器,即数据由接收寄存器SBUF读出。

  • 定时器1产生波特率, 串口一般使用定时器1,模式2,八位自动重装模式,来产生溢出率,从而产生波特率。而且在配置定时器相关的寄存器时不用配置定时器中断,只是使用定时器1来产生波特率的功能。

  • 移位寄存器,在接受控制器的控制下,将输入的数据逐位移入接收SBUF。

  • 串行控制寄存器SCON,SCON的功能是控制串行通信口的工作方式以及工作的状态。

![在这里插入图片描述](https://img-blog.csdnimg.cn/e5c05783ac394db9bd900f423d9bc550.pn


二、串行通信口的控制寄存器

2.1 串行控制寄存器SCON

SCON寄存器用来控制串行通信的工作方式及反映串行口的工作状态。SCON的地址是98H,可位寻址。如下图所示。
在这里插入图片描述
通过配置SCON寄存器来对串行通信的工作模式进行控制。
说说几个常用的位

  • SM1和SM2,组合确定串行口的模式,不同的模式下波特率不同,功能也不同,下面会详细介绍不同模式下的波特率该如何计算
  • REN,允许/禁止串行接收控制位。 由软件置位REN,即REN=1为允许串行接收状态,可启动串行口接收数据。
  • TI,发送中断请求标志位。主机通过串行口发送数据发送完成后,TI会置1,向串口申请中断,如果TI为1 就表示SUBF的数据已经发送完成了,要手动将TI位清零。(即SBUF=Data)
  • RI,接收中断请求标志位。从机接收到主机通过串行口接收到的数据后,RI会置1,即会串口申请中断,如果RI为1 就表示数据已经通过SBUF读取完成了,要手动将RI位清零。(即Data=SBUF)

2.2 电源控制寄存器PCON

在这里插入图片描述
这里我们只需要知道SMOD是啥就可以了。

  • SMOD位,就是波特率是否加倍,若SMOD=0,波特率不变。SMOD=1,波特率加倍SMOD默认为0。

2.3 配置寄存器

配置SCON寄存器

在这里插入图片描述
看,上图就是SCON寄存器的位图,下面以串口通信的模式1来举例。
模式1,那么
SM1和SM2就要配置成 0 1
REN,可置1,置1就是允许串行通信口接收数据,当不需要接收数据的时候可以置0。
后面的几位直接不看,一般用不到
TI和RI,也默认为0,当接收数据或发送数据的时候,会由硬件置1,继而触发中断,这时要由软件置1。
这样SCON寄存器就配置好了。
这样我的SCON配置如下

SCON=0x40;   //方式1   REN置1/0 允许/禁止数据接收的控制位

配置PCON寄存器

在这里插入图片描述

我们只需要明确一点,我的波特率是否需要加倍,如果加倍,那么PCON的第一位SMOD就要置1。
这样我的PCON就配置好了,如加倍

PCON |= 0x80;  //波特率加倍

配置中断

注意,定时器1,不用开中断,即ET1=0,因为定时器的功能只是产生波特率。
下图为串口和中断的连接图,较为直观,也比较好理解
在这里插入图片描述

下方代码块为中断服务子函数模块

// 串口中断函数模板
void Uart_Routine() interrupt 4
{
	if(RI==1)  
	{
		RI=0;
	}
	if(TI==1)
	{
	TI=0;
	}
}

2.4 实验

单片机向pc发送数据

代码如下:
UART.c
因为是单片机向PC发送数据,不用接收数据,所以这里的SCON寄存器的REN位未置1,而模式1,SM1和SM2就要配置成 0 1。

#include <REGX52.H>

/**
  * @brief 串口初始化
  * @param  无
  * @retval 无
  */
void Uart_Init()	//4800bps@11.0592MHz
{
	SCON=0x40;   //方式1   REN置1 允许/禁止数据接收的控制位
	PCON |= 0x80;  //波特率加倍  
	
	//配置定时器1 模式二 8位自动重装
	TMOD&=0x0F;
	TMOD|=0x20;  //模式二
	TL1 = 0xF4;		//设定定时初值
	TH1 = 0xF4;		//设定定时器重装值
	
	ET1=0;   //不用开启中断 定时器在这里的作用是产生波特率
	TR1=1;   //启动定时器1
	
}

/**
  * @brief 串口发送一位字节数据
  * @param  Byte 要发送的字节数据
  * @retval 无
  */
void Uart_SendByte(unsigned char Byte)
{
	SBUF=Byte;   //向缓存器中写入内容
	while(TI==0);   //发送中断标志位 如果检测到了寄存器的TI位 如果为0 就表示数据未发送完成  反复执行本条语句检测TI位
	//如果TI为1 就表示SUBF的数据已经发送完成了  马上执行下条语句将TI位清零
	TI=0;
}

main.c
这里,调用UART模块里的串口发送一位字节数据的函数,向PC发送递增的数据。

#include <REGX52.H>
#include "Delay.h"
#include "Uart.h"

unsigned char Sec;
void main()
{
	Uart_Init();
	
	while(1)
	{
		Sec++;
		Uart_SendByte(Sec);
		Delay(50);
	}
}

PC向单片机发送数据,单片机接收数据

UART.c
这里,因为单片机要接收自己发送到PC里的数据,简而言之就是MCU->PC,然后PC->MCU

#include <REGX52.H>

/**
  * @brief 串口初始化
  * @param  无
  * @retval 无
  */
void Uart_Init()	//4800bps@11.0592MHz
{
	SCON=0x50;   //方式1   REN置1 允许/禁止数据接收的控制位  允许接收 REN置1
	PCON |= 0x80;  //波特率加倍  
	
	//配置定时器1 模式二 8位自动重装
	TMOD&=0x0F;
	TMOD|=0x20;  //模式二
	TL1 = 0xF4;		//设定定时初值
	TH1 = 0xF4;		//设定定时器重装值
	
	ET1=0;   //不用开启中断 定时器在这里的作用是产生波特率
	TR1=1;   //启动定时器1
	
	//接收数据完成后就触发中断
	ES=1;
	EA=1;
}

/**
  * @brief 串口发送一位字节数据
  * @param  Byte 要发送的字节数据
  * @retval 无
  */
void Uart_SendByte(unsigned char Byte)
{
	SBUF=Byte;   //向缓存器中写入内容
	while(TI==0);   //发送中断标志位 如果检测到了寄存器的TI位 如果为0 就表示数据未发送完成  反复执行本条语句检测TI位
	//如果TI为1 就表示SUBF的数据已经发送完成了  马上执行下条语句将TI位清零
	TI=0;
}

/* 串口中断函数模板
void Uart_Routine() interrupt 4
{
	if(RI==1)   //如果接收到数据 接收完成后 产生中断 如果是接收中断  
		//发送数据也会产生中断
	{
		P2=SBUF;  //从SUBF缓存器中读取数据
		Uart_SendByte(SBUF);
		RI=0;
	}
}
*/

main.c
如果接收到数据 接收完成后 产生中断 ,单片机把SBUF缓存里的数据读取出来了,因为检测到了接收中断,即RI=1,在主函数写了串口中断函数,检测是否接收中断,把接收到的数据,以LED灯的形式显示出来。

#include <REGX52.H>
#include "Delay.h"
#include "Uart.h"

unsigned char Sec;
void main()
{
	Uart_Init();
	
	while(1)
	{
		
	}
}
void Uart_Routine() interrupt 4
{
	if(RI==1)   //如果接收到数据 接收完成后 产生中断 如果是接收中断  
		//发送数据也会产生中断
	{
		P2=SBUF;  //从SUBF缓存器中读取数据
		Uart_SendByte(SBUF);
		RI=0;
	}
}


2.5 实验现象

单片机向PC发送数据

可以看到单片机向PC发送递增的数据,直到关闭串口,数据停止发送。
在这里插入图片描述

PC向单片机发送数据,单片机接收数据

可以看到在PC上发送0xF0,LED灯以相应的状态亮起,串口数据发送成功。
在这里插入图片描述
在这里插入图片描述

三、总结

首先要保证双机通信时,配置的波特率相同

然后串口通信主要要明确S**CON中的RN,SM0和SM1模式位的选择,以及RI和TI和理解。

在配置定时器1的时候,一定不要开定时器中断,即ET1=0,因为定时器的功能只是产生波特率。

然后定时器1产生的波特率该如何计算,计时器的初始值应该如何计算,将会在下一篇文章中详细说明。

希望对你有帮助,行文仓促,还请谅解,欢迎指错。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:14:20  更:2022-10-31 12:18:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:25:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码