小白向单片机笔记八:串口通信

  • 前言
  • 一、前置知识了解
  • 二、51单片机寄存器
    • 1. 串口控制寄存器SCON
    • 2. 电源控制寄存器PCON
  • 三、工作方式选择
    • 方式0
      • 输出时序图
      • 输入时序图
    • 方式1
      • 输出时序图
      • 输入时序图
    • 方式2、3
      • 输出时序图
      • 输入时序图
  • 四、串口通信代码
    • 时延函数 delay.h
    • 中断初始化函数 interrupt_utils.h
    • 串口初始化及相关功能函数 uart_init.h
    • 矩阵按键扫描函数 scan_button.h
    • 主函数

前言

51单片机串口通信原理及代码,实现单片机与PC的交互

一、前置知识了解

数据传输方式分类:

  1. 串行通信:使用一条数据线,将数据一位一位传输,每个数据占据一个固定的时间长度。特点:传输线少,长时间传输成本低,但传输控制比并行复杂。
  2. 并行通信:将数据字节的各位用多条数据线同时进行传输。特点:控制简单,速度快,但长距离传输时间成本高且接受方接受困难,扛干扰能力差。

数据同步方式分类

  1. 异步通信: 发送与接受设备使用各自的时钟控制数据的发送和接受过程。双方时钟不一定一致,但通信时钟应尽可能保持一致。特点: 不要求双方时钟严格一致,实现简单,设备开销小,但传输效率低。
  2. 同步通信: 要建立发送和接受双方的时钟直接控制,使双方达到完全同步。分为外同步和自同步。特点: 双方时钟应严格一致,控制复杂,开销大,但传输效率高。

数据传输方向分类

  1. 单工通信: 数据传输只能沿一个方向
  2. 半双工通信: 数据可双向传输,但须分时进行
  3. 全双工通信: 数据可以同时双向传输。

通信速率

  1. 比特率: 每秒钟传输二进制代码的位数,单位:位/秒。如:每秒传输240字符,每个字符含10位,则其比特率为:2400bps
  2. 波特率: 当定义若干位为一个码元,以2400bps为例,定义每四位为一码元,则其波特率为2400/4=6002400/4=6002400/4=600

二、51单片机寄存器

1. 串口控制寄存器SCON

7 6 5 4 3 2 1 0
字节地址:98H SM0 SM1 SM2 REN TB8 RB8 TI RI SCON

REN: 允许串行接收位。 REN=1REN=1REN=1启用串口接收数据,反之禁止。

RB8: 在方式2或3中(见下表),为接收数据的第9位,作为奇偶校验位或地址帧/数据帧的标志位。在方式1时,若SM2=0SM2=0SM2=0,则RB8是接收到的停止位。

RI: 接收中断标志位。 在方式0中,接收到第8位数据结束时,在其他方式中,接收到停止位时,硬件置1,发出中断申请,须在中断程序中软件清0,取消此中断。

SM2: 多机通信控制位,主要用于方式2和3(见下表)。 当SM2=1SM2=1SM2=1时,启用多机通信;接收的第九位数据赋值给RB8,当RB8=0RB8=0RB8=0,不激活RI(即RI=0RI=0RI=0),收到的数据丢弃;当RB8=1RB8=1RB8=1,激活RI(即RIRIRI硬件置1),产生中断从SBUF中读取数据。当SM2=0SM2=0SM2=0,不管RB8为0或1,均可读取其中数据。

TB8: 方式0和1中未用到。在方式2和3中,是发送数据的第9位,可以软件定义其作用,作为校验位或标志位。

TI: 发送中断标志位。 在方式0中,发送第8位数据结束时,在其他方式中,发送停止位时,硬件置1,发出中断申请,须在中断程序中软件清0,取消此中断。

SM0和SM1为工作方式选择位

SM0 SM1 方式 说明 波特率
0 0 0 移位寄存器 fosc/12f_{osc}/12fosc​/12
0 1 1 10位异步收发器(8位数据) 可变
1 0 2 11位一步收发器(9位数据) fosc/64f_{osc}/64fosc​/64或fosc/32f_{osc}/32fosc​/32
1 1 3 11位异步收发器(9位数据) 可变

foscf_{osc}fosc​为外部晶振频率

2. 电源控制寄存器PCON

7 6 5 4 3 2 1 0
字节地址:97H SMOD PCON

SMOD: 波特率倍增位。 在串口方式1、2、3(见工作方式选择表)时,波特率和SMOD有关。SMOD=1SMOD=1SMOD=1,波特率提高一倍,复位时置0。

如何理解波特率,及其倍增位,以全双工异步通信为例,如下图所示。

图中结构可以看出为全双工通信,如果为异步通信(即接收端与发送端双方的时钟由各自控制),为了保证设备正常工作,需要尽可能让双方时钟保持一致;如果为同步通信,则发送端除了控制自己的时钟,同时还要控制接收端的时钟,使双方时钟保持一致。

举例说明,当发送端与接收端同步时(即双方波特率比值为1:1),发送端发送一个a,接收端接收一个a。

当发送端与接收端时钟不同步时(例如双方波特率比值为2:1)。发送端发送一个a,接收端接收到两个a。这就是双方时钟不一致(即波特率不同)产生的现象。

无论同步通信还是异步通信都要使双方时钟保持一致,区别只在于同步时钟是由谁控制。至于为什么要进行波特率倍增,大概可能估计是由于硬件限制,考虑到最大波特率也无法进行正常通信的情况。

三、工作方式选择

  1. 接收到的数据和需要发送的数据存储在两段相互独立的内存中,但两段内存对外都命名为SBUF,因此对发送数据和接收数据的处理只需对SBUF处理即可。
  2. 无论是工作在哪种工作模式,在输入数据到单片机时,均须使SCON寄存器中的REN置1。
  3. 除方式0外,其余RXD均为数据接收引脚,TXD均为数据发送引脚

方式0

串口为同步移位寄存器的输入输出方式。主要用于扩展并行输入或输出口。数据由RXD(P3.0)引脚输入或输出,同步位移脉冲由TXD(P3.1)引脚输出。例如外部设备须并行输出数据到单片机,但单片机没有多余的引脚,则可以使用该引脚通信功能,与74HC595扩展的区别在于需要使用TXD引脚同步双方时钟。发送和接收均为8位数据,从低至高位依次发送。

输出时序图


先将数据写入SBUF,从低至高依次输出数据,在第八位结束时,硬件置TI=1(详见SCON中TI的描述),产生中断结束发送数据,后续还需软件置0。

输入时序图


输入前先将输入中断RI软件置0,输入完毕后RI硬件置1(详见SCON中RI描述),产生中断,结束输入。

方式1

一帧数据由1位起始位,8位数据位,1位停止位组成。

输出时序图


接收到停止位时,TI硬件置1(详见SCON中TI描述),产生中断,结束输出。

输入时序图


接收到起始位开始输入,至接收到停止位时,前八数据为存入SBUF,停止位进入RB8,RI硬件置1,产生中断,结束输入。

上述为SM2=1,多机通信中的场景。在SM2=0,单机通信中,接收到停止位即产生中断,结束输入。

方式2、3

数据格式

当输出时,数据第九位为TB8,为输出的标志位或校验位。
当输入时,数据第九位位RB8,为输入的标志位或校验位。

输出时序图


如上图所示,当移位寄存器检测到上种情况时,TI硬件置1,产生中断终止输出。

输入时序图


四、串口通信代码

波特率计算使用提供的波特率计算软件即可。电路图不太能看懂就省略了。
功能:

  1. 由于显示设备限制,将PC发送的数据返回给PC以代替单片机上的数据显示。
  2. 通过按键矩阵,可输入a~p字符,按下独立按键K3即可将单片机的数据发送给PC。

这是简单的设备之间的通信,后续单片机如果有合适的显示设备,或许会完善使用按键矩阵和独立按键实现拼音9键,实现单片机和PC的英文交互。

时延函数 delay.h

#ifndef _DELAY_H__
#define _DELAY_H__
/*10us=1,时延为10us*/
void delay_10us(unsigned int _10us){while(_10us--){}
}
/*1ms=1,时延为1ms*/
void delay_1ms(unsigned int _1ms){_1ms*=110;while(_1ms--){}
}
#endif

中断初始化函数 interrupt_utils.h

#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include "reg52.h"
/*中断初始化*/
/*外部中断0*/
void Int0_Init(const unsigned char *mode){//外部中断0的触发方式,0低电平触发,1下降沿触发EA=1;//总中断允许位EX0=1;//外部中断0允许位IT0=*mode;
}
/*外部中断1*/
void Int1_Init(const unsigned char *mode){//外部中断1的触发方式,0低电平触发,1下降沿触发EA=1;//总中断允许位EX1=1;//外部中断0允许位IT1=*mode;
}
void Timer0_Init(const unsigned char *mode ,const unsigned char *HighVal , const unsigned char *LowVal ){EA=1;//打开中断总允许位ET0=1;//打开T0中断允许位TR0=1;//定时/计数器中断0开始工作TMOD |= *mode;//设置T0工作模式TH0 = *HighVal; //高八位寄存器初值TL0 = *LowVal;  //第八位寄存器初值
}
void Timer1_Init(const unsigned char *mode ,const unsigned char *HighVal , const unsigned char *LowVal ){EA=1;//打开中断总允许位ET1=1;//打开T0中断允许位TR1=1;//定时/计数器中断0开始工作TMOD |= *mode;//设置T0工作模式TH1 = *HighVal; //高八位寄存器初值TL1 = *LowVal;  //第八位寄存器初值
}
#endif

串口初始化及相关功能函数 uart_init.h

#ifndef __UART_INIT_H__
#define __UART_INIT_H__
#include "interrupt_utils.h"
unsigned char data_buffer[10];//存储接收的数据
unsigned char Send_buffer[10];//要发送的数据
unsigned char Num=0;
unsigned char Send_Num=0;
/*设置串口寄存器参数1.设置串口寄存器2.设置波特率参数
*/
void Set_Uart( unsigned char *Uart_Reg_mode ,  unsigned char *Baud_mode){SCON = *Uart_Reg_mode;PCON |= *Baud_mode;
}
/*串口初始化函数*/
void Uart_Init(unsigned char T1_Mode , unsigned char Uart_Reg_mode , unsigned char Baud_mode ,  unsigned char Init_Val ){Set_Uart(&Uart_Reg_mode,  &Baud_mode);Timer1_Init(&T1_Mode ,&Init_Val , &Init_Val );ES=1; //打开串口中断允许位ET1=0;//关闭定时器中断1的允许位
}
/*串口发送一个字符*/
void Uart_Send_byte(unsigned char dat){SBUF = dat;while(!TI);//发出中断,TI硬件置1,跳出循环TI=0;//重置,取消本次中断  }
/*串口发送一串字符*/
void Uart_Send_String(){unsigned char i;for(i=0 ; i!=Send_Num;++i){Uart_Send_byte(Send_buffer[i]);}Send_Num=0;
}
/*串口接受数据(不超过10位)*/
void UART_Routine( ) interrupt 4{  RI=0;       //将接收中断标志清0 if(Num>9){    //超出缓存大小,覆盖从头开始存储Num=0;}   data_buffer[Num++] = SBUF;       /*由于单片机暂无合适的显示设备,将接收到的数据返回给电脑*/Uart_Send_byte(data_buffer[Num-1]);
}
#endif

矩阵按键扫描函数 scan_button.h

#ifndef __SCAN_BUTTON_H__
#define __SCAN_BUTTON_H__
/*扫描矩阵按键*/
#include "reg52.h"
#include "delay.h"
typedef unsigned int uint;
typedef unsigned char uchar;sbit line0 = P1^7;
sbit line1 = P1^6;
sbit line2 = P1^5;
sbit line3 = P1^4;
sbit col0 = P1^3;
sbit col1 = P1^2;
sbit col2 = P1^1;
sbit col3 = P1^0;char  Table16[4][4] = {{'a','b','c','d'},{'e','f','g','h'},{'i','j','k','l'},{'m','n','o','p'}} ;
/*确定行*/
uint get_line(void){uint retVal=4;col0=0;col1=0;col2=0;col3=0;if(!line0) retVal=0;if(!line1) retVal=1;if(!line2) retVal=2;if(!line3) retVal=3;col0=1;col1=1;col2=1;col3=1;return retVal;
}
/*确定列*/
uint get_col(void){uint retVal=4;line0=0;line1=0;line2=0;line3=0;if(!col0) retVal=0;if(!col1) retVal=1;if(!col2) retVal=2;if(!col3) retVal=3;line0=1;line1=1;line2=1;line3=1;return retVal;
}
/*监测按键,并返回按键值*/
char Scan_Button(){uint row;uint col;delay_10us(6000);row = get_line();col = get_col();delay_10us(6000);if(row!=4&&col!=4)return Table16[row][col];return 0;
}
#endif

主函数

#include "Uart_Init.h"
#include "Scan_Button.h"
/*1.由于暂时无合适的显示设备,所以将单片机接收到的信息返回给电脑显示。2.可以通过矩阵键盘输入信息,按独立按键k3进行发送
*/
void main(){Int0_Init(0);//外部中断0初始化Uart_Init(0x20,0x50,0x80,0xFA);//串口中断初始化while(1){char cha;cha=Scan_Button();if(cha)Send_buffer[Send_Num++] = cha;}
}
void Int0_Rountine() interrupt 0{ //按键矩阵输入完毕,按独立按键K3中断发送Uart_Send_String();
}

51单片机:串口通信相关推荐

  1. 51单片机串口通信模板_深入理解51单片机串口通信及通信实例

    串口通信的原理 串口通信(SerialCommunications)的概念非常简单,串口按位(bit)发送和接收字节.尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一 ...

  2. 51单片机串口通信原理、相关寄存器配置与简单串口收发程序代码

    目录 1. 串口通信原理 2. 51单片机串口通信 2.1 串口简要模式图 2.2 相关寄存器 (1)PCON.SCON.SBUF (2)IE.IPH.IP (3)配置T1定时器 2.3 波特率和系统 ...

  3. 51单片机串口通信模板_51单片机串口通信

    51 单片机串口通信 51 单片机串口通信(转载) 2009-03-03 18:22 一.串口通信原理 串口通讯对单片机而言意义重大,不但可以实现将单片机的数据传输到计 算机端,而且也能实现计算机对单 ...

  4. 51单片机~串口通信(讲解+代码)

    51单片机~串口通信 (一)计算机串行通信原理: 综上:所以在设置的时候,经常将SCON设置为0X50==0101 0000 ,使用方式1. (二)工作: 中断控制 led灯,每发送一条指令灯亮或灭( ...

  5. 51单片机串口通信【收集学习向】

    本篇整理了学习51串口通信过程中看到的一些比较好的文章,有很多的超链接.并根据自己遇到的情况分析了串口传输乱码的一些原因. 目录 1.原理知识 2.测试程序和虚拟仿真 3.电路设计与公母口连线 电路设 ...

  6. 51单片机串口通信发送以及接收代码详解1

    #include <reg51.h> //实验现象:单片接收电脑发送的字符串,并发回给PC端的代码.//函数声明 void uart_init(void); void uart_seng_ ...

  7. 51单片机串口通信发送以及接收代码详解2

    #include <reg51.h> //实验现象:在电脑端没按下发送的时候,单片一直给电脑发送aaa字符串: //实验现象:在电脑端按下发送的时候,结束字符串aaa的发送代码,执行单片接 ...

  8. 51单片机-串口通信

    目录 1.什么是通信 1.1.通信的概念 1.2.传送方式 1.3.同步方式 1.4.传送方向 1.5.校验方式 2.单片机串口介绍 2.1.硬件电路 2.2.电平标准 2.3.常见接口 2.4.内部 ...

  9. 51单片机-串口通信(串口向电脑发送信息电脑通过串口控制LED)

    文章目录 前言 一.串行通信口的功能以及串行通信口的结构及原理 1.1 串行通信口的功能 1.2 51单片机串口的结构 二.串行通信口的控制寄存器 2.1 串行控制寄存器SCON 2.2 电源控制寄存 ...

  10. 51单片机C语言波特率十六进制,理解51单片机串口通信的波特率与USB转串口通信...

    RS232 在我们电脑上,一般都会有一个9针的串行接口,这个串行接口叫做RS232接口,它和UART通信有关联,但是由于现在笔记本电脑不带9针串口,所以和单片机通信越来越趋于使用USB虚拟串口. 九针 ...

最新文章

  1. 计算机网络技术及应用 课程 英语,计算机网络应用—现代英语课堂中的第三种语言...
  2. LeetCode 803. 打砖块(并查集)
  3. html标记的索引,基于HTML标记分析及中文切词的网页索引研究与实现
  4. PetShop4.0的安装、设置、调试与体验(草稿)
  5. 映射date类型_SQLALchemy常见数据类型
  6. C学习笔记-makefile
  7. mysql 备份 没有自动删除文件_删掉spfile在没有自动备份控制文件下从以前的rman备份中恢复数据库...
  8. 百度地图API的第一次接触
  9. 【DIY贴片机】基于opencv识别定位电子元件
  10. FS68001电动牙刷无线充电IC
  11. 【JavaWeb】JSP:基本语法大全
  12. java中length的使用法_java -length的三种用法说明
  13. WIN系统仿MAC任务栏工具分享——RocketDock
  14. strtol,strtoul,strtod
  15. 男神网络红人莫小涛2022生活百度图片大全
  16. Joining data
  17. 21天学会c++(英汉对照,个人翻译,水平有限,供参考)-------第2天
  18. leetcode java 大厂基础面试题附答案(二)
  19. nobody用户介绍
  20. 智慧灯杆项目案例:点亮科技城市!宁波第一个5G智能路段投入使用!

热门文章

  1. sprint演示会议
  2. 打开计算机硬盘有声音,电脑硬盘有响声总吱吱响的解决方法
  3. 计算机的DNS地址如何设置,如何设置电脑的DNS地址?
  4. Excel 冻结首行
  5. CRC校验(模型、手算、程序编写)
  6. 电商数据分析项目总结!
  7. 计算机无法显示大容量,Win7系统电脑提示“usb大容量存储设备 代码10”的解决方法...
  8. 三分钟彻底弄明白shiro原理
  9. Egret引擎启动流程和源码裁剪
  10. 微信公众图文消息html,微信公众号图文消息怎么添加图片背景?