From 283685ff35ffc6bd9cc428a74b935d5665e236f1 Mon Sep 17 00:00:00 2001 From: zhji Date: Sun, 23 Jun 2024 21:50:41 +0800 Subject: [PATCH] [feat] add rs485(UART3) baseic driver --- stm32f4/main.c | 9 ++- stm32f4/src/CMakeLists.txt | 3 +- stm32f4/src/rs485.c | 153 +++++++++++++++++++++++++++++++++++++ stm32f4/src/rs485.h | 26 +++++++ 4 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 stm32f4/src/rs485.c create mode 100644 stm32f4/src/rs485.h diff --git a/stm32f4/main.c b/stm32f4/main.c index 2972c8f..a2bf8e2 100755 --- a/stm32f4/main.c +++ b/stm32f4/main.c @@ -1,6 +1,7 @@ #include "stm32f4xx_rcc.h" #include "led.h" -#include "lcd.h" +// #include "lcd.h" +#include "rs485.h" volatile uint32_t system_tick_cnt; @@ -28,7 +29,8 @@ void system_init(void) { led_init(); system_tick_init(); - lcd_init(); + // lcd_init(); + rs485_init(); } int main(void) @@ -39,7 +41,8 @@ int main(void) __enable_irq(); while (1) { led_loop(); - lcd_loop(); + // lcd_loop(); + rs485_loop(); } return 0; } diff --git a/stm32f4/src/CMakeLists.txt b/stm32f4/src/CMakeLists.txt index 86416a1..11a9284 100755 --- a/stm32f4/src/CMakeLists.txt +++ b/stm32f4/src/CMakeLists.txt @@ -1,6 +1,7 @@ file(GLOB FILELIST led.c -lcd.c +# lcd.c +rs485.c ) add_library(src STATIC ${FILELIST}) diff --git a/stm32f4/src/rs485.c b/stm32f4/src/rs485.c new file mode 100644 index 0000000..e7c0a94 --- /dev/null +++ b/stm32f4/src/rs485.c @@ -0,0 +1,153 @@ +#include "stm32f4xx_rcc.h" +#include "stm32f4xx_gpio.h" +#include "stm32f4xx_usart.h" +#include "stm32f4xx_dma.h" +#include "rs485.h" + +#define RS485_TX_STREAM DMA1_Stream3 +#define RS485_RX_STREAM DMA1_Stream1 +#define RS485_BUFF_TX_LEN (4096) +#define RS485_BUFF_RX_LEN (1024) +uint8_t rs485_buff_tx[RS485_BUFF_TX_LEN] __attribute__((aligned(16))); +uint8_t rs485_buff_rx[RS485_BUFF_RX_LEN] __attribute__((aligned(16))); + +extern uint32_t system_tick_cnt; + +static void rs485_mode_tx(void) +{ + GPIO_SetBits(RS485_PORT, RS485_PIN_DIR); +} + +static void rs485_mode_rx(void) +{ + GPIO_ResetBits(RS485_PORT, RS485_PIN_DIR); +} + +void rs485_init(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + DMA_InitTypeDef DMA_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); + + GPIO_InitStructure.GPIO_Pin = RS485_PIN_DIR, + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT, + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP, + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz, + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL, + GPIO_Init(RS485_PORT, &GPIO_InitStructure); + rs485_mode_tx(); + + GPIO_PinAFConfig(RS485_PORT, GPIO_PinSource10, GPIO_AF_USART3); + GPIO_PinAFConfig(RS485_PORT, GPIO_PinSource11, GPIO_AF_USART3); + GPIO_InitStructure.GPIO_Pin = RS485_PIN_TX | RS485_PIN_RX; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_Init(RS485_PORT, &GPIO_InitStructure); + + USART_DeInit(USART3); + USART_OverSampling8Cmd(USART3, ENABLE); + USART_InitStructure.USART_BaudRate = RS485_BAUDRATE; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_Init(USART3, &USART_InitStructure); + USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE); + USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE); + USART_Cmd(USART3, ENABLE); + + DMA_InitStructure.DMA_BufferSize = RS485_BUFF_TX_LEN; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(&(USART3->DR)); + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_Priority = DMA_Priority_Low; + DMA_InitStructure.DMA_Channel = DMA_Channel_4; + DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; + DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rs485_buff_tx; + DMA_Init(RS485_TX_STREAM, &DMA_InitStructure); + /* Configure DMA controller to manage USART RX request */ + DMA_InitStructure.DMA_BufferSize = RS485_BUFF_RX_LEN; + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; + DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)rs485_buff_rx; + DMA_Init(RS485_RX_STREAM, &DMA_InitStructure); + /* Configure interrupt for USART3 RX */ + NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); + USART_ITConfig(USART3, USART_IT_TC, ENABLE); + /* clear IT flag */ + USART_GetITStatus(USART3, USART_IT_IDLE); + USART_ReceiveData(USART3); + USART_ClearITPendingBit(USART3, USART_IT_IDLE); + USART_ClearITPendingBit(USART3, USART_IT_TC); + + rs485_send(15); +} + +void rs485_send(uint16_t len) +{ + rs485_mode_tx(); + DMA_SetCurrDataCounter(RS485_TX_STREAM, len); + DMA_Cmd(RS485_TX_STREAM, ENABLE); +} + +void rs485_loop(void) +{ + static uint32_t ms = 0; + + if (system_tick_cnt < (ms + 500)) { + return; + } + ms = system_tick_cnt; + // rs485_send(15); +} + +void USART3_IRQHandler(void) +{ + uint16_t len; + + if (USART_GetITStatus(USART3, USART_IT_TC) != RESET) + { + USART_ClearITPendingBit(USART3, USART_IT_TC); + DMA_ClearFlag(RS485_TX_STREAM, DMA_FLAG_TCIF3 | DMA_FLAG_HTIF3 | DMA_FLAG_TEIF3 | DMA_FLAG_DMEIF3 | DMA_FLAG_FEIF3); + DMA_Cmd(RS485_TX_STREAM, DISABLE); + /* after tx complete, config rx */ + USART_ReceiveData(USART3); + USART_ClearITPendingBit(USART3, USART_IT_IDLE); + DMA_SetCurrDataCounter(RS485_RX_STREAM, RS485_BUFF_RX_LEN); + DMA_Cmd(RS485_RX_STREAM, ENABLE); + USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); + rs485_mode_rx(); + } + if (USART_GetITStatus(USART3, USART_IT_IDLE) != RESET) { + USART_ITConfig(USART3, USART_IT_IDLE, DISABLE); + USART_ReceiveData(USART3); + USART_ClearITPendingBit(USART3, USART_IT_IDLE); + DMA_Cmd(RS485_RX_STREAM, DISABLE); + DMA_ClearFlag(RS485_RX_STREAM, DMA_FLAG_TCIF1 | DMA_FLAG_HTIF1 | DMA_FLAG_TEIF1 | DMA_FLAG_DMEIF1 | DMA_FLAG_FEIF1); + len = DMA_GetCurrDataCounter(RS485_RX_STREAM); + len = RS485_BUFF_RX_LEN - len; + for (uint16_t i = 0; i < len; i++) { + rs485_buff_tx[i] = rs485_buff_rx[i] + 2; + } + rs485_send(len); + } +} diff --git a/stm32f4/src/rs485.h b/stm32f4/src/rs485.h new file mode 100644 index 0000000..41c2a1c --- /dev/null +++ b/stm32f4/src/rs485.h @@ -0,0 +1,26 @@ +#ifndef __RS485_H__ +#define __RS485_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "stm32f4xx.h" + +#define RS485_PORT (GPIOB) +#define RS485_PIN_TX (GPIO_Pin_10) +#define RS485_PIN_RX (GPIO_Pin_11) +#define RS485_PIN_DIR (GPIO_Pin_1) + +#define RS485_BAUDRATE (115200) +#define RS485_MB_ADDR (9) + +void rs485_init(void); +void rs485_send(uint16_t len); +void rs485_loop(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __RS485_H__ */