/** ************************************************************************************************ * @文件 : uart3.c * @作者 : 樊春春 * @版本 : V1.0 * @时间 : 2022/05/31 20:15:29 * @邮箱 : fanchcho@gmail.com * @说明 : 485底层驱动 ************************************************************************************************ **/ #include "uart3.h" static uint8_t uart3_tx_buf[UART3_TX_LEN] = {0}; static uint8_t uart3_rx_buf[UART3_REC_LEN] = {0}; UartFrame_TypeDef Uart3FrameStruct[UART3_MAX_MSG_NUM]; extern OS_EVENT *uart3_mbox; void uart3_nvic_config(void) { NVIC_InitTypeDef NVIC_InitStructure; // Usart3 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; //串口3中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能 NVIC_Init(&NVIC_InitStructure); } void uart3_dma_init(void) { DMA_InitTypeDef DMA_InitStructure; if ((uint32_t)UART3_DMA_TXCH > (uint32_t)DMA2) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // DMA2时钟使能 } else { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // DMA1时钟使能 } DMA_DeInit(UART3_DMA_TXCH); while (DMA_GetCmdStatus(UART3_DMA_TXCH) != DISABLE) { } //等待DMA可配置 /* 配置 DMA Stream */ DMA_InitStructure.DMA_Channel = UART3_DMA; //通道选择 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR; // DMA外设地址 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)uart3_tx_buf; // DMA 存储器0地址 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //存储器到外设模式 DMA_InitStructure.DMA_BufferSize = UART3_TX_LEN; //数据传输量 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度:8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 使用普通模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //中等优先级6 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发单次传输 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发单次传输 DMA_Init(UART3_DMA_TXCH, &DMA_InitStructure); //初始化DMA Stream if ((uint32_t)UART3_DMA_RXCH > (uint32_t)DMA2) //得到当前stream是属于DMA2还是DMA1 { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // DMA2时钟使能 } else { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // DMA1时钟使能 } DMA_DeInit(UART3_DMA_RXCH); while (DMA_GetCmdStatus(UART3_DMA_RXCH) != DISABLE) { } //等待DMA可配置 /* 配置 DMA Stream */ DMA_InitStructure.DMA_Channel = UART3_DMA; //通道选择 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR; // DMA外设地址 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)uart3_rx_buf; // DMA 存储器0地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //外设到存储器模式 DMA_InitStructure.DMA_BufferSize = UART3_REC_LEN; //数据传输量 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度:8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 使用循环模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //中等优先级 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发单次传输 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发单次传输 DMA_Init(UART3_DMA_RXCH, &DMA_InitStructure); } void uart3_config(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式 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(USART3, &USART_InitStructure); //初始化串口1 USART_Cmd(USART3, ENABLE); //使能串口3 } void Uart3DMA_Enable(DMA_Stream_TypeDef *DMA_Streamx, u16 count) { DMA_Cmd(DMA_Streamx, DISABLE); //关闭DMA传输 while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE) { } //确保DMA可以被设置 DMA_SetCurrDataCounter(DMA_Streamx, count); //数据传输量 DMA_Cmd(DMA_Streamx, ENABLE); //开启DMA传输 } void uart3_init(void) { uart3_config(); uart3_dma_init(); uart3_nvic_config(); /* USART DMA enable*/ USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE); // 使能串口DMA接收数据 Uart3DMA_Enable(UART3_DMA_RXCH, UART3_REC_LEN); /*configure DMA interrupt*/ USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); //开启空闲中断 USART_ITConfig(USART3, USART_IT_TC, ENABLE); UART3_RX_ENABLE; } /**************************************************** * 函 数 名:Uart3_Send_Data * 函数功能:串口3发送数据 * 入口参数:buf 待发送数据 len 数据长度 * 说 明: *****************************************************/ void Uart3_Send_Data(const uint8_t *buf, uint16_t len) { uint8_t i; UART3_TX_ENABLE; // 485 发送使能 for (i = 0; i < len; i++) //循环发送数据 { while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET) ; USART_SendData(USART3, buf[i]); } while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET) ; UART3_RX_ENABLE; // 接收使能 } void uart3_dma_send(const uint8_t *buf, uint16_t len) { if (DMA_GetFlagStatus(UART3_DMA_TXCH, DMA_FLAG_TCIF3) != RESET) { DMA_ClearFlag(UART3_DMA_TXCH, DMA_FLAG_TCIF3); } UART3_TX_ENABLE; // 485 发送使能 if (len > UART3_TX_LEN) { len = UART3_TX_LEN; } memcpy(uart3_tx_buf, buf, len); USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE); Uart3DMA_Enable(UART3_DMA_TXCH, len); } void USART3_IRQHandler(void) { static uint8_t u3_index = 0; volatile uint8_t clear = 0; uint8_t rec_cnt = 0; if (RESET != USART_GetITStatus(USART3, USART_IT_IDLE)) { clear = USART3->SR; clear = USART3->DR; // 先读SR, 再读DR, 就是为了消除IDLE中断 DMA_Cmd(UART3_DMA_RXCH, DISABLE); DMA_ClearFlag(UART3_DMA_RXCH, DMA_FLAG_TCIF1); rec_cnt = UART3_REC_LEN - DMA_GetCurrDataCounter(UART3_DMA_RXCH); memcpy(Uart3FrameStruct[u3_index].buf, uart3_rx_buf, rec_cnt); Uart3FrameStruct[u3_index].len = rec_cnt; OSMboxPost(uart3_mbox, &Uart3FrameStruct[u3_index]); if (u3_index < UART3_MAX_MSG_NUM - 1) { u3_index++; } else { u3_index = 0; } DMA_SetCurrDataCounter(UART3_DMA_RXCH, UART3_REC_LEN); DMA_Cmd(UART3_DMA_RXCH, ENABLE); } else if (RESET != USART_GetITStatus(USART3, USART_IT_TC)) { USART_ClearITPendingBit(USART3, USART_IT_TC); UART3_RX_ENABLE; Uart3DMA_Enable(UART3_DMA_RXCH, UART3_REC_LEN); // DMA接收使能 DMA_Cmd(UART3_DMA_TXCH, DISABLE); // 关闭发送DMA DMA_SetCurrDataCounter(UART3_DMA_TXCH, 0); // 清除发送数据长度 } }