STM32 USART解析

本文详细介绍了STM32的USART通信,包括结构体、重定向、轮询模式、DMA模式和中断模式的使用。重点讲解了HAL库中的HAL_USART_Transmit、HAL_UART_Transmit_DMA、HAL_UART_Receive_IT等函数,以及DMA配置和中断处理。同时提到了数据字长、DMA配置和中断标志位的管理。
摘要由CSDN通过智能技术生成

一:前言

1、USART 数据寄存器 (USART_DR) 只有低 9 位有效,并且第 9 位数据是否有效要取决于 USART控制寄存器1(USART_CR1) 的 M 位设置,当 M 位为 0 时表示 8 位数据字长,当 M 位为 1 表示 9位数据字长(最后一位为奇偶校验位),我们一般使用 8 位数据字长

寄存器 作用 标志
TXE:发送数据寄存器空 当TDR寄存器中的数据被硬件转移到移位寄存器的时候,该位被硬件置1,对USART_DR的写操作,该位清零。 1:数据已经被转移到移位寄存器
TC:发送完成 当包含有数据的一帧发送完成后,并且TXE=1时,由硬件将该位置“1” 。清零:软件序列清除该位(先读USART_SR,然后写入USART_DR,也就是读一下然后直接写就行了),TC位也可以通过写入“0”来清除,只有在多缓存通讯中才推荐这种清除程序。(移位寄存器也发送光了) 1:发送完成
RXNE:读数据寄存器非空 当RDR移位寄存器中的数据被转移到USART_DR寄存器中,该位被硬件置位。对USART_DR的读操作可以将该位清零。RXNE位也可以通过写入0来清除,只有在多缓存通讯中才推荐这种清除程序。 1:收到数据,可以读出。
IDLE:监测到总线空闲 当检测到总线空闲时,该位被硬件置位。由软件序列清除该位(先读USART_SR,然后读USART_DR)。注意:IDLE位不会再次被置高,直到RXNE位被置起(即又检测到一次总线空闲) 1:检测到总线空闲

二:结构体

typedef struct __USART_HandleTypeDef
{
   
  USART_TypeDef                 *Instance;        /*!< USART registers base address        */

  USART_InitTypeDef             Init;             /*!< Usart communication parameters      */

  uint8_t                       *pTxBuffPtr;      /*!< Pointer to Usart Tx transfer Buffer */

  uint16_t                      TxXferSize;       /*!< Usart Tx Transfer size              */

  __IO uint16_t                 TxXferCount;      /*!< Usart Tx Transfer Counter           */

  uint8_t                       *pRxBuffPtr;      /*!< Pointer to Usart Rx transfer Buffer */

  uint16_t                      RxXferSize;       /*!< Usart Rx Transfer size              */

  __IO uint16_t                 RxXferCount;      /*!< Usart Rx Transfer Counter           */

  DMA_HandleTypeDef             *hdmatx;          /*!< Usart Tx DMA Handle parameters      */

  DMA_HandleTypeDef             *hdmarx;          /*!< Usart Rx DMA Handle parameters      */

  HAL_LockTypeDef                Lock;            /*!< Locking object                      */

  __IO HAL_USART_StateTypeDef    State;           /*!< Usart communication state           */

  __IO uint32_t                  ErrorCode;       /*!< USART Error code                    */

#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
  void (* TxHalfCpltCallback)(struct __USART_HandleTypeDef *husart);        /*!< USART Tx Half Complete Callback        */
  void (* TxCpltCallback)(struct __USART_HandleTypeDef *husart);            /*!< USART Tx Complete Callback             */
  void (* RxHalfCpltCallback)(struct __USART_HandleTypeDef *husart);        /*!< USART Rx Half Complete Callback        */
  void (* RxCpltCallback)(struct __USART_HandleTypeDef *husart);            /*!< USART Rx Complete Callback             */
  void (* TxRxCpltCallback)(struct __USART_HandleTypeDef *husart);          /*!< USART Tx Rx Complete Callback          */
  void (* ErrorCallback)(struct __USART_HandleTypeDef *husart);             /*!< USART Error Callback                   */
  void (* AbortCpltCallback)(struct __USART_HandleTypeDef *husart);         /*!< USART Abort Complete Callback          */

  void (* MspInitCallback)(struct __USART_HandleTypeDef *husart);           /*!< USART Msp Init callback                */
  void (* MspDeInitCallback)(struct __USART_HandleTypeDef *husart);         /*!< USART Msp DeInit callback              */
#endif  /* USE_HAL_USART_REGISTER_CALLBACKS */

} USART_HandleTypeDef;

三:重定向

如果忘记重定向了,然后还是使用了printf,程序就会卡死
当想换一个usart做端口打印的时候,只需要在重定向函数中将&huart1 换成我们需要的那个。

1:代码分析

#include <stdio.h>
///重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
   
	/* 发送一个字节数据到串口DEBUG_USART */
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);	
	
	return (ch);
}

///重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
   
		
	int ch;
	HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);	
	return (ch);
}
#include <stdio.h>
//记得在usart.h中声明一下函数
/*****************  发送字符串 **********************/
void Usart_SendString(uint8_t *str)
{
   
	unsigned int k=0;
  do 
  {
   
      HAL_UART_Transmit(&huart1,(uint8_t *)(str + k) ,1,1000);
      k++;
  } while(*(str + k)!='\0');
  
}

2:使用

	/*调用printf函数,因为重定向了fputc,printf的内容会输出到串口*/
	printf("欢迎使用野火开发板\n");	

	/*自定义函数方式*/
	Usart_SendString( (uint8_t *)"自定义函数输出:这是一个串口中断接收回显实验\n" );

四: 轮询模式

1: HAL_USART_Transmit()

1:HAL_USART_Transmit:在规定时间内发送一个数组中的size个byte
使用这个函数的时候,可以直接用重定向中的那几个函数
2:他是没有回调函数的

    // 实验1:
     char a[]="这是第一句话";
	 uint8_t d[]="1wo\nshi";//\n也是一个字符,换行
	 char c=99;//这个99就代表ASCII
   
    printf("欢迎使用开发板\n");
	printf("1:%s\n",a);
	Usart_SendString( (uint8_t *)"这是第二句话\n" );//这是自己定义的函数 用来发送一串的
	Usart_SendString( (uint8_t *)a);

	HAL_UART_Transmit(&huart1,d, 4, 1000);
	HAL_UART_Transmit(&huart1, (uint8_t *)&c,1, 1000);

在这里插入图片描述

//实验2:
   char str[80];	 
	 char num=99
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

成草

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

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

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

打赏作者

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

抵扣说明:

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

余额充值