文章目录
前言
一、实验目的
使用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