完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本文主要记录UART DMA操作方式,同时对STM32F103 UART驱动抽象出来实现帧数据接收
1、MDK工程目录(创建工程方式略) main.c内容如下 运行后的结果是UART收到数据立即通过TX发送出去,同时LED状态反转一次 #include 《stdio.h》 #include “stm32f10x.h” #include “platform.h” unsigned char led_count = 0; void LED_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } void uart_recv_str(UART_TypeDef *p, uint8_t *pbuf, uint16_t len){ UART_ApiStructure.send_str(p, pbuf, len); GPIO_WriteBit(GPIOB, GPIO_Pin_9, (++led_count & 0x01) ? Bit_SET : Bit_RESET); } int main(void){ LED_Init(); UART_ApiStructure.config(&UART_TypeDef_param, uart_recv_str); UART_ApiStructure.send_str(&UART_TypeDef_param, (uint8_t *)“uart init okrn”, 14); for(;;){} } uart.h #ifndef __UART_H #define __UART_H typedef void (*pfunc_uart_gpio_init)(void); /** * @addtogroup 串口参数定义 * @{ */ /** UART 数据处理设置 */ typedef struct{ uint8_t *tx_buf; /*!《 发送数据缓存 */ uint8_t *rx_buf; /*!《 接收数据缓存 */ uint16_t tx_buf_len_max; /*!《 发送数据最大缓存空间大小 */ uint16_t rx_buf_len_max; /*!《 接收数据最大缓存空间大小 */ uint16_t rx_tail; /*!《 接收数据缓存尾标识 */ uint16_t rx_head; /*!《 接收数据缓存头标识 */ }UART_UserParam; /** DMA 参数设置 */ typedef struct{ uint8_t irq_tx; /*!《 发送通道中断号 */ uint8_t irq_rx; /*!《 接收通道中断号 */ DMA_Channel_TypeDef *channel_tx; /*!《 发送通道 */ DMA_Channel_TypeDef *channel_rx; /*!《 接收通道 */ uint32_t TX_IT_FLAG_TCx; /*!《 发送完成中断标志 */ uint32_t RX_IT_FLAG_TCx; /*!《 接收完成中断标志 */ }DMA_Param; /** UART 参数设置 */ typedef struct{ uint32_t baud; /*!《 波特率参数 */ pfunc_uart_gpio_init pfunc_gpio_init; /*!《 指向串口GPIO初始化函数指针 */ USART_TypeDef* USARTx; /*!《 使用串口号 */ uint8_t USARTx_IRQn; /*!《 串口接收中断号 */ DMA_Param *DMAx; /*!《 DMA参数指针 */ UART_UserParam *user; /*!《 UART数据处理指针 */ }UART_TypeDef; /** * @} */ /** * @addtogroup API 接口定义 */ typedef void (*pfunc_uart_rsend_str)(UART_TypeDef *p, uint8_t *pbuf, uint16_t len); typedef uint8_t (*pfunc_uart_config)(UART_TypeDef *p, pfunc_uart_rsend_str cb); typedef struct{ pfunc_uart_config config; /*!《 初始化串口 */ pfunc_uart_rsend_str send_str; /*!《 发送数据 */ pfunc_uart_rsend_str recv_cb; /*!《 接收数据 */ }UART_ApiDef; extern UART_ApiDef UART_ApiStructure; /** * @} */ #ifdef USE_PRINTF extern int __printf(const char *fmt, 。..); #else #define __printf(。..) #endif #endif uart.c /** * @file uart.c USART 驱动程序 * * @author T0213-ZH * @date 2018.06.13 */ #include “platform.h” /** * @brief 配置USART参数 * @param p: 指向串口参数指针 * @param cb: 用于接收数据回调函数指针 * * @retval 0-成功,1-已初始过了,2-未设置GPIO初始函数, 3-串口组参数不匹配 */ static uint8_t uart_init(UART_TypeDef *p, pfunc_uart_rsend_str cb){ USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; //if(g_uart_param) return 1; if(!p-》pfunc_gpio_init) return 2; if(cb) UART_ApiStructure.recv_cb = cb; //g_uart_param = p; p-》pfunc_gpio_init(); if(p-》USARTx == USART1){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); }else if(p-》USARTx == USART2){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); }else if(p-》USARTx == USART3){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); }else{ return 3; } USART_InitStructure.USART_BaudRate = p-》baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(p-》USARTx, &USART_InitStructure); USART_Cmd(p-》USARTx, ENABLE); USART_ClearFlag(p-》USARTx, USART_FLAG_TC); //注:避免首字符丢掉现象 USART_ITConfig(p-》USARTx, USART_IT_IDLE, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = p-》USARTx_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_DMACmd(p-》USARTx, USART_DMAReq_Tx, ENABLE); USART_DMACmd(p-》USARTx, USART_DMAReq_Rx, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //DMA TX Config DMA_DeInit(p-》DMAx-》channel_tx); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&p-》USARTx-》DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)p-》user-》tx_buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = p-》user-》tx_buf_len_max; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(p-》DMAx-》channel_tx, &DMA_InitStructure); //DMA_Cmd(p-》DMAx-》channel_tx, ENABLE) NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = p-》DMAx-》irq_tx; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //DMA RX Config DMA_DeInit(p-》DMAx-》channel_rx); DMA_InitStructure.DMA_BufferSize = p-》user-》rx_buf_len_max;; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)p-》user-》rx_buf; DMA_Init(p-》DMAx-》channel_rx, &DMA_InitStructure); DMA_Cmd(p-》DMAx-》channel_rx, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = p-》DMAx-》irq_rx; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(p-》DMAx-》channel_tx, DMA_IT_TC, ENABLE); DMA_ITConfig(p-》DMAx-》channel_rx, DMA_IT_TC, ENABLE); return 0; } /** * @brief 发送数据接口 * @param p: 指向发送数据缓存指针 * @param len: 数据长度 * * @retval none */ static void uart_send_str(UART_TypeDef *p, uint8_t *pbuf, uint16_t len){ if(!len) return; uint16_t i; for(i=0; i《len; i++){ p-》user-》tx_buf[i] = *pbuf++; } while(DMA_GetFlagStatus(p-》DMAx-》TX_IT_FLAG_TCx) == SET); DMA_SetCurrDataCounter(p-》DMAx-》channel_tx, len); DMA_Cmd(p-》DMAx-》channel_tx, ENABLE); } /** * @brief 接收数据接口,中断触发 * * @retval none */ static void uart_recv_len(UART_TypeDef *p){ p-》user-》rx_head = p-》user-》rx_buf_len_max - DMA_GetCurrDataCounter(p-》DMAx-》channel_rx); if(p-》user-》rx_tail != p-》user-》rx_head){ uint16_t i = 0; uint8_t buf[p-》user-》rx_buf_len_max]; uint16_t head = p-》user-》rx_head; do{ buf[i++] = p-》user-》rx_buf[p-》user-》rx_tail++]; if(p-》user-》rx_tail == p-》user-》rx_buf_len_max) p-》user-》rx_tail = 0; }while(p-》user-》rx_tail != head); if(UART_ApiStructure.recv_cb){ UART_ApiStructure.recv_cb(p, buf, i); } //uart_send_str(buf, i); } } /** * @brief UART 接口函数 */ UART_ApiDef UART_ApiStructure = { .config = uart_init, /*!《 指向串口参数配置接口函数指针 */ .send_str = uart_send_str, /*!《 指向串口发送字符串接口函数指针 */ .recv_cb = 0, }; void uart_tx_irq(UART_TypeDef *p){ if(DMA_GetITStatus(p-》DMAx-》TX_IT_FLAG_TCx) == SET){ DMA_Cmd(p-》DMAx-》channel_tx, DISABLE); DMA_ClearITPendingBit(p-》DMAx-》TX_IT_FLAG_TCx); } } void uart_rx_irq(UART_TypeDef *p){ if(DMA_GetITStatus(p-》DMAx-》RX_IT_FLAG_TCx) == SET){ DMA_ClearITPendingBit(p-》DMAx-》RX_IT_FLAG_TCx); } } void uart_irq(UART_TypeDef *p){ if(USART_GetITStatus(p-》USARTx, USART_IT_IDLE) != RESET){ USART_ReceiveData(p-》USARTx); USART_ClearITPendingBit(p-》USARTx, USART_IT_IDLE); uart_recv_len(p); } } #ifdef USE_PRINTF int __fputc(unsigned char ch, unsigned char *f){ /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ USART_SendData(USART1, (uint8_t) ch); /* Loop until the end of transmission */ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch; } #endif platform.c #include “platform.h” extern void uart_tx_irq(UART_TypeDef *p); extern void uart_rx_irq(UART_TypeDef *p); extern void uart_irq(UART_TypeDef *p); void USART_GpioInit(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); } /** * @addtogroup * @{ */ #define UART_TX_BUF_MAX (256) #define UART_RX_BUF_MAX (256) uint8_t uart_tx_buf[UART_TX_BUF_MAX]; uint8_t uart_rx_buf[UART_RX_BUF_MAX]; DMA_Param dma_param = { .irq_tx = DMA1_Channel4_IRQn, .irq_rx = DMA1_Channel5_IRQn, .channel_tx = DMA1_Channel4, .channel_rx = DMA1_Channel5, .TX_IT_FLAG_TCx = DMA1_IT_TC4, .RX_IT_FLAG_TCx = DMA1_IT_TC5, }; /** UART */ UART_UserParam uart_param = { .tx_buf = uart_tx_buf, .rx_buf = uart_rx_buf, .tx_buf_len_max = UART_TX_BUF_MAX, .rx_buf_len_max = UART_RX_BUF_MAX, .rx_tail = 0, .rx_head = 0, }; /** UART */ UART_TypeDef UART_TypeDef_param = { .baud = 115200, .pfunc_gpio_init = USART_GpioInit, .USARTx = USART1, .USARTx_IRQn = USART1_IRQn, .DMAx = &dma_param, .user = &uart_param, }; void DMA1_Channel4_IRQHandler(void){ uart_tx_irq(&UART_TypeDef_param); } void DMA1_Channel5_IRQHandler(void){ uart_rx_irq(&UART_TypeDef_param); } void USART1_IRQHandler(void){ uart_irq(&UART_TypeDef_param); } /** * @} */ |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1641 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1562 浏览 1 评论
988 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
691 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1608 浏览 2 评论
1869浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
655浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
525浏览 3评论
541浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
514浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-26 13:11 , Processed in 0.789133 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号