3.串口(UART)

串口理论部分可看51部分:链接

数据帧 = 帧头(2字节,例如AA、BB) + 数据长度(2字节)+ 数据 + CRC16校验(2字节) + 帧尾(2字节)

代码编写

串口一发送命令控制LED灯(PB5、PE5)

LED灯、串口、串口打印浮点数据、串口重定向配置

LED灯配置请看:链接

串口配置:

串口配置

配置中断NVIC(嵌套向量中断控制器)

配置中断NVIC

配置DMA:

配置DMA

Cube IDE中串口打印浮点数据配置方法(参考):进入“Project→Properties”;显示界面如下。按照图片中的设置完成即可!

打印浮点数配置

串口重定向配置:

uint8_t u_buf[256];	//usart.c,24行

#include <stdio.h>	//usart.h,32行
extern uint8_t u_buf[256];	//usart.h,38行
#define printf(...)  HAL_UART_Transmit(&huart1, (uint8_t *)u_buf, sprintf((char*)u_buf, __VA_ARGS__), 0xffff)	//usart.h,39行

轮询方式

缺点:

    必须要等待数据发送完或者等待时间超时,代码才会往下走

    必须要等待数据接收到固定的字节长度,超时,代码才往下走

Cube IDE代码

mian.c

/* USER CODE BEGIN Includes */
#include <string.h>	//26行
#include <stdio.h>	//27
/* USER CODE END Includes */

/* USER CODE BEGIN PV */
uint8_t UART_Recv[5];	//48行
char UART_Str[30];		//49行
/* USER CODE END PV */

//参数1:UART 模块的配置信息的指针,参数2:数据缓冲区的指针,参数3:接收字节长度,参数4:接收超时时间(单位为毫秒)
HAL_UART_Receive(&huart1, UART_Recv, 4, 1000);	//接收数据函数
if(strcmp("LED1", (char *)UART_Recv) == 0)	//字符串比较函数
{
	HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
	memset(UART_Recv,'\0',5);	//替换字符函数,常用于清除指定空间
}

if(!strcmp("LED2", (char *)UART_Recv))	//字符串比较函数
{
	HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
	memset(UART_Recv,'\0',5);
}

sprintf(UART_Str, "%f\n", 666.6);
//参数1:UART 模块的配置信息的指针,参数2:发送的字符串或字符数组,参数3:发送字节长度,参数4:接收超时时间(单位为毫秒)
HAL_UART_Transmit(&huart1, (char *)UART_Str, strlen(UART_Str), 1000);	//发送数据
printf("xinzai\n");	//配置串口重定向后才可使用

中断(IT)方式

Cube IDE代码


HAL_UART_RxCpltCallback(huart);	//stm32f1xx_hal_uart.c,3660行

//stm32f1xx_hal_uart.c,2619行
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)	//中断回调函数

main.c

/* USER CODE BEGIN Includes */
#include <string.h>	//26行
#include <stdio.h>	//27行
/* USER CODE END Includes */

/* USER CODE BEGIN PV */
uint8_t UART_Recv_IT[5];	//48行
char UART_Str[30];	//49行
/* USER CODE END PV */

/* USER CODE BEGIN 2 */
//参数1:UART 模块的配置信息的指针,参数2:数据缓冲区的指针,参数3:接收字节长度
HAL_UART_Receive_IT(&huart1, UART_Recv_IT, 4);	//串口中断接收函数,95行
/* USER CODE END 2 */

//while函数里
sprintf(UART_Str, "%d\n", 666);	//102
HAL_UART_Transmit_IT(&huart1, UART_Str, strlen(UART_Str));	//串口中断发送函数,103
HAL_Delay(1000);	//104

//151行开始
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)	//串口中断接收触发函数
{
	if(huart == &huart1)	//判断传进来的串口是哪个
	{
		if(strcmp("LED1", (char *)UART_Recv_IT) == 0)	//字符串比较函数
		{
		  HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
		  memset(UART_Recv_IT,'\0',5);	//替换字符函数,常用于清除指定空间
		}

		if(!strcmp("LED2", (char *)UART_Recv_IT))	//字符串比较函数
		{
		  HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
		  memset(UART_Recv_IT,'\0',5);
		}
		//因为只能接受一次串口中断,所以在串口中断触发函数需要重新调用
		HAL_UART_Receive_IT(&huart1, UART_Recv_IT, 4);
	}
}
/* USER CODE END 4 */

空闲中断(IDLE) + DMA

不受接收字符长度影响,可以随意接收字符长度并判断

空闲状态:在多个字节传输结束后,通信线路将会维持高电平,这个状态称为空闲状态(没有数据传输时的空闲状态,数据传输刚结束的空闲状态)

空闲中断产生条件:在数据传输过程中,当CPU检测到通信线路处于空闲状态时,且空闲状态的持续时间大于一个字节传输时间时,空闲状态标志IDLE将由硬件置1,产生空闲中断

Cube IDE代码

//stm32f1xx_hal_uart.h,2710行
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)	//空闲中断接收回调函数

main.c

/* USER CODE BEGIN Includes */
#include <string.h>		//27行
/* USER CODE END Includes */

/* USER CODE BEGIN PD */
#define RECV_Size 100	//37行
/* USER CODE END PD */

/* USER CODE BEGIN 2 */
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, UART_Recv_IDLE, RECV_Size);	//空闲中断接收函数,94行
//数据接收RECV_Size一半时会重新触发中断,需要关闭DMA接收中断使能
HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);	//96行
/* USER CODE END 2 */

//150行
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)	//空闲中断接收触发函数
{
	if(huart == &huart1)	//判断传进来的串口是哪个
	{
		if(strcmp("LED1", (char *)UART_Recv_IDLE) == 0)	//字符串比较函数
		{
		  HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
		  memset(UART_Recv_IDLE,'\0',Size);	//替换字符函数,常用于清除指定空间
		}

		if(!strcmp("LED2ON", (char *)UART_Recv_IDLE))	//字符串比较函数
		{
		  //HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
		  HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, 0);
		  memset(UART_Recv_IDLE,'\0',Size);
		}else if(!strcmp("LED2OFF", (char *)UART_Recv_IDLE))
		{
			HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, 1);
			memset(UART_Recv_IDLE,'\0',Size);
		}
		//因为只能接受一次串口中断,所以在串口中断触发函数需要重新调用
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1, UART_Recv_IDLE, RECV_Size);
	}

}
  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

星仔_X

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

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

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

打赏作者

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

抵扣说明:

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

余额充值