首页 > 其他分享 >UART异步串行通信协议

UART异步串行通信协议

时间:2025-01-09 14:48:37浏览次数:1  
标签:异步 UART 通信协议 发送 UART2 寄存器 波特率 接收

UART概述

UART的定义

  • USART指通用同步收发器,UART指通用异步收发器
  • 这些通用收发器提供了一种灵活的方式与外部设备进行单工/半双工/全双工方式的数据交互,并且可选择多种波特率,支持多种通信协议和功能模式等

UART的类别

  • STM8S单片机片内总共有3个串口资源:UART1/2/3(STM8S105则只有UART2这个串口资源,具体情况查阅对应型号的数据手册)

  • UART1/2/3之间在功能支持上存在差异,见下图:

    image

UART配置流程

UART配置简述

  1. 主时钟频率配置

    确定主时钟,这与后续波特率的设置相关

  2. 配置通信数据帧格式

    设定发送/接收数据位数

    设定发送/接收数据校验位以及校验方式(可选),

    设定发送/接收数据停止位位数

  3. 计算并配置波特率

    设定发送/接收数据波特率

  4. 使能发送/接收中断功能

    此步可选,让单片机发送出数据/接收到数据时进入中断服务程序

  5. 使能发送/接收功能

    使能之后,然后就开始向寄存器写入数据以发送/接收单字节数据,并等待发送/接收完毕

UART相关寄存器

  • 控制寄存器UART_CR1

    明确发送的数据帧格式,配置奇偶校验

    • 本寄存器的M位(位4)配置数据帧的格式(UART数据字长度由此位决定):

      配置为1,数据帧格式为1个起始位,8个数据位,n个停止位(取决于另一个寄存器UART_CR3中的STOP[1:0]位)

      配置为1,数据帧格式为1个起始位,9个数据位,1个停止位;此时需要本寄存器的T8位(位6)与R8位(位7)用以储存发送与接收的第九位

    • PIEN位(位0)、PS位(位1)与PCEN位(位2)用于配置校验:

      PCEN位配置为1则使能硬件奇偶校验控制(校验位的启用状态将导致数据帧格式变化,例如:M位为1且PCEN位也为1,则数据帧有1起始位+8数据位+1校验位+停止位,校验位将挤占一个数据位);

      PS位用于选择校验方式,0使能偶校验,1则使能奇校验;

      PIEN位配置为1则使能校验中断,当发生数据校验错误时产生中断

    各个位的具体作用

    image

  • 控制寄存器UART_CR3

    配置数据的停止位

    • STM8单片机通信的停止位可以设定为1位/1.5位/2位,通过对本寄存器的STOP[1:0]位(由位5与4共同组成)配置得到:写入00则为1位,10为2位,11为1.5位

    各个位的具体作用(其它位在UART3上不存在):

    image

  • 控制寄存器UART_CR2

    使能发送/接收功能,配置发送/接收中断

    • 配置好数据帧格式后,配置发送功能位TEN位(位3)为1以使能发送,配置接收功能位REN位(位2)为1以使能接收
    • 如果需要检测数据是否被硬件传送到移位寄存器中,可以将发送数据中断使能位TIEN位(位7)置1;如果需要检测数据是否发送完毕,可以将发送完成中断使能位TCIEN位(位6)置1
    • 如果需要检测是否接收到数据,可以将接收中断使能位RIEN位(位5)置1

    各个位的具体功能:

    image

  • 波特率寄存器UART_BRR1/2

    收发双方波特率应当匹配,配置波特率流程如下:

    1. 确定主时钟频率fMASTER

    2. 确定预设波特率:串口收发波特率=fMASTER/UART_DIV(串口分频值)

    3. 计算UART_DIV取值:例如欲设定波特率为9600bps,而主时钟频率为fHSI/2=8MHz,则根据公式可计算得UART_DIV=8.33.33,取833

      在连续大数据量通信时这样的误差会导致缺码,可以把时钟源切换为更高精度的外部时钟源以减小误差

    4. 配置波特率寄存器:将计算得的数值转换为十六进制,得0341HEX,配置如下

      image

      UART_BRR1的0至7位均为UART_DIV位,定义了UART分频数的中间8位(第二、第三半位元),UART_BRR2的7至4位则是分频数的高四位,3到0位是低四位

    • 特别注意,计算出的分频值不应小于16,且UART_BRR1不能被赋值为0,否则会关闭波特率时钟导致无法通信,若中间两位恰好为0则需要重新设定波特率或改变主时钟频率
  • 数据状态寄存器UART_SR

    用于反映通信过程中的一些状态变化,例如:

    • 检测数据是否出错:发生奇偶校验错误时,此寄存器的PE位(位0)会被置1;
    • 检测发送数据是否移入寄存器:开启发送数据中断使能(UART_CR2的TIEN位(位7)置1),此时UART_SR的TXE位(位7)为1时产生中断(表示数据已经被转入寄存器);
    • 检测数据是否发送完毕:开启发送完成中断使能(UART_CR2的TCIEN位(位7)置1),此时UART_SR的TC位(位6)为1时产生中断(表示发送已经完成);
    • 检测接收到数据:开启接收中断使能(UART_CR2的RIEN位(位5)置1),此时UART_SR的RXNE位(位5)或OR位(位3)为1时产生中断(表示收到数据);

    各个位的具体含义:

    image

  • 数据寄存器UART_DR

    内部分为数据发送寄存器TDR与数据接收寄存器RDR

    上述寄存器配置完成后,即完成了对数据帧格式的约定与功能位的使能,就可以进入正常的发送/接收程序了,发送过程只需将欲发送的数据传入串口数据寄存器UART_DR即可

代码实现

  • 初始化UART
    //首先初始化UART2的TX与RX,以PD6连接TX,PD5连接RX为例
    void UART2_IO_init()
    {
        PD_DDR=0x20;		//TXD设置为OD输出
    	PD_CR1=0x40;		//RXD设置为上拉输入
    	PD_CR2=0x00;		//全部低速率
    }
    
    //初始化函数,用于配置UART2的波特率与数据帧格式,并最后使能UART2
    void UART2_init()
    {
        UART2_IO_Init();	//初始化UART的IO口
    
    	UART2_BRR2 = 0x00;	//设置波特率寄存器,先设置BRR2
    	UART2_BRR1 = 0x0D;	// 2M/9600,换算为十六进制为000D
    	//具体配置事项见寄存器UART_BRR介绍,此处使用默认时钟2MHz,波特率为9600
    
    	UART2_CR1 = 0x00;			//设置数据帧格式:8个数据位,无校验位
    	UART2_CR3 = 0x00;			//设置 1个停止位
    	UART2_CR2 = 0x2C;			//使能发送、接收以及接收中断
    	//0010 1100 三个1分别对应RIEN位接收中断 TEN位发送使能 REN位接收使能
    }
    
  • 发送程序
    //让单片机通过UART向外发送数据
    //原理:利用UART_SR状态寄存器判断当前发送的进程,以作出不同反应
    void UART2_SendStr(unsigned char *s)	//传入指向欲发送字符的指针
    {
    	while(*s != '\0')	//当发送未到达终止位时
    	{
    		while(UART2_SR & 0x80==0);
    		//1000 0000,UART_SR的TXE位为1时表示数据已经被转入寄存器
    		//当TXE位还不是1时等待,以让数据从数据发送寄存器转移到 Transmit shift register
    
    		UART2_DR = *s;	//发送数据寄存器装填当前指向的一位
    		s++;			//指针指向下一位
    
    		while((UART2_SR & 0x40)== 0);
    		//0100 0000,UART_SR的TC位为1时表示数据发送已经完成
    		//当TC位还不是1的时候等待,以待数据发送完成
    	}
    }
    
  • 接收程序
    //让单片机读取自UART发送来的数据
    //原理:开启接收中断后,将接收程序写在中断服务函数中
    unsigned int ReceiveData=0xFF;//用一个变量存放接收到的数据
    #pragma vector=23	//UART2中断向量号为21
    __interrupt void UART2_Receive_Interrupt(void)
    {
    	while(UART2_SR & 0x20 == 0);//等待数据接收完成
    	ReceiveData = UART2_DR;	//保存接收而来的数据
    }
    
  • 与电脑进行串口通信的实验设计
    1. 在实验之前,先在电脑上打开“串口调试助手”这个软件(有很多软件都可以实现电脑与单片机的串口通信功能,自行搜索选择一个下载即可)

    2. 然后,使用USB线将电脑和单片机连接起来(一般的开发板上会有USB-UART接口),在串口调试助手的串口选择中选择USB连接的串口

      需要注意的是,电脑未必能识别出这个串口,原因是电脑系统没有你的单片机上的USB-UART芯片的相应驱动,解决方法是看你的开发板上使用的USB-UART芯片型号(比如PL-2303),下载对应驱动安装

      如果还是找不到串口,很可能是因为新的Win系统不支持这个驱动,打开电脑的设备管理器,在“通用串行总线控制器”中刚刚安装的驱动有没有带三角感叹号标识,如果有的话卸载它,去网上搜索其他能够兼容的版本

    3. 在软件中设置波特率、停止位、校验位、数据位等与单片机程序一致,打开串口

    4. 实验现象是:发送0到3不同的数时,分别控制PB0-3连接的LED灯亮灭,然后在接收窗口中应该就能看到单片机发送的数据

    实验代码很简单,首先写好上文提到的初始化、发送与接收函数,再调用

    unsigned char StringBuf[]="Hello,world! \r\n";
    void main(void)
    {
    	GPIO_init();//对LED灯初始化
    	UART2_init();
    	asm("RIM");
    	while(1)
    	{
    		UART2_SendStr(StringBuf);//发送字符串
    		delay_ms(3000);
    	}
    }
    
    #pragma vector=23
    __interrupt void UART2_Receive_Interrupt(void)
    {
    	while(UART2_SR & 0x20 == 0);
    	ReceiveData = UART2_DR;
    	switch(ReceiveData)
    	{
    		case 0:PB_ODR_ODR0 = !PB_ODR_ODR0; break;
    		case 1:PB_ODR_ODR1 = !PB_ODR_ODR1; break;
    		case 2:PB_ODR_ODR2 = !PB_ODR_ODR2; break;
    		case 3:PB_ODR_ODR3 = !PB_ODR_ODR3; break;
    	}
    }
    

标签:异步,UART,通信协议,发送,UART2,寄存器,波特率,接收
From: https://www.cnblogs.com/untit1ed/p/18662101

相关文章

  • FastAPI使用异步 ORM 进行高效数据库操作与管理
    FastAPI使用异步ORM进行高效数据库操作与管理目录......
  • FastAPI 依赖注入、异步任务与分布式调度
    FastAPI依赖注入、异步任务与分布式调度目录......
  • Fast-Retry:一个支持百万级多任务异步重试框架
    前言假设你的系统里有100万个用户,然后你要轮询重试的获取每个用户的身份信息,如果你还在使用SpringRetry和GuavaRetry之类的这种单任务的同步重试框架,那你可能到猴年马月也处理不完,即使加再多的机器和线程也是杯水车薪,而Fast-Retry正是为这种场景而生。Fast-Retry一个高性......
  • C#中如何使用异步编程
    在C#中,异步编程主要通过async和await关键字来实现。异步编程的目的是让程序在执行耗时操作(如I/O操作、网络请求等)时不会阻塞主线程,从而提高程序的性能。1.异步编程的核心概念async关键字用于标记一个方法为异步方法。异步方法的返回类型通常是Task、Task<T>或Va......
  • 【江协STM32】10-1 I2C通信协议
    1.I2C通信I2C(InterICBus)是由Philips公司开发的一种通用数据总线两根通信线:SCL(SerialClock,串行时钟线)、SDA(SerialData,串行数据线)同步,半双工带数据应答支持总线挂载多设备(一主多从、多主多从)         2.硬件电路所有I2C设备的SCL连在一起,SDA连在一起设......
  • 定时任务与异步任务:django-apscheduler 与 django-Q的区别
    django-apscheduler和django-Q是两个用于调度任务和异步任务处理的Django扩展库,但它们的功能和设计目标有所不同。以下是两者的主要区别:1.django-apschedulerdjango-apscheduler是Django框架下的一个定时任务调度工具,它基于Python的APScheduler实现。它主要......
  • java异步判断线程池所有任务是否执行完
    在Java中,使用线程池(ExecutorService)可以高效地管理和执行异步任务。对于某些应用场景,可能需要异步地判断线程池中所有任务是否执行完毕。以下是一个高度专业的指南,讲解如何在Java中实现这一功能。步骤概述创建并配置线程池。提交多个异步任务到线程池。使用 CompletionServi......
  • 聊一聊 C#异步中的Overlapped是如何寻址的
    一:背景1.讲故事前段时间训练营里的一位朋友提了一个问题,我用ReadAsync做文件异步读取时,我知道在Win32层面会传lpOverlapped到内核层,那在内核层回头时,它是如何通过这个lpOverlapped寻找到ReadAsync这个异步的Task的呢?这是一个好问题,这需要回答人对异步完整的运转流程有一......
  • window环境运行 django+celery+redis 异步任务报错:kombu.exceptions.OperationalError
    在所有配置都正常,并且redis服务正常,django和celery服务启动都正常;但就在请求执行异步任务时报错了:kombu.exceptions.OperationalError:[WinError10061]由于目标计算机积极拒绝,无法连接。启动服务指令:django:pythonmanage.pyrunservercelery:celery-Adifyworker-l......
  • USB子系统驱动 USB通信协议 Type A、Type A 3.0、Type C
    目录USB硬件基础TypeA引脚说明TypeA3.0引脚说明TypeC引脚说明USB驱动你一定需要知道的事USB硬件基础在了解LINUX的USB驱动之前,我们肯定是要了解相关硬件内容的,如下给出了三种常用的USB接口。特性TypeA(2.0)TypeA3.0TypeC接口形状长方形,单向插入与TypeA2......