首先打开时钟,本项目使用的是HSE。
打开串口,DMA,中断
打开定时器以及定时器中断,因为我测试的数据量较大,定时器设置的5ms,具体计算如下。
这里我们 arr=4799 psc=49 Tclk=48Mhz Tout = (4800*50)/48000000 = 5ms。可以根据实际情况,数据量大小来调整定时时间。
生成工程,不会的可以去查一下怎么生成,很多教程。
需要添加的代码如下
/*
这些是串口通信所用到的变量
*/
#define USART_RXC_MAX 6000 //定义最大接收字节数 6000
#define USART_TXC_MAX 6000 //定义最大发送字节数 6000
#define USART_RXC_SIZE 200 //定义最大临时接收字节数 200
#define USART_TXC_SIZE 200 //定义最大临时发送字节数 200
typedef struct {
uint8_t USART_MAX[USART_RXC_MAX]; //接收最大缓冲区
uint8_t USART_BUF[USART_RXC_SIZE]; //接收临时缓冲区
volatile uint16_t USART_STA; //接收标志位
volatile uint16_t USART_SIZE; //接收数据量
DMA_HandleTypeDef hdma_usart1_rx; //DMA
}USART_RX;
typedef struct {
uint8_t USART_MAX[USART_TXC_MAX]; //发送最大缓冲区
uint8_t USART_BUF[USART_TXC_SIZE]; //发送临时缓冲区
volatile uint16_t USART_STA; //发送标志位
volatile uint16_t USART_SIZE; //发送数据量
DMA_HandleTypeDef hdma_usart1_tx; //DMA
}USART_TX;
typedef struct __USART_CUSTOM
{
UART_HandleTypeDef huart;
USART_RX USART_RX;
USART_TX USART_TX;
}USART_CUSTOM;
extern USART_CUSTOM huart1;
/*
这些是中断中所要更改的
#include "stm32l4xx_it.c"
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1.huart);
/* USER CODE BEGIN USART1_IRQn 1 */
HAL_UARTEx_ReceiveToIdle_DMA(&huart1.huart,huart1.USART_RX.USART_BUF,USART_RXC_SIZE); //重新开启串口空闲中断和DMA接收,一定要放在这里
/* USER CODE END USART1_IRQn 1 */
}
/*
这些是相关回调函数
*/
//这个我放倒了tim.c里
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&htim1))
{
huart1.USART_RX.USART_STA = 1;
HAL_TIM_Base_Stop_IT(&htim1);//关闭定时
}
}
//这些我放倒了usart.c里面
uint16_t cnt;
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) //接收中断回调函数
{
if (huart->Instance == USART1)
{
if(huart1.USART_RX.USART_STA == 0){
__HAL_TIM_CLEAR_FLAG(&htim1,TIM_FLAG_UPDATE);
HAL_TIM_Base_Start_IT(&htim1);
}
cnt = USART_RXC_SIZE - __HAL_DMA_GET_COUNTER(&huart1.USART_RX.hdma_usart1_rx);
if((cnt+huart1.USART_RX.USART_SIZE) < USART_RXC_MAX){
memcpy(&huart1.USART_RX.USART_MAX[huart1.USART_RX.USART_SIZE],huart1.USART_RX.USART_BUF,cnt);
huart1.USART_RX.USART_SIZE += cnt;
__HAL_TIM_SET_COUNTER(&htim1,0);
}
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) //发送完成回调函数
{
if(huart->Instance==USART1)
{
memset(huart1.USART_RX.USART_MAX, 0, sizeof(huart1.USART_RX.USART_MAX));
huart1.USART_RX.USART_SIZE = 0;
huart1.USART_RX.USART_STA = 0;
}
}
/*
这些是main.c里面的
*/
void huart1_initialize() //串口自定义相关变量的结构体初始化
{
huart1.USART_RX.USART_SIZE = 0;
huart1.USART_RX.USART_STA = 0;
huart1.USART_TX.USART_SIZE = 0;
huart1.USART_TX.USART_STA = 0;
}
//重要提醒//
//这个我放到了void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)函数里面的最后面,可以根据各位喜好,放到main函数内或者其它可行的地方都可以。
__HAL_UART_ENABLE_IT(&huart1.huart, UART_IT_IDLE); /* 开启串口空闲中断 */
//主函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
huart1_initialize();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if(huart1.USART_RX.USART_STA == 1)
{
HAL_UART_Transmit_DMA(&huart1.huart,huart1.USART_RX.USART_MAX, huart1.USART_RX.USART_SIZE); //将接受到的数据再发回上位机
while(__HAL_UART_GET_FLAG(&huart1.huart, UART_FLAG_TC) == RESET){}///<等待发送完成
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
实现效果,这里我一次性发送的是5000字节。