mirror of
https://gitea.ecohim.ru:3000/RS485_Relay/RS485_Relay2_fw.git
synced 2025-08-06 16:07:17 +03:00
RS485 UART переделал на DMA по образцу HVD4
This commit is contained in:
@@ -13,6 +13,6 @@
|
||||
#define REL_AUX_BIT (1u<<1)
|
||||
|
||||
void loop_iterate();
|
||||
|
||||
void timer1_ovf_isr(void);
|
||||
|
||||
#endif
|
||||
|
@@ -24,7 +24,7 @@ enum send_state {SEND_IDLE, SEND_BUSY};
|
||||
|
||||
void UART_RxCpltCallback(void);
|
||||
void UART_TxCpltCallback(void);
|
||||
|
||||
void process_incoming_packet();
|
||||
void modbus_loop_iterate();
|
||||
uint8_t read_register(uint16_t address, uint16_t* value);
|
||||
uint8_t write_register(uint16_t address, uint16_t value);
|
||||
|
@@ -51,6 +51,7 @@ void HardFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
void DMA1_Channel2_3_IRQHandler(void);
|
||||
void TIM1_BRK_UP_TRG_COM_IRQHandler(void);
|
||||
void TIM1_CC_IRQHandler(void);
|
||||
void USART1_IRQHandler(void);
|
||||
|
@@ -1,13 +0,0 @@
|
||||
#ifndef __UART_H
|
||||
#define __UART_H
|
||||
#include <stdint.h>
|
||||
|
||||
#define RET_OK 0
|
||||
#define RET_OVERFLOW 1
|
||||
#define RET_TIMEOUT 2
|
||||
|
||||
uint8_t UART_Transmit_IT(uint8_t * data, uint16_t len, uint16_t timeout);
|
||||
uint8_t UART_Receive_IT(uint8_t * data, uint16_t len, uint16_t timeout);
|
||||
extern void UART_TxCpltCallback(void);
|
||||
extern void UART_RxCpltCallback(void);
|
||||
#endif
|
@@ -47,6 +47,8 @@ TIM_HandleTypeDef htim1;
|
||||
TIM_HandleTypeDef htim3;
|
||||
|
||||
UART_HandleTypeDef huart1;
|
||||
DMA_HandleTypeDef hdma_usart1_rx;
|
||||
DMA_HandleTypeDef hdma_usart1_tx;
|
||||
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
@@ -55,6 +57,7 @@ UART_HandleTypeDef huart1;
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void SystemClock_Config(void);
|
||||
static void MX_GPIO_Init(void);
|
||||
static void MX_DMA_Init(void);
|
||||
static void MX_TIM3_Init(void);
|
||||
static void MX_USART1_UART_Init(void);
|
||||
static void MX_TIM1_Init(void);
|
||||
@@ -95,11 +98,11 @@ int main(void)
|
||||
|
||||
/* Initialize all configured peripherals */
|
||||
MX_GPIO_Init();
|
||||
MX_DMA_Init();
|
||||
MX_TIM3_Init();
|
||||
MX_USART1_UART_Init();
|
||||
MX_TIM1_Init();
|
||||
/* USER CODE BEGIN 2 */
|
||||
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // включить прерывания usart'a
|
||||
HAL_TIM_Base_Start_IT(&htim1);
|
||||
|
||||
/* USER CODE END 2 */
|
||||
@@ -290,6 +293,22 @@ static void MX_USART1_UART_Init(void)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable DMA controller clock
|
||||
*/
|
||||
static void MX_DMA_Init(void)
|
||||
{
|
||||
|
||||
/* DMA controller clock enable */
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
|
||||
/* DMA interrupt init */
|
||||
/* DMA1_Channel2_3_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 2, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO Initialization Function
|
||||
* @param None
|
||||
|
@@ -6,11 +6,13 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "main.h"
|
||||
#include "uart.h"
|
||||
#include "modbus_logic.h"
|
||||
|
||||
volatile uint8_t recv_buffer[BUFFERS_SIZE];
|
||||
volatile uint8_t send_buffer[BUFFERS_SIZE];
|
||||
extern UART_HandleTypeDef huart1;
|
||||
extern DMA_HandleTypeDef hdma_usart1_rx;
|
||||
|
||||
uint8_t recv_buffer[BUFFERS_SIZE];
|
||||
uint8_t send_buffer[BUFFERS_SIZE];
|
||||
|
||||
uint16_t bytes_to_send = 0;
|
||||
uint16_t last_rx_time = 0xFFFF;
|
||||
@@ -19,55 +21,56 @@ enum send_state cmd_sending = SEND_IDLE;
|
||||
uint16_t tranfer_errors_count;
|
||||
extern uint16_t led_time_act;
|
||||
|
||||
static void process_incoming_packet();
|
||||
void process_incoming_packet();
|
||||
|
||||
void UART_RxCpltCallback(void)
|
||||
#define TXEN_ON HAL_GPIO_WritePin(TXEN_GPIO_Port, TXEN_Pin, GPIO_PIN_SET)
|
||||
#define TXEN_OFF HAL_GPIO_WritePin(TXEN_GPIO_Port, TXEN_Pin, GPIO_PIN_RESET)
|
||||
|
||||
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
|
||||
{
|
||||
uint16_t pdu_size;
|
||||
uint16_t remaining_size;
|
||||
if (cmd_receiving == RECV_READ_HEADER)
|
||||
{
|
||||
// Check destination address
|
||||
if (recv_buffer[5] != BOARD_ADRESS)
|
||||
{
|
||||
cmd_receiving = RECV_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check function code
|
||||
if (recv_buffer[6] == 3 || recv_buffer[6] == 4 || recv_buffer[6] == 6)
|
||||
{
|
||||
cmd_receiving = RECV_READ_COMPLETE;
|
||||
return;
|
||||
}
|
||||
else if (recv_buffer[6] == 0x10)
|
||||
{
|
||||
cmd_receiving = RECV_READ_DATA;
|
||||
pdu_size = *((uint16_t*)(recv_buffer + 2));
|
||||
// Receive remaining PDU and checksum
|
||||
remaining_size = pdu_size - (MODBUS_HEADER_SIZE - 4) + 2;
|
||||
if (remaining_size + MODBUS_HEADER_SIZE <= BUFFERS_SIZE)
|
||||
UART_Receive_IT(recv_buffer + MODBUS_HEADER_SIZE, remaining_size, 5000);
|
||||
if (huart->Instance == USART1)
|
||||
{
|
||||
if (recv_buffer[5] != BOARD_ADRESS)
|
||||
{
|
||||
cmd_receiving = RECV_ERROR;
|
||||
return;
|
||||
}
|
||||
// Check function code
|
||||
if (recv_buffer[6] == 3 || recv_buffer[6] == 4 || recv_buffer[6] == 6)
|
||||
{
|
||||
if(Size==MODBUS_HEADER_SIZE)cmd_receiving = RECV_READ_COMPLETE;
|
||||
return;
|
||||
}
|
||||
else if (recv_buffer[6] == 0x10)
|
||||
{
|
||||
uint16_t pdu_size = *((uint16_t*)(recv_buffer + 2));
|
||||
uint16_t remaining_size = pdu_size - (MODBUS_HEADER_SIZE - 4) + 2;
|
||||
if (remaining_size + MODBUS_HEADER_SIZE == Size)
|
||||
cmd_receiving = RECV_READ_COMPLETE;
|
||||
else
|
||||
{
|
||||
cmd_receiving = RECV_ERROR;
|
||||
tranfer_errors_count++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
tranfer_errors_count++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
tranfer_errors_count++;
|
||||
cmd_receiving = RECV_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (cmd_receiving == RECV_READ_DATA)
|
||||
{
|
||||
cmd_receiving = RECV_READ_COMPLETE;
|
||||
}
|
||||
cmd_receiving = RECV_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UART_TxCpltCallback()
|
||||
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
cmd_sending = SEND_IDLE;
|
||||
if (huart->Instance == USART1)
|
||||
{
|
||||
cmd_sending = SEND_IDLE;
|
||||
TXEN_OFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void modbus_loop_iterate()
|
||||
@@ -76,19 +79,22 @@ void modbus_loop_iterate()
|
||||
{
|
||||
if (cmd_receiving == RECV_ERROR)
|
||||
{
|
||||
//delay_ms(30); // poor man's way to synchronize packets
|
||||
if(last_rx_time>=BUS_IDLE_TIME)
|
||||
{
|
||||
// poor man's way to synchronize packets
|
||||
//if(last_rx_time>=BUS_IDLE_TIME)
|
||||
//{
|
||||
cmd_receiving = RECV_IDLE;
|
||||
//TXEN_485 = 1;
|
||||
//delay_us(10);
|
||||
//TXEN_485 = 0;
|
||||
}
|
||||
//}
|
||||
}
|
||||
if (cmd_receiving == RECV_IDLE)
|
||||
{
|
||||
cmd_receiving = RECV_READ_HEADER;
|
||||
UART_Receive_IT(recv_buffer, MODBUS_HEADER_SIZE, 5000);
|
||||
if(HAL_UARTEx_ReceiveToIdle_DMA(&huart1, recv_buffer, BUFFERS_SIZE)==HAL_OK)
|
||||
{
|
||||
cmd_receiving = RECV_READ_HEADER;
|
||||
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
|
||||
}
|
||||
}
|
||||
else if (cmd_receiving == RECV_READ_COMPLETE)
|
||||
{
|
||||
@@ -98,7 +104,8 @@ void modbus_loop_iterate()
|
||||
}
|
||||
else if (cmd_sending == SEND_BUSY && bytes_to_send != 0)
|
||||
{
|
||||
UART_Transmit_IT(send_buffer, bytes_to_send, 1000);
|
||||
TXEN_ON;
|
||||
HAL_UART_Transmit_DMA(&huart1, send_buffer, bytes_to_send);
|
||||
bytes_to_send = 0;
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,9 @@
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
extern DMA_HandleTypeDef hdma_usart1_rx;
|
||||
|
||||
extern DMA_HandleTypeDef hdma_usart1_tx;
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN TD */
|
||||
@@ -94,9 +97,9 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_TIM1_CLK_ENABLE();
|
||||
/* TIM1 interrupt Init */
|
||||
HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0, 0);
|
||||
HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 3, 0);
|
||||
HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
|
||||
HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0);
|
||||
HAL_NVIC_SetPriority(TIM1_CC_IRQn, 3, 0);
|
||||
HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
|
||||
/* USER CODE BEGIN TIM1_MspInit 1 */
|
||||
|
||||
@@ -230,8 +233,41 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart)
|
||||
GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* USART1 DMA Init */
|
||||
/* USART1_RX Init */
|
||||
hdma_usart1_rx.Instance = DMA1_Channel3;
|
||||
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_usart1_rx.Init.Mode = DMA_NORMAL;
|
||||
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
|
||||
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
__HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);
|
||||
|
||||
/* USART1_TX Init */
|
||||
hdma_usart1_tx.Instance = DMA1_Channel2;
|
||||
hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_usart1_tx.Init.Mode = DMA_NORMAL;
|
||||
hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
|
||||
if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
__HAL_LINKDMA(huart,hdmatx,hdma_usart1_tx);
|
||||
|
||||
/* USART1 interrupt Init */
|
||||
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
|
||||
HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
|
||||
HAL_NVIC_EnableIRQ(USART1_IRQn);
|
||||
/* USER CODE BEGIN USART1_MspInit 1 */
|
||||
|
||||
@@ -262,6 +298,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
|
||||
|
||||
/* USART1 DMA DeInit */
|
||||
HAL_DMA_DeInit(huart->hdmarx);
|
||||
HAL_DMA_DeInit(huart->hdmatx);
|
||||
|
||||
/* USART1 interrupt DeInit */
|
||||
HAL_NVIC_DisableIRQ(USART1_IRQn);
|
||||
/* USER CODE BEGIN USART1_MspDeInit 1 */
|
||||
|
@@ -56,6 +56,8 @@
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern TIM_HandleTypeDef htim1;
|
||||
extern DMA_HandleTypeDef hdma_usart1_rx;
|
||||
extern DMA_HandleTypeDef hdma_usart1_tx;
|
||||
extern UART_HandleTypeDef huart1;
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
@@ -141,6 +143,21 @@ void SysTick_Handler(void)
|
||||
/* please refer to the startup file (startup_stm32f0xx.s). */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA1 channel 2 and 3 interrupts.
|
||||
*/
|
||||
void DMA1_Channel2_3_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DMA1_Channel2_3_IRQn 0 */
|
||||
|
||||
/* USER CODE END DMA1_Channel2_3_IRQn 0 */
|
||||
HAL_DMA_IRQHandler(&hdma_usart1_tx);
|
||||
HAL_DMA_IRQHandler(&hdma_usart1_rx);
|
||||
/* USER CODE BEGIN DMA1_Channel2_3_IRQn 1 */
|
||||
|
||||
/* USER CODE END DMA1_Channel2_3_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM1 break, update, trigger and commutation interrupts.
|
||||
*/
|
||||
@@ -175,8 +192,6 @@ void TIM1_CC_IRQHandler(void)
|
||||
void USART1_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN USART1_IRQn 0 */
|
||||
USER_UART1_IRQHandler(&huart1);
|
||||
return;
|
||||
|
||||
/* USER CODE END USART1_IRQn 0 */
|
||||
HAL_UART_IRQHandler(&huart1);
|
||||
|
102
Core/Src/uart.c
102
Core/Src/uart.c
@@ -1,102 +0,0 @@
|
||||
#include "uart.h"
|
||||
#include "main.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
uint8_t * uart_tx_buf;
|
||||
uint8_t uart_tx_busy=0;
|
||||
uint16_t uart_tx_counter=0;
|
||||
uint16_t uart_tx_len=0;
|
||||
|
||||
uint8_t * uart_rx_buf;
|
||||
uint8_t uart_rx_busy=0;
|
||||
uint16_t uart_rx_counter=0;
|
||||
uint16_t uart_rx_len=0;
|
||||
extern uint16_t last_rx_time;
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
|
||||
#define TXEN_ON HAL_GPIO_WritePin(TXEN_GPIO_Port, TXEN_Pin, GPIO_PIN_SET)
|
||||
#define TXEN_OFF HAL_GPIO_WritePin(TXEN_GPIO_Port, TXEN_Pin, GPIO_PIN_RESET)
|
||||
|
||||
void USER_UART1_IRQHandler(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
if((huart1.Instance->ISR & USART_ISR_RXNE) != RESET)
|
||||
{
|
||||
last_rx_time = 0;
|
||||
data = (uint8_t)(huart1.Instance->RDR & (uint8_t)0x00FF); // читает байт из регистра
|
||||
if(uart_rx_busy)
|
||||
{
|
||||
uart_rx_buf[uart_rx_counter]=data;
|
||||
if(++uart_rx_counter == uart_rx_len)
|
||||
{
|
||||
uart_rx_busy = 0;
|
||||
UART_RxCpltCallback();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if((uart_tx_busy)&&((huart1.Instance->ISR & USART_ISR_TC) != RESET))
|
||||
{
|
||||
if(++uart_tx_counter == uart_tx_len)
|
||||
{
|
||||
TXEN_OFF;
|
||||
uart_tx_busy = 0;
|
||||
UART_TxCpltCallback();
|
||||
__HAL_UART_DISABLE_IT(&huart1, UART_IT_TC);
|
||||
}
|
||||
else
|
||||
//putchar(uart_tx_buf[uart_tx_counter]);
|
||||
huart->Instance->TDR=uart_tx_buf[uart_tx_counter];
|
||||
}
|
||||
huart->Instance->ICR=0xFFFFFFFF;
|
||||
}
|
||||
|
||||
uint8_t UART_Receive_IT(uint8_t * data, uint16_t len, uint16_t timeout)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
//if(len>UART_RX_LEN)return RET_OVERFLOW;
|
||||
for(i=0;i<timeout;i++)
|
||||
{
|
||||
if(uart_rx_busy!=0)
|
||||
HAL_Delay(1);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(i==timeout) return RET_TIMEOUT;
|
||||
uart_rx_counter = 0;
|
||||
uart_rx_len = len;
|
||||
uart_rx_buf = data;
|
||||
uart_rx_busy = 1;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
uint8_t UART_Transmit_IT(uint8_t * data, uint16_t len, uint16_t timeout)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
for(i=0;i<timeout;i++)
|
||||
{
|
||||
if(uart_tx_busy!=0)
|
||||
HAL_Delay(1);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(i==timeout) return RET_TIMEOUT;
|
||||
uart_tx_busy = 1;
|
||||
TXEN_ON;
|
||||
HAL_Delay(1);
|
||||
uart_tx_buf = data;
|
||||
uart_tx_counter = 0;
|
||||
uart_tx_len = len;
|
||||
huart1.Instance->TDR=uart_tx_buf[0];
|
||||
//putchar(uart_tx_buf[0]);
|
||||
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
|
||||
return RET_OK;
|
||||
}
|
Reference in New Issue
Block a user