完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本项目代码利用HAL库中DMA的中断方式,向串口1发送大量数据,芯片为STM32F407,通过串口助手来接收并显示数据。具体步骤如下: 1、配置MCU的引脚功能。 2、初始化DMA功能。 3、初始化USART1功能。 4、初始化TIM14,使用PWM功能。 5、当按下KEY1键时,开始发送字符串:"爱丽是一个喜欢咬自己尾巴的小笨狗",同时LED灯开始闪烁,串口助手接收数据。 6、传输完毕后,灯光停止闪烁。 7、步骤5、 6 可以重复。 一. STM32CubeMX配置功能参数
按键的引脚为:PE2、PE3、PE4、PA0 PF10控制LED灯,作为电源灯使用。
二. 软件实现 下面的代码只展示需要进行编辑的部分,STM32CubeMX自动生成的就不贴出来了。 1.按键功能实现 key.c文件 #include /** *按键处理函数, *参数mode:0,不支持连续按键;1,支持连续按键 *返回按键值0,无按键按下,1-4,表示1-4键被按下 *次函数有响应优先级,KEY1>KEY2>KEY3>KEY_UP */ uint8_t KEY_SCAN(uint8_t mode) { uint8_t key_up = 1; //按键全部松开的标志 if(mode == 1) key_up = 1; //连续按键模式 if(key_up&&(KEY1 == 0||KEY2 == 0||KEY3 == 0||KEY_UP == 1)) { HAL_Delay(10); //延迟10ms key_up = 0; if(KEY1 == 0) return KEY1_PRES; else if(KEY2 == 0) return KEY2_PRES; else if(KEY3 == 0) return KEY3_PRES; else if(KEY_UP == 1) return KEYUP_PRES; } else { if(KEY1 == 1&& KEY2 ==1 && KEY3 == 1&& KEY_UP == 0) { key_up = 1; } return 0; } } key.h文件 #ifndef _KEY_H_ #define _KEY_H_ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "gpio.h" #define KEY1 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2) //KEY1按键PE2 #define KEY2 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3) //KEY2按键PE3 #define KEY3 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4) //KEY3按键PE4 #define KEY_UP HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) //KEY4按键PA0 #define KEY1_PRES 1 #define KEY2_PRES 2 #define KEY3_PRES 3 #define KEYUP_PRES 4 //函数声明 //按键扫描 uint8_t KEY_SCAN(uint8_t mode); #endif 2.串口功能实现 usart.c /* Includes ------------------------------------------------------------------*/ #include "usart.h" /* USER CODE BEGIN 0 */ /** *引入printf中的fputc函数 *本函数使用USART1串口为输出 *波特率:115200,数据位:8,停止位:1 ,奇偶效验:无 *使用方式:直接拷贝本文件至项目中,然后在需要的地方直接使用printf(). */ #include "stdio.h" /** *定义传输缓存区 */ //#define SEND_BUF_SIZE 14000 //发送数据的长度最好等于sizeof(TEXT_TO_SEND)+2的整数倍 uint8_t SendBuff[SEND_BUF_SIZE]; //发送数据缓冲区 uint8_t TEXT_TO_SEND[] = {"爱丽是一个喜欢咬自己尾巴的小笨狗"} ; /* USER CODE END 0 */ UART_HandleTypeDef huart1; DMA_HandleTypeDef hdma_usart1_tx; /* USART1 init function */ void MX_USART1_UART_Init(void) { 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; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 DMA Init */ /* USART1_TX Init */ hdma_usart1_tx.Instance = DMA2_Stream7; hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4; hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_tx.Init.Mode = DMA_NORMAL; hdma_usart1_tx.Init.Priority = DMA_PRIORITY_MEDIUM; hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 2, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); /* USART1 DMA DeInit */ HAL_DMA_DeInit(uartHandle->hdmatx); /* USART1 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ //为串口打印重写输出函数 int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xfffff); return ch; } //为缓存区填充数据,并在每句字符串后加入 void Write_Send_Buf(void) { uint16_t i,t=0,j,mask=0; j = sizeof(TEXT_TO_SEND); for(i=0;i if(t>=j) //加入换行符 { if(mask) { SendBuff = 0x0a; //加入换行的ASCII码 t = 0; //重新开始计数,开始重复填写数据 } else { SendBuff = 0x0d; //加入回车的ASCII码 mask++; } } else //复制TEXT_TO_SEND语句 { mask = 0; SendBuff = TEXT_TO_SEND[t]; t++; } } } /* USER CODE END 1 */ usart.h文件 /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __usart_H #define __usart_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "main.h" /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ extern UART_HandleTypeDef huart1; /* USER CODE BEGIN Private defines */ extern DMA_HandleTypeDef hdma_usart1_tx; #define SEND_BUF_SIZE 14000 //发送数据的长度最好等于sizeof(TEXT_TO_SEND)+2的整数倍 /* USER CODE END Private defines */ void MX_USART1_UART_Init(void); /* USER CODE BEGIN Prototypes */ //传输数据填充 void Write_Send_Buf(void); /* USER CODE END Prototypes */ #ifdef __cplusplus } #endif #endif /*__ usart_H */ 3.PWM功能实现 tim.c文件 /* Includes ------------------------------------------------------------------*/ #include "tim.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ TIM_HandleTypeDef htim14; /* TIM14 init function */ void MX_TIM14_Init(void) { TIM_OC_InitTypeDef sConfigOC = {0}; htim14.Instance = TIM14; htim14.Init.Prescaler = 840-1; htim14.Init.CounterMode = TIM_COUNTERMODE_UP; htim14.Init.Period = 8000-1; htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim14) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim14) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 4000-1; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } HAL_TIM_MspPostInit(&htim14); } void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM14) { /* USER CODE BEGIN TIM14_MspInit 0 */ /* USER CODE END TIM14_MspInit 0 */ /* TIM14 clock enable */ __HAL_RCC_TIM14_CLK_ENABLE(); /* USER CODE BEGIN TIM14_MspInit 1 */ /* USER CODE END TIM14_MspInit 1 */ } } void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(timHandle->Instance==TIM14) { /* USER CODE BEGIN TIM14_MspPostInit 0 */ /* USER CODE END TIM14_MspPostInit 0 */ __HAL_RCC_GPIOF_CLK_ENABLE(); /**TIM14 GPIO Configuration PF9 ------> TIM14_CH1 */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF9_TIM14; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); /* USER CODE BEGIN TIM14_MspPostInit 1 */ /* USER CODE END TIM14_MspPostInit 1 */ } } void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM14) { /* USER CODE BEGIN TIM14_MspDeInit 0 */ /* USER CODE END TIM14_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM14_CLK_DISABLE(); /* USER CODE BEGIN TIM14_MspDeInit 1 */ /* USER CODE END TIM14_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ 4.GPIO引脚功能实现 gpio.c /* Includes ------------------------------------------------------------------*/ #include "gpio.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /*----------------------------------------------------------------------------*/ /* Configure GPIO */ /*----------------------------------------------------------------------------*/ /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI */ void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); /*Configure GPIO pins : PE2 PE3 PE4 */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /*Configure GPIO pin : PtPin */ GPIO_InitStruct.Pin = LED2_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : PA0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } 5.中断功能实现 stm32f4xx_it.c文件,部分代码 /** * @brief This function handles USART1 global interrupt. */ void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ } /** * @brief This function handles DMA2 stream7 global interrupt. */ void DMA2_Stream7_IRQHandler(void) { /* USER CODE BEGIN DMA2_Stream7_IRQn 0 */ /* USER CODE END DMA2_Stream7_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_usart1_tx); /* USER CODE BEGIN DMA2_Stream7_IRQn 1 */ /* USER CODE END DMA2_Stream7_IRQn 1 */ } /* USER CODE BEGIN 1 */ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { //传输完成后关闭串口DMA uint8_t retu_status; retu_status = HAL_UART_DMAStop(huart); printf("中断方式数据发送完成,DMA停止状态:0x%02xrn",retu_status); //关闭DMA传输 HAL_TIM_PWM_Stop(&htim14,TIM_CHANNEL_1); } /* USER CODE END 1 */ 6.主函数 main.c文件 /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "dma.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define LED2_Pin GPIO_PIN_10 #define LED2_GPIO_Port GPIOF extern uint8_t SendBuff[SEND_BUF_SIZE]; uint8_t SendBuff_2[SEND_BUF_SIZE]; /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ uint8_t key_pres = 0; //按键标志 uint8_t retu_status; /* 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_TIM14_Init(); /* USER CODE BEGIN 2 */ printf("程序开始运行……rn"); //填充传输所需的数据 Write_Send_Buf(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { //Key_LED(); //HAL_Delay(20); key_pres = KEY_SCAN(0); if(key_pres == KEY1_PRES) //按键1被按下 { //启动中断DMA方式进行传输 printf("中断DMA方式数据传输启动……rn"); retu_status = HAL_UART_Transmit_DMA(&huart1, (uint8_t *)SendBuff, SEND_BUF_SIZE); HAL_TIM_PWM_Start(&htim14,TIM_CHANNEL_1); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_Delay(20); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /**Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 4; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /**Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %drn", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ 当发送完成后,中断调用了回调函数,HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart),执行回调函数中的代码。当再次按下KEY1键时,重复执行WHILE循环中的代码。 |
|
|
|
只有小组成员才能发言,加入小组>>
3314 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9059 浏览 16 评论
4088 浏览 18 评论
1180浏览 3评论
605浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
599浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2335浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1896浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 21:02 , Processed in 1.108469 second(s), Total 49, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号