飞控开发日志——F405完善串口模块程序(根据F4开发指南HAL库版本)

 

文章目录

 


前言

 

一、实验目的

使用STM32F4的串口来发送和接收数据。

例程实现如下功能: STM32通过串口和上位机的对话,STM32F407在收到上位机发过来的字符串后,原原本本的返回给上位机。

   电脑/F405→F407→电脑/F405

已经测试的线路是: F405→F407→电脑

现在要测试F405是否也收到了它出去的数据 

修改程序为:  电脑→F407→F405→F407→电脑  只有F405接收到了数据 才发送一组数据

问题:那么没接收到数据的时候如何处理?(参考一下MiniFly)

                

现在写一个程序 如果接受到了数据 就发送一个标志 给F407 F407又接收到了这个 如果接受到了这个标志位就发送给电脑

F405应该实现的功能:能够接收到串口数据 并且发送  目前只实现了接收功能。

 

二、串口设置的步骤

串口设置的一般步骤可以总结为如下几个步骤:
1) 串口时钟使能,GPIO 时钟使能。
2) 设置引脚复用器映射:调用 GPIO_PinAFConfig 函数。
3) GPIO 初始化设置:要设置模式为复用功能。
4) 串口参数初始化:设置波特率,字长,奇偶校验等参数。
5) 开启中断并且初始化 NVIC,使能中断(如果需要开启中断才需要这个步骤)。
6) 使能串口。
7) 编写中断处理函数:函数名格式为 USARTxIRQHandler(x 对应串口号)。
下面,我们就简单介绍下这几个与串口基本配置直接相关的几个 HAL 库函数。这些函数
和定义主要分布在 stm32f4xx_hal_usart.h 和 stm32f4xx_hal_usart.c 文件中

1.初始化的函数实现(GPIO设置及复用之后)

①在usart.c 里面定义了一个串口句柄  UART_HandleTypeDef huart1   ,这个句柄通常只设置Insatance USART的具体地址, 以及Init 串口模式

②在main函数里面初始化串口的时候 MX_USART1_UART_Init   给这个句柄的各个成员变量赋值

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  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;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;

//Cube生成的代码好像没有开启接收中断   没有以下两句

HAL_UART_Init(&UART1_Handler); //HAL_UART_Init()会使能 UART1
HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);

③随后就可以通过这个句柄 使用各个函数

2.配置过程

1.在main函数 code0 定义了 一个接收缓存数组 uint8_t  100

2.在code2  初始化过后 使能了串口中断 并发送了提示信息

3.在code4 定义了回调函数  实现将接收到的数据发送

但这个回调函数写的有点简单 并不能判断接收到了多少字符 只能接收到一定字符后固定发送  所以会出现发送不完整或者数据过短不能发送的问题。

修改了回调函数 但是在extern 变量那里卡了很久 是因为 extern 只是在h文件里面声明并不是定义,在C文件中应该定义

3.最终配置

  /* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
  /* USER CODE END 2 */

usart.h 文件

/* USER CODE BEGIN Private defines */
#define EN_USART1_RX 			1		
#define USART_REC_LEN  			200  	
extern uint8_t  USART_RX_BUF[USART_REC_LEN]; 
extern uint16_t USART_RX_STA;         		
#define RXBUFFERSIZE   1 
extern uint8_t aRxBuffer[RXBUFFERSIZE];
/* USER CODE END Private defines */

/* USER CODE BEGIN Prototypes */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
/* USER CODE END Prototypes */

/* USER CODE END Private defines */

usart.c 文件

/* USER CODE BEGIN 0 */

#include "stdio.h"

/* USER CODE END 0 */


/* USER CODE BEGIN 1 */

uint8_t USART_RX_BUF[USART_REC_LEN];     
uint16_t USART_RX_STA=0;      
uint8_t aRxBuffer[RXBUFFERSIZE];

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		//HAL_UART_Transmit(&huart1,(uint8_t*)aRxBuffer,1,1000);
		if((USART_RX_STA&0x8000)==0)
		{
			if(USART_RX_STA&0x4000)
			{
				if(aRxBuffer[0]!=0x0a)
				{
					USART_RX_STA=0;
				}
				else 
				{
					USART_RX_STA|=0x8000;
				}
			}
			else 
			{	
				if(aRxBuffer[0]==0x0d)
				{
					USART_RX_STA|=0x4000;
				} 
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;
				}		 
			}
		}
	}
	HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE);
}




#if SYSTEM_SUPPORT_OS
#include "includes.h"					  
#endif

#ifdef __GNUC__

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif

PUTCHAR_PROTOTYPE

{

HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);

return ch;

}

/* USER CODE END 1 */

总结

串口调试助手不过不勾选16进制发送的话 他会把空格也看做一个字符为20            并不是发送多个位

如果是勾选16进制发送 那么不管你空不空空格 都是两位发送一次 最好 空  

勾选了发送新行 就会再发送一个0D 0A

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F405芯片上,串口6的DMA接收可以通过标准库来实现。以下是一个示例代码,演示了如何使用DMA接收串口数据: ```c #include "stm32f4xx.h" #include "stm32f4xx_hal.h" #define UART_RX_BUFFER_SIZE 64 UART_HandleTypeDef huart6; DMA_HandleTypeDef hdma_usart6_rx; uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE]; uint8_t uart_rx_index = 0; void configure_uart_dma(void) { // 配置串口6 huart6.Instance = USART6; huart6.Init.BaudRate = 115200; huart6.Init.WordLength = UART_WORDLENGTH_8B; huart6.Init.StopBits = UART_STOPBITS_1; huart6.Init.Parity = UART_PARITY_NONE; huart6.Init.Mode = UART_MODE_TX_RX; huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart6.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&huart6); // 配置DMA hdma_usart6_rx.Instance = DMA2_Stream1; hdma_usart6_rx.Init.Channel = DMA_CHANNEL_5; hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart6_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart6_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart6_rx.Init.Mode = DMA_CIRCULAR; hdma_usart6_rx.Init.Priority = DMA_PRIORITY_HIGH; hdma_usart6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&hdma_usart6_rx); // 将DMA与UART6的RX通道关联 __HAL_LINKDMA(&huart6, hdmarx, hdma_usart6_rx); // 启动DMA传输 HAL_UART_Receive_DMA(&huart6, uart_rx_buffer, UART_RX_BUFFER_SIZE); } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // 处理接收到的数据 // 重新启动DMA传输 HAL_UART_Receive_DMA(&huart6, uart_rx_buffer, UART_RX_BUFFER_SIZE); } ``` 在上面的代码中,我们首先定义了一个包含64个字节的UART接收缓冲区。然后,我们调用`configure_uart_dma`函数来配置UART和DMA。在该函数中,我们使用HAL库的函数来初始化UART(USART6)和DMA(DMA2_Stream1),并将DMA与UART的RX通道关联起来。我们还启用了DMA的循环模式,以便在接收完整个缓冲区后,DMA可以自动重新开始传输。最后,我们通过调用`HAL_UART_Receive_DMA`函数来启动DMA传输。 当DMA传输完成时,将自动触发中断并调用`HAL_UART_RxCpltCallback`函数。在该函数中,我们首先处理接收到的数据(可以在这里添加自定义的处理操作),然后重新启动DMA传输。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值