17江科大stm32视频学习笔记——USART串口协议和USART串口外设

Posted weixin_45981798

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了17江科大stm32视频学习笔记——USART串口协议和USART串口外设相关的知识,希望对你有一定的参考价值。

目录

1、通信接口

2、 硬件电路

3、电平标准

4、串口参数及时序

5、USART简介

 6、USART工作

(1)写操作

(2)读操作

(3)帧头和帧尾的添加和除由电路自动执行

(4)硬件数据控制流

(5)中断输出控制(USART)

(6)波特率发生器

 7、USART基本结构

 8、数据帧

 9、波特率发生器


1、通信接口

通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统通信协议:制定通信的规则,通信双方按照协议规则进行数据收发

 异步:需要双方约定一个频率

2、 硬件电路

简单双向串口通信有两根通信线(发送端 TX 和接收端 RX TX RX 要交叉连接当只需单向的数据传输时,可以只接一根通信线当电平标准不一致时,需要加电平转换芯片

 

 两个设备之间的GND一定要接在一起,但是VCC可以各自接

3、电平标准

TTL 电平: +3.3V +5V 表示 1 0V 表示 0RS232 电平: -3~-15V 表示 1 +3~+15V 表示 0RS485 电平:两线压差 +2~+6V 表示 1 -2~-6V 表示 0 (差分信号)

4、串口参数及时序

波特率:串口通信的速率 速率的参数就是波特率,波特率就是每秒传输码元的个数,单位是码元/s(baud) 比特率:每秒传输的比特数,单位是bit/s,或者是bps 在二进制的情况下,一个码元及时一个bit,此时波特率等于比特率起始位:标志一个数据帧的开始,固定为低电平数据位:数据帧的有效载荷, 1 为高电平, 0 为低电平,低位先行校验位:用于数据验证,根据数据位计算得来停止位:用于数据帧间隔,固定为高电平

  • 字节装载在数据帧中,数据帧由起始位、数据位、停止位组成
  • 数据位有8个,代表一个字节的8位置,可以在最右边加一个奇偶校验位,则数据位总共是9位。接收方在接收数据后,会验证数据位和校验位
  • 若规定发送的波特率是1000bps,表示1s要发1000位,每一位的时间就是1ms,发送方每隔1ms发送一位,接收方每隔1ms接受一位,决定了每隔多久发送一位
  • 空闲状态下,起始位为高电平,起始位给低电平,使其产生下降沿,表示数据帧要开始

5、USART简介

USART: 通用同步 / 异步收发器USART STM32 内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从 TX 引脚发送出去,也可自动接收 RX 引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里.自带波特率(一般设置为9600/115200)发生器,最高达 4.5Mbits/s可配置数据位长度( 8/9 )、停止位长度( 0.5/1/1.5/2 可选校验位(无校验 / 奇校验 / 偶校验)支持同步模式、硬件流控制、 DMA 、智能卡、 IrDA LIN 同步模式:多了个时钟CLK的输出STM32F103C8T6 USART 资源: USART1(APB2总线上的设备) USART2(APB1) USART3(APB1)

 6、USART工作

(1)写操作

当数据移位完成后,数据会立刻自动从TDR发送移位寄存器

TDR和移位寄存器的双重缓存,保证在连续发送数据时,数据帧之间不会有空闲,提高了工作效率

(2)读操作

 因为串口协议规定是低位先行,所以接收移位寄存器时从高位往低位方向移动

(3)帧头和帧尾的添加和除由电路自动执行

(4)硬件数据控制流

A向B发送数据,当A一直发,B处理不过来; 若无硬件控制流,B只能抛弃新数据或者覆盖元数据; 有硬件控制流,硬件电路上会多出一条线,B没准备好置高电平,准备好置低电平; A收到B的反馈决定数据发送,防止因为B处理慢而导致数据丢失。

 能接收的时候,RTS就置低电平,请求对方发送,对方的CTS接收到后,就可以一直发

处理不过来时,RTS就置高电平,对方的CTS接收到后,就会暂停发送

(5)中断输出控制(USART)

 TXE发送寄存器空,RXNE接收寄存器非空,是判断发送状态和接收状态的必要标志位
 中断输出控制就是配置中断是不是能通向NVIC

(6)波特率发生器

  

波特率发生器是分频器,APB时钟进行分频,得到发送和接收移位的时钟

时钟输入时fPCLKx(x=1或2),USART1挂载在APB2,所以就是PCLK2的时钟,为72M

其他的USART挂载在APB1,就是PCLK1的时钟,为36M

之后对时钟进行分频,除以USARTDIV的分频系数,分频后再除以16,得到发送器时钟和接收器时钟,通向控制部分

若TE=1,发送器使能,发送部分的波特率就有效

若RE=1,接收器使能,接收部分的波特率有效

 7、USART基本结构

 8、数据帧

 有8位字长和9位字长,分别可以选择有校验和无校验

 9位建议有校验,8位建议无校验

 停止位有0.5,1,1.5,2,建于选择1位

9、波特率发生器

发送器和接收器的波特率由波特率寄存器BRR里的DIV确定
计算公式:波特率 = fPCLK2/1 / (16 * DIV)//内部有16倍波特率的采样时钟 

配置USART1为9600的波特率
9600=72M(USART1的时钟)/(16*DIV)
DIV=72M/9600/16=468.75(二进制:11101 0100.11)
用库函数配置,需要多少波特率直接写就行

STM32G0学习手册——多串口同时使用printf输出

目录

新建工程

代码部分


这个实验向我们演示,不同的串口使用printf函数来输出对应的信息。默认printf()函数使用usart1,剩下usart2~4分别使用USART2_printf(),USART3_printf(),USART4_printf()输出信息。

项目地址:GitHub

新建工程

1、新建芯片工程"g071c8/g071rb",打开SWD调试接口、HSE

2、 设置时钟树,HCLK=64MHz

3、 查看数据手册,看那些引脚可以用作usart1、usart2、usart3、usart4。把这些引脚设置成TX,RX

USART1:PA10,PA9。USART2:PA2,PA3。USART3:PB10,PB11。USART4:PA0,PA1

4、启用USART外设,参数按照自己的实际来填。模式设为Asynchronous,115200,8bit,None,1

5、 项目管理填好信息。生成代码"GENERATE CODE"

6、使用MDK打开工程,debug选项中勾上“Reset and Run”

代码部分

1、usart.h中添加如下代码

#include <stdarg.h>

/* USER CODE BEGIN Prototypes */

void USART4_printf(char *fmt,...);                   //重写usart4的printf函数
void USART3_printf(char *fmt,...);
void USART2_printf(char *fmt,...);

/* USER CODE END Prototypes */

2、usart.c添加如下代码

/* USER CODE BEGIN 0 */

#include <stdio.h>
#include <string.h>
#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE

  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
  return ch;


#define USART_TXBUFF_SIZE   256                                 //定义串口发送缓冲区大小 256字节
__align(8) char usart_txBuff[USART_TXBUFF_SIZE];                //字节对齐缓冲区

//usart4的printf()
void USART4_printf(char *fmt,...)

  uint32_t i,length;
  va_list ap;
  va_start(ap,fmt);
  vsprintf(usart_txBuff,fmt,ap);
  va_end(ap);
  length=strlen((const char*)usart_txBuff);
  while((USART4->ISR&0x40)==0);
  for(i=0;i<length;i++)
  
    USART4->TDR=usart_txBuff[i];
    while((USART4->ISR&0x40)==0);
  


//usart3的printf()
void USART3_printf(char *fmt,...)

  uint32_t i,length;
  va_list ap;
  va_start(ap,fmt);
  vsprintf(usart_txBuff,fmt,ap);
  va_end(ap);
  length=strlen((const char*)usart_txBuff);
  while((USART3->ISR&0x40)==0);
  for(i=0;i<length;i++)
  
    USART3->TDR=usart_txBuff[i];
    while((USART3->ISR&0x40)==0);
  


//usart2的printf()
void USART2_printf(char *fmt,...)

  uint32_t i,length;
  va_list ap;
  va_start(ap,fmt);
  vsprintf(usart_txBuff,fmt,ap);
  va_end(ap);
  length=strlen((const char*)usart_txBuff);
  while((USART2->ISR&0x40)==0);
  for(i=0;i<length;i++)
  
    USART2->TDR=usart_txBuff[i];
    while((USART2->ISR&0x40)==0);
  


/* USER CODE END 0 */

3、main.c中添加如下代码

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

int main(void)

  while (1)
  
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_Delay(1000);
		
    USART4_printf("This is the signal from serial port 4.\\r\\n");
    USART3_printf("This is the signal from serial port 3.\\r\\n");
    USART2_printf("This is the signal from serial port 2.\\r\\n");
    printf("This is the signal from serial port 1.\\r\\n");  
  
  /* USER CODE END 3 */

4、最后编译,烧录固件,串口输出如图

以上是关于17江科大stm32视频学习笔记——USART串口协议和USART串口外设的主要内容,如果未能解决你的问题,请参考以下文章

stm32学习笔记-3GPIO通用输入输出口

stm32串口通信

stm32串口——标志位学习

16 . USART 串口通信实验

16 . USART 串口通信实验

16 . USART 串口通信实验