完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
前言
STM32CubeMX_环境搭建_GPIO_外部中断 STM32CubeMX_定时器中断_PWM 前两节简单的总结了GPIO, EXTI, TIMER的相关用法, 本节总结一下STM32串口的用法, 依然是原理性的东西不多讲, 直接开干. 先看下缩写:
LPUART是新出的 STM32G/H/WB系列 和 部分STM32L系列 才有的, 顾名思义, 低功耗, 允许只使用32.768K的LSE作为时钟达到9600bps通讯速率, 超级省电; 但当时钟源是100MHz时, 可以达到33.3Mbps通讯速率, 可谓上限极高. 此外, 支持多机通信, 单线半双工通信等. 详细可参考 en.STM32G4-Peripheral-LPUART_interface_LPUART.pdf . LPUART的例子暂略, 通用用法大致一样. HAL库函数的操作方式有轮询, 中断和DMA3种, 轮询是Blocking mode, 中断和DMA是 Non-Blocking mode. 注意后缀很好区分, 如发送函数: HAL_UART_Transmit() HAL_UART_Transmit_IT() HAL_UART_Transmit_DMA() 补充一点, 最近几年出的片子的UART/USART功能也越来越完善, 增加了诸如自动波特率, 数据反转, TX/RX引脚互换等亮眼操作. 暂且不表, 先从 NUCLEO-F767ZI 的串口开始吧. STM32CubeMX新建F767工程 步骤如下:
UART配置 Pinout & Configuration -> Connectivity -> USART3 -> Mode选择异步Asynchronous, 波特率之类的就默认115200-8-N-1: 然后发现图中的引脚居然是PB10, PB11, 而不是原理图的PD8/PD9: 不要慌, 鼠标悬停提示 生成代码 Project Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM. Project Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral 点击右上角 GENERATE CODE 按钮生成代码, 打开工程. Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置Debug为ST-link Debugger, 点击Setting -> Flash Download -> 勾选Reset and Run, 这样下载后可以自动复位运行. 如有疑问, 仍然去参考 STM32CubeMX_环境搭建_GPIO_外部中断 一节. 串口发送 主要是用HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) 这个函数进行发送, main.c中补充代码发送字符串和十六进制: /* USER CODE BEGIN 2 */ uint8_t str_arr[] = "UART Example!nr"; uint8_t hex_arr[] = {0x00, 0x02, 0x03, 0x04, 0x05, 0x06}; uint8_t arr_length = 0; arr_length = sizeof(str_arr) / sizeof(*str_arr); HAL_UART_Transmit(&huart3, str_arr, arr_length, 100); HAL_Delay(1000); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ ++hex_arr[0]; arr_length = sizeof(hex_arr) / sizeof(*hex_arr); HAL_UART_Transmit(&huart3, hex_arr, arr_length, 100); HAL_Delay(1000); } /* USER CODE END 3 */ 选择板子的虚拟串口, 115200波特率, 打开串口调试助手, 编译下载程序, 发现接收到UART Example 信息, 切换HEX显示, 符合预期: printf支持 随便找个地方添加以下代码: #ifdef __GNUC__ /* With GCC, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ /** * @brief Retargets the C library printf function to the USART. * @param None * @retval None */ PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */ HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF); return ch; } 要问哪来的, 官方的Example -> UART_Printf 复制过来的, 同时, 别忘添加头文件: #include 然后就可以愉快的使用printf了: uint8_t str_arr[] = "print Example!"; uint8_t hex_arr[] = {0x00, 0x02, 0x03, 0x04, 0x05, 0x06}; printf("printf test: nr"); printf("string array: %snr", str_arr); printf("hex: hex_arr[1] = 0x%02xnr", hex_arr[1]); printf("num one: %dnr", 1u); printf("pi = %.3fnr", 3.1415926f); 打印结果: 串口接收中断 关闭Keil, 回到STM32CubeMX, NVIC中勾选 USART3 global interrupt, 优先级不设置么, 默认(0, 0): 点击 GENERATE CODE 重新生成代码, 打开工程, 补充代码: /* USER CODE BEGIN PD */ #define RXBUFFERSIZE 28 /* USER CODE END PD */ /* USER CODE BEGIN PV */ uint8_t aRxBuffer[RXBUFFERSIZE]; //Buffer used for reception __IO ITStatus g_uart3_rx_status = RESET; /* USER CODE END PV */ /* USER CODE BEGIN 0 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == huart3.Instance) { //if(huart == &huart3) g_uart3_rx_status = SET; } } /* USER CODE END 0 */ /* USER CODE BEGIN 2 */ HAL_UART_Receive_IT(&huart3, (uint8_t *)aRxBuffer, RXBUFFERSIZE); /* USER CODE END 2 */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if(g_uart3_rx_status == SET) { g_uart3_rx_status = RESET; HAL_UART_Transmit(&huart3, aRxBuffer, RXBUFFERSIZE, 20); HAL_UART_Receive_IT(&huart3, (uint8_t *)aRxBuffer, RXBUFFERSIZE); } } /* USER CODE END 3 */ 100ms间隔发送26个英文字母加回车换行是28字节, 发送间隔20ms以上10字节收发没有什么问题, 再快就可能出问题卡死了: 这种对于 定长字符串的接收 还是可以用的, 对于 不定长字符串的接收, 一般会有明显的结束标志, 比如回车换行, 典型的就是AT指令的接收, 可以设置1字节接收中断, 来一个字节存一个字节到一个数组里, 然后在中断里判断是否是结束标志如回车换行或者特殊字符之类的即可 . DMA空闲中断 上面的接收方式使用起来还是很抓狂的, 可能会出现卡死之类, 是没有调校好的结果. 好在STM32提供了空闲中断, 当字节流不连续时, 总会出现串口总线空闲的时候, 出现空闲就表示一帧数据接收完毕, 这个时候来个中断岂不美哉, 嗯, DMA空闲中断就是这么好使. 对于定长不定长字符串的接收通通好用. 关掉Keil, 回到STM32CubeMX, 原来的工程不要了, 新建一个工程, 时钟引脚配置之类的步骤略, 到USART3的界面, 找到DMA Setting, 点击 Add 按钮添加USART3_RX的DMA, 同样添加USART3_TX的DMA: 然后到NVIC里面勾选中断, 优先级可以设置低一点: 点击生成代码, 打开工程, keil别忘记Debug里面勾选Reset and Run. main.h添加代码: /* USER CODE BEGIN Private defines */ #define RXBUFFERSIZE 50 /* USER CODE END Private defines */ main.c添加代码: /* USER CODE BEGIN PV */ uint8_t aRxBuffer[RXBUFFERSIZE]; /* USER CODE END PV */ /* USER CODE BEGIN 2 */ __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); HAL_UART_Receive_DMA(&huart3, (uint8_t *)aRxBuffer, RXBUFFERSIZE); /* USER CODE END 2 */ stm32f7xx_it.c中: /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ extern uint8_t aRxBuffer[]; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ void UART_RxIdleCallback(UART_HandleTypeDef *huart); /* USER CODE END PFP */ //void USART3_IRQHandler(void) /* USER CODE BEGIN USART3_IRQn 1 */ UART_RxIdleCallback(&huart3); /* USER CODE END USART3_IRQn 1 */ /* USER CODE BEGIN 1 */ void UART_RxIdleCallback(UART_HandleTypeDef *huart) { uint32_t temp; if(huart == &huart3) { if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE) != RESET ) { __HAL_UART_CLEAR_IDLEFLAG(&huart3); temp = huart3.Instance->ISR; temp = huart3.Instance->ICR; temp = huart3.Instance->RDR; HAL_UART_DMAStop(&huart3); temp = hdma_usart3_rx.Instance->NDTR; //DMA stream x number of data register HAL_UART_Transmit_DMA(&huart3, aRxBuffer, RXBUFFERSIZE-temp); HAL_UART_Receive_DMA(&huart3, aRxBuffer, RXBUFFERSIZE); } } } /* USER CODE END 1 */ 编译下载, 打开串口调试助手, 可以看到只要长度不超过RXBUFFERSIZE定义的字节, 都会自动回传: |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1792 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1626 浏览 1 评论
1094 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
732 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1682 浏览 2 评论
1943浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
744浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
578浏览 3评论
601浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
563浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 19:57 , Processed in 0.722843 second(s), Total 81, Slave 64 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号