2024-06-23 21:50:41 +08:00
|
|
|
#include "stm32f4xx_rcc.h"
|
|
|
|
|
#include "stm32f4xx_gpio.h"
|
|
|
|
|
#include "stm32f4xx_usart.h"
|
|
|
|
|
#include "stm32f4xx_dma.h"
|
|
|
|
|
#include "rs485.h"
|
2024-07-13 22:59:41 +08:00
|
|
|
#include "lark1s.h"
|
|
|
|
|
#include "dwin.h"
|
2024-06-23 21:50:41 +08:00
|
|
|
|
|
|
|
|
#define RS485_TX_STREAM DMA1_Stream3
|
|
|
|
|
#define RS485_RX_STREAM DMA1_Stream1
|
|
|
|
|
#define RS485_BUFF_TX_LEN (4096)
|
2024-07-07 21:37:22 +08:00
|
|
|
#define RS485_BUFF_RX_LEN (4096)
|
2024-06-23 21:50:41 +08:00
|
|
|
uint8_t rs485_buff_tx[RS485_BUFF_TX_LEN] __attribute__((aligned(16)));
|
|
|
|
|
uint8_t rs485_buff_rx[RS485_BUFF_RX_LEN] __attribute__((aligned(16)));
|
2024-07-13 22:59:41 +08:00
|
|
|
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")));
|
2024-06-23 21:50:41 +08:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2024-07-07 21:37:22 +08:00
|
|
|
// rs485_send(15);
|
2024-06-23 21:50:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rs485_send(uint16_t len)
|
|
|
|
|
{
|
|
|
|
|
rs485_mode_tx();
|
|
|
|
|
DMA_SetCurrDataCounter(RS485_TX_STREAM, len);
|
|
|
|
|
DMA_Cmd(RS485_TX_STREAM, ENABLE);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-13 22:59:41 +08:00
|
|
|
void rs485_state_machine_tx(void)
|
2024-07-07 21:37:22 +08:00
|
|
|
{
|
2024-07-13 22:59:41 +08:00
|
|
|
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);
|
2024-07-07 21:37:22 +08:00
|
|
|
}
|
|
|
|
|
|
2024-07-13 22:59:41 +08:00
|
|
|
void rs485_state_machine_rx(int len)
|
2024-07-07 21:37:22 +08:00
|
|
|
{
|
2024-07-13 22:59:41 +08:00
|
|
|
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;
|
|
|
|
|
}
|
2024-07-07 21:37:22 +08:00
|
|
|
}
|
|
|
|
|
|
2024-06-23 21:50:41 +08:00
|
|
|
void rs485_loop(void)
|
|
|
|
|
{
|
|
|
|
|
static uint32_t ms = 0;
|
|
|
|
|
|
2024-07-13 22:59:41 +08:00
|
|
|
if (system_tick_cnt < (ms + 200)) {
|
2024-06-23 21:50:41 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ms = system_tick_cnt;
|
2024-07-13 22:59:41 +08:00
|
|
|
rs485_state_machine_tx();
|
2024-06-23 21:50:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2024-07-13 22:59:41 +08:00
|
|
|
rs485_state_machine_rx((uint16_t)len);
|
2024-06-23 21:50:41 +08:00
|
|
|
}
|
|
|
|
|
}
|