5.STM32CubeMX学习笔记五:STM32的串口通信基础

一、串行接口相关知识点

并行通信、串行通信的概念。
1.串行通信
串行通信是指计算机与I/O设备之间数据传输的各位是按顺序依次一位接一位进行传送。通常数据在一根数据线或一对差分线上传输。
2.并行通信
并行通信是指计算机与I/O口设备间通过多条传输线交换数据,数据的各位同时进行传送。
单工、半双工、全双工三种通信方式的概念。
异步串行通信: 通信双方在没有同步时钟的前提下,将一个字符(包括特定的附加位)按位进行传输的通信方式。
**波特率:**每秒钟传输的二进制位数,如9600bps。通信时,通信双方波特率需要保证一致。
TTL电平<—->RS232:MAX3232 SP3232
串口<———>USB接口:CH340 CP2012

STM32芯片的串口UASRT功能十分强大,但对于日常编程而言,使用最多的还是异步串行通信。
串口1:USART1_TX与PA9复用,USART1_RX与PA10复用。
串口2:USART2_TX与PA2复用,USART2_RX与PA3复用。

二、HAL库中串口发送的重要函数

查询方式,阻塞式发送函数(初学者,推荐使用)   
HAL_StatusTypeDef  HAL_UART_Transmit(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size, uint32_t Timeout);

参数1:huart,串口实例的指针。(哪个串口?哪个外设?)
参数2*pData,待发送数据缓冲区的指针。(内容在哪?)
参数3:Size,待发送数据的字节数。
参数4:Timeout,超时时间值。
返回值:HAL_StatusTypeDef,函数执行状态。
typedef enum
{
  HAL_OK       = 0x00U,
  HAL_ERROR    = 0x01U,
  HAL_BUSY     = 0x02U,
  HAL_TIMEOUT  = 0x03U
} HAL_StatusTypeDef;

中断方式,非阻塞式发送函数
HAL_StatusTypeDef  HAL_UART_Transmit_IT(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size);
参数1:huart,串口实例的指针。
参数2*pData,待发送数据缓冲区的指针。
参数3:Size,待发送数据的字节数。
返回值:HAL_StatusTypeDef,函数执行状态。

串口发送完毕中断回调函数  
void HAL_UART_TxCpltCallback(UART_HandleTypeDef  *huart);
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef  *huart)
应用举例:使用非阻塞式的串口发送函数,将发送缓数组dat_Txd中的前5个数据发送到USART1,在数据发送完成后,翻转PB9引脚的输出电平。   
//使用中断,非阻塞方式 
HAL_UART_Transmit_IT(&huart1,  dat_Txd, 5);

void HAL_UART_TxCpltCallback(UART_HandleTypeDef  *huart) 
{         
    if(huart->Instance == USART1);         
    {             
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);    
    }
}

 
//使用查询,阻塞方式 
HAL_UART_Transmit(&huart1,  dat_Txd, 5, 10000);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);

三、HAL库中串口接收的重要函数

查询方式,阻塞式接收函数
     
HAL_StatusTypeDef  HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData,  uint16_t Size, uint32_t Timeout);
参数1:huart,串口实例的指针。
参数2*pData,数据接收据缓冲区的指针。
参数3:Size,待接收数据的字节数。
参数4:Timeout,超时时间值。
返回值:HAL_StatusTypeDef,函数执行状态。

非阻塞式接收函数(推荐使用)
HAL_StatusTypeDef  HAL_UART_Receive_IT(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size);
参数1:huart,串口实例的指针。
参数2*pData,数据接收据缓冲区的指针。
参数3:Size,待接收数据的字节数。
返回值:HAL_StatusTypeDef,函数执行状态。

串口接收完毕中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart);
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef  *huart);
应用举例:使用非阻塞式的串口接收函数,接收USART1中的一个字节,将其保存在dat_Rxd变量中,在数据接收完成后,判断该字节,若为0x5A,则翻转PB8引脚的输出电平。
//使用中断,非阻塞方式
HAL_UART_Transmit_IT(&huart1,  &dat_Rxd, 1);
  
void HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart)    
{        
    if(huart->Instance == USART1)    
    {       
        if(dat_Rxd == 0x5A)      
            HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
    }
}

四、练习:上位机通过串口控制LED灯开关

在STM32F103ZET6开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能:
【1】开机后,向串口1发送“hello world!”。
【2】串口1收到字节指令“0xA1”,打开LED1,发送“LED1 Open!”。
【3】串口1收到字节指令“0xA2”,关闭LED1,发送“LED1 Closed!”。
【4】在串口发送过程中,打开LED0作为发送数据指示灯。

第一部分:STM32CubeMX的配置
调试方式,时钟源,时钟树,IO口设置等基本配置项目与前几篇笔记相同。
配置串口通信时,在左侧的Connectivity选项卡中,找到USART1串口,通信模式选择异步时钟,下方的设置选项中设置波特率。
USART1设置
设置后,不要忘记使能对应NVIC通道。
使能NVIC
第二部分:Keil5中代码的编写
【1】串口通信参数的设置
在项目的usart.c文件中可以看到,该代码中对串口USART1的相关参数进行了初始化,初始化的内容是前期在STM32CubeMX中设置的:

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;                 //波特率
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;          //支持读写
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;

【2】回调函数的剖析
在main.c文件所关联的头文件,文件名为stm32f1xx_hal_uart.h,在这个文件中可以找到关于串口接收的回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

【3】回调函数的编写

/* USER CODE BEGIN 0 */
#define LED0_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
#define LED0_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
#define LED1_ON() HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET);
#define LED1_OFF() HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);

uint8_t TX_str1[] = "hello world!\r\n";
uint8_t TX_str2[] = "LED1 Open!\r\n";
uint8_t TX_str3[] = "LED1 Close!\r\n";
uint8_t RX_dat = 0;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART1)
	{
		if(RX_dat == 0xa1)
		{
				LED1_ON();
			
				LED0_ON();
				HAL_UART_Transmit(&huart1,TX_str2,sizeof(TX_str2),10000);
				LED0_OFF();
				HAL_UART_Receive_IT(&huart1,&RX_dat,1);//判断接收到A1字节,执行完相关操作后,需要继续等待接收字符串
		}
		else if(RX_dat == 0xa2)
		{
				LED1_OFF();
			
				LED0_ON();
				HAL_UART_Transmit(&huart1,TX_str3,sizeof(TX_str3),10000);//判断接收到A2字节,执行完相关操作后,需要继续等待接收字符串
				LED0_OFF();
				HAL_UART_Receive_IT(&huart1,&RX_dat,1);
		}
	}
}


/* USER CODE END 0 */

在main()函数中添加下列代码:

//在main()函数中添加以下代码:
LED2_ON();
HAL_UART_Transmit(&huart1,Tx_str1,sizeof(Tx_str1),10000);    //向上位机发送“hello world!”
LED2_OFF();
HAL_UART_Receive_IT(&huart1,&Rx_dat,1);                      //启动串口1接收上位机1个字节

运行结果:
串口通信练习结果
注意事项:
(1)在判断完字符串内容,执行完相关操作后,需要继续等待接收字符串,否则只能接收一次。
(2)在stm32f1xx_hal_uart.h头文件调用相关回调函数的过程中,不要看错,否则无法进行相关操作。

点击此处下载串口通信基础练习例程
点击此处下载串口调试助手sscom32

一些关于串行接口的相关知识点与串口通信的参考资料:

串行通信与并行通信概念
三种通信方式——单工、半双工和双工通信
STM32F103ZET6串口通信
STM32F103ZET6 串口

以上内容为本人学习b站小蜜蜂老师基于STM32CubeMX的嵌入式开发基础教程所做的笔记,其中有一些为个人的理解与感悟,如有疏漏之处,敬请大佬指正。

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值