#include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_usart.h" #include "stm32f4xx_dma.h" #include "rs485.h" #include "lark1s.h" #include "dwin.h" #define RS485_TX_STREAM DMA1_Stream3 #define RS485_RX_STREAM DMA1_Stream1 #define RS485_BUFF_TX_LEN (4096) #define RS485_BUFF_RX_LEN (4096) uint8_t rs485_buff_tx[RS485_BUFF_TX_LEN] __attribute__((aligned(16))); uint8_t rs485_buff_rx[RS485_BUFF_RX_LEN] __attribute__((aligned(16))); static int __attribute__((section(".bss_ccm"))) sm = 0; char sn[16] __attribute__((section(".bss_ccm"))); struct lark1s_gas_info_s lark1s_gas_info __attribute__((section(".bss_ccm"))); struct lark1s_gas_cali_data_s lark1s_gas_cali_data __attribute__((section(".bss_ccm"))); struct lark1s_data_s lark1s_data __attribute__((section(".bss_ccm"))); struct lark1s_status_s lark1s_status __attribute__((section(".bss_ccm"))); 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_state_machine_tx(void) { int len; switch (sm) { case 0: len = lark1s_req_sn(rs485_buff_tx); break; case 1: len = lark1s_req_gas3_info(rs485_buff_tx); break; case 2: len = lark1s_req_gas3_cali_data(rs485_buff_tx); break; case 3: len = lark1s_req_data(rs485_buff_tx); break; case 4: len = lark1s_req_status(rs485_buff_tx); break; default: len = 0; break; } rs485_send((uint16_t)len); } void rs485_state_machine_rx(int len) { int ret = LARK1S_PARSE_OK; switch (sm) { case 0: ret = lark1s_parse_sn(rs485_buff_rx, len, sn); break; case 1: ret = lark1s_parse_gas3_info(rs485_buff_rx, len, &lark1s_gas_info); break; case 2: ret = lark1s_parse_gas3_cali_data(rs485_buff_rx, len, &lark1s_gas_cali_data); break; case 3: ret = lark1s_parse_data(rs485_buff_rx, len, &lark1s_data); break; case 4: ret = lark1s_parse_status(rs485_buff_rx, len, &lark1s_status); break; default: break; } if (ret) { return; } sm++; if (sm > 4) { sm = 0; } } void rs485_loop(void) { static uint32_t ms = 0; if (system_tick_cnt < (ms + 200)) { return; } ms = system_tick_cnt; rs485_state_machine_tx(); } 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; rs485_state_machine_rx((uint16_t)len); } }