310 lines
8.8 KiB
C
310 lines
8.8 KiB
C
|
|
/*
|
|||
|
|
* FreeModbus Libary: RT-Thread Port
|
|||
|
|
* Copyright (C) 2013 Armink <armink.ztl@gmail.com>
|
|||
|
|
*
|
|||
|
|
* This library is free software; you can redistribute it and/or
|
|||
|
|
* modify it under the terms of the GNU Lesser General Public
|
|||
|
|
* License as published by the Free Software Foundation; either
|
|||
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|||
|
|
*
|
|||
|
|
* This library is distributed in the hope that it will be useful,
|
|||
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
|
* Lesser General Public License for more details.
|
|||
|
|
*
|
|||
|
|
* You should have received a copy of the GNU Lesser General Public
|
|||
|
|
* License along with this library; if not, write to the Free Software
|
|||
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
|
*
|
|||
|
|
* File: $Id: portserial.c,v 1.60 2013/08/13 15:07:05 Armink $
|
|||
|
|
*/
|
|||
|
|
#include "port.h"
|
|||
|
|
/* ----------------------- Modbus includes ----------------------------------*/
|
|||
|
|
#include "mb.h"
|
|||
|
|
#include "mbport.h"
|
|||
|
|
|
|||
|
|
static usart_type* port_uart_list[] = {UART5, UART7};
|
|||
|
|
static usart_type* port_uart;
|
|||
|
|
|
|||
|
|
/* ----------------------- Static variables ---------------------------------*/
|
|||
|
|
/* software simulation serial transmit IRQ handler thread */
|
|||
|
|
static TaskHandle_t thread_serial_soft_trans_irq = NULL;
|
|||
|
|
/* serial event */
|
|||
|
|
static EventGroupHandle_t event_serial;
|
|||
|
|
/* modbus slave serial device */
|
|||
|
|
//static UART_HandleTypeDef *serial;
|
|||
|
|
/*
|
|||
|
|
* Serial FIFO mode
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
static volatile uint8_t rx_buff[FIFO_SIZE_MAX];
|
|||
|
|
static Serial_fifo Slave_serial_rx_fifo;
|
|||
|
|
/* ----------------------- Defines ------------------------------------------*/
|
|||
|
|
/* serial transmit event */
|
|||
|
|
#define EVENT_SERIAL_TRANS_START (1 << 0)
|
|||
|
|
|
|||
|
|
/* ----------------------- static functions ---------------------------------*/
|
|||
|
|
static void prvvUARTTxReadyISR(void);
|
|||
|
|
static void prvvUARTRxISR(void);
|
|||
|
|
static void serial_soft_trans_irq(void *parameter);
|
|||
|
|
//static void Slave_TxCpltCallback(struct __UART_HandleTypeDef *huart);
|
|||
|
|
//static void Slave_RxCpltCallback(struct __UART_HandleTypeDef *huart);
|
|||
|
|
static int stm32_getc(void);
|
|||
|
|
static int stm32_putc(CHAR c);
|
|||
|
|
/* ----------------------- Start implementation -----------------------------*/
|
|||
|
|
BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
|
|||
|
|
eMBParity eParity) {
|
|||
|
|
/**
|
|||
|
|
* set 485 mode receive and transmit control IO
|
|||
|
|
* @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
BOOL bStatus = FALSE;
|
|||
|
|
usart_parity_selection_type usart_parity;
|
|||
|
|
usart_stop_bit_num_type usart_stop;
|
|||
|
|
usart_data_bit_num_type usart_data;
|
|||
|
|
gpio_init_type gpio_init_struct;
|
|||
|
|
|
|||
|
|
bStatus = TRUE;
|
|||
|
|
|
|||
|
|
if(ucPORT < (sizeof(port_uart_list) / sizeof(usart_type*)))
|
|||
|
|
{
|
|||
|
|
port_uart = port_uart_list[ucPORT];
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
bStatus = FALSE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
switch ( eParity )
|
|||
|
|
{
|
|||
|
|
case MB_PAR_NONE:
|
|||
|
|
usart_parity = USART_PARITY_NONE;
|
|||
|
|
usart_stop = USART_STOP_2_BIT;
|
|||
|
|
break;
|
|||
|
|
case MB_PAR_ODD:
|
|||
|
|
usart_parity = USART_PARITY_ODD;
|
|||
|
|
usart_stop = USART_STOP_1_BIT;
|
|||
|
|
break;
|
|||
|
|
case MB_PAR_EVEN:
|
|||
|
|
usart_parity = USART_PARITY_EVEN;
|
|||
|
|
usart_stop = USART_STOP_1_BIT;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
bStatus = FALSE;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
switch ( ucDataBits )
|
|||
|
|
{
|
|||
|
|
case 8:
|
|||
|
|
if(usart_stop == USART_STOP_1_BIT)
|
|||
|
|
{
|
|||
|
|
usart_data = USART_DATA_9BITS;
|
|||
|
|
}
|
|||
|
|
else if(usart_stop == USART_STOP_2_BIT)
|
|||
|
|
{
|
|||
|
|
usart_data = USART_DATA_8BITS;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
bStatus = FALSE;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case 7:
|
|||
|
|
if(usart_stop == USART_STOP_1_BIT)
|
|||
|
|
{
|
|||
|
|
usart_data = USART_DATA_8BITS;
|
|||
|
|
}
|
|||
|
|
else if(usart_stop == USART_STOP_2_BIT)
|
|||
|
|
{
|
|||
|
|
usart_data = USART_DATA_8BITS; //before F435 not support 7bit.
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
bStatus = FALSE;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
bStatus = FALSE;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* configure uart param */
|
|||
|
|
usart_parity_selection_config(port_uart, usart_parity);
|
|||
|
|
usart_init(port_uart, ulBaudRate, usart_data, usart_stop);
|
|||
|
|
// usart_rs485_delay_time_config(port_uart, 2, 2);
|
|||
|
|
// usart_de_polarity_set(port_uart, USART_DE_POLARITY_HIGH);
|
|||
|
|
// usart_rs485_mode_enable(port_uart, TRUE);
|
|||
|
|
usart_transmitter_enable(port_uart, TRUE);
|
|||
|
|
usart_receiver_enable(port_uart, TRUE);
|
|||
|
|
usart_enable(port_uart, TRUE);
|
|||
|
|
|
|||
|
|
NVIC_ClearPendingIRQ(UART5_IRQn);
|
|||
|
|
nvic_irq_enable(UART5_IRQn, 0, 1);
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* software initialize */
|
|||
|
|
Slave_serial_rx_fifo.buffer = rx_buff;
|
|||
|
|
Slave_serial_rx_fifo.get_index = 0;
|
|||
|
|
Slave_serial_rx_fifo.put_index = 0;
|
|||
|
|
|
|||
|
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD>߳<EFBFBD>*/
|
|||
|
|
event_serial = xEventGroupCreate(); //<2F><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
|
|||
|
|
if (NULL != event_serial) {
|
|||
|
|
MODBUS_DEBUG("Create Slave event_serial Event success!\r\n");
|
|||
|
|
} else {
|
|||
|
|
MODBUS_DEBUG("Create Slave event_serial Event Faild!\r\n");
|
|||
|
|
}
|
|||
|
|
BaseType_t xReturn =
|
|||
|
|
xTaskCreate((TaskFunction_t)serial_soft_trans_irq, /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
|||
|
|
(const char *)"slave trans", /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
|||
|
|
(uint16_t)128, /* ջ*/
|
|||
|
|
(void *)NULL, /* <20><><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD> */
|
|||
|
|
(UBaseType_t)12, /* <20><><EFBFBD>ȼ<EFBFBD>*/
|
|||
|
|
(TaskHandle_t *)&thread_serial_soft_trans_irq); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
|||
|
|
|
|||
|
|
if (xReturn == pdPASS) {
|
|||
|
|
MODBUS_DEBUG("xTaskCreate slave trans success\r\n");
|
|||
|
|
}
|
|||
|
|
return TRUE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) {
|
|||
|
|
// __HAL_UART_CLEAR_FLAG(serial,UART_FLAG_RXNE);
|
|||
|
|
// __HAL_UART_CLEAR_FLAG(serial,UART_FLAG_TC);
|
|||
|
|
// if (xRxEnable) {
|
|||
|
|
// /* enable RX interrupt */
|
|||
|
|
// __HAL_UART_ENABLE_IT(serial, UART_IT_RXNE);
|
|||
|
|
// /* switch 485 to receive mode */
|
|||
|
|
// MODBUS_DEBUG("RS485_RX_MODE\r\n");
|
|||
|
|
// SLAVE_RS485_RX_MODE;
|
|||
|
|
// } else {
|
|||
|
|
// /* switch 485 to transmit mode */
|
|||
|
|
// MODBUS_DEBUG("RS485_TX_MODE\r\n");
|
|||
|
|
// SLAVE_RS485_TX_MODE;
|
|||
|
|
// /* disable RX interrupt */
|
|||
|
|
// __HAL_UART_DISABLE_IT(serial, UART_IT_RXNE);
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
if(xRxEnable == TRUE)
|
|||
|
|
{
|
|||
|
|
usart_interrupt_enable(port_uart, USART_RDBF_INT, TRUE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
usart_interrupt_enable(port_uart, USART_RDBF_INT, FALSE);
|
|||
|
|
}
|
|||
|
|
//不使用发送中断
|
|||
|
|
// if(xTxEnable == TRUE)
|
|||
|
|
// {
|
|||
|
|
// usart_interrupt_enable(port_uart, USART_TDBE_INT, TRUE);
|
|||
|
|
// }
|
|||
|
|
// else
|
|||
|
|
// {
|
|||
|
|
// usart_interrupt_enable(port_uart, USART_TDBE_INT, FALSE);
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
if (xTxEnable) {
|
|||
|
|
/* start serial transmit */
|
|||
|
|
xEventGroupSetBits(event_serial, EVENT_SERIAL_TRANS_START);
|
|||
|
|
} else {
|
|||
|
|
/* stop serial transmit */
|
|||
|
|
xEventGroupClearBits(event_serial, EVENT_SERIAL_TRANS_START);
|
|||
|
|
/*<2A><><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>*/
|
|||
|
|
// printf("ms=%.2f,fps=%.2f\r\n", __HAL_TIM_GetCounter(&htim7) / 100.f,
|
|||
|
|
// 1000.f / (__HAL_TIM_GetCounter(&htim7) / 100.f));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void vMBPortClose(void)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*Send a byte*/
|
|||
|
|
BOOL xMBPortSerialPutByte(CHAR ucByte) {
|
|||
|
|
stm32_putc(ucByte);
|
|||
|
|
return TRUE;
|
|||
|
|
}
|
|||
|
|
/*Get a byte from fifo*/
|
|||
|
|
BOOL xMBPortSerialGetByte(CHAR *pucByte) {
|
|||
|
|
Get_from_fifo(&Slave_serial_rx_fifo, (uint8_t *)pucByte, 1);
|
|||
|
|
return TRUE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* Create an interrupt handler for the transmit buffer empty interrupt
|
|||
|
|
* (or an equivalent) for your target processor. This function should then
|
|||
|
|
* call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that
|
|||
|
|
* a new character can be sent. The protocol stack will then call
|
|||
|
|
* xMBPortSerialPutByte( ) to send the character.
|
|||
|
|
*/
|
|||
|
|
void prvvUARTTxReadyISR(void) { pxMBFrameCBTransmitterEmpty(); }
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
* Create an interrupt handler for the receive interrupt for your target
|
|||
|
|
* processor. This function should then call pxMBFrameCBByteReceived( ). The
|
|||
|
|
* protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
|
|||
|
|
* character.
|
|||
|
|
*/
|
|||
|
|
void prvvUARTRxISR(void) { pxMBFrameCBByteReceived(); }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Software simulation serial transmit IRQ handler.
|
|||
|
|
*
|
|||
|
|
* @param parameter parameter
|
|||
|
|
*/
|
|||
|
|
static void serial_soft_trans_irq(void *parameter) {
|
|||
|
|
uint32_t recved_event;
|
|||
|
|
while (1) {
|
|||
|
|
/* waiting for serial transmit start */
|
|||
|
|
xEventGroupWaitBits(event_serial, /* <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
|
EVENT_SERIAL_TRANS_START, /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȥ<EFBFBD><C8A4><EFBFBD>¼<EFBFBD> */
|
|||
|
|
pdFALSE, /* <20>˳<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>?? */
|
|||
|
|
pdFALSE, /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȥ<EFBFBD><C8A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?? */
|
|||
|
|
portMAX_DELAY); /* ָ<><D6B8><EFBFBD><EFBFBD>ʱ<EFBFBD>¼<EFBFBD>,<2C><><EFBFBD>ȴ<DEB5> */
|
|||
|
|
/* execute modbus callback */
|
|||
|
|
prvvUARTTxReadyISR();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*UART<52><54><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽ<EFBFBD>*/
|
|||
|
|
static int stm32_putc(CHAR c) {
|
|||
|
|
// serial->Instance->DR = c;
|
|||
|
|
// while (!(serial->Instance->SR & UART_FLAG_TC))
|
|||
|
|
// ;
|
|||
|
|
usart_data_transmit(port_uart, c);
|
|||
|
|
return TRUE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
void vUSARTHandler( void )
|
|||
|
|
{
|
|||
|
|
int ch = -1;
|
|||
|
|
|
|||
|
|
if(port_uart->ctrl1_bit.rdbfien == SET)
|
|||
|
|
{
|
|||
|
|
if(usart_flag_get(port_uart, USART_RDBF_FLAG) == SET)
|
|||
|
|
{
|
|||
|
|
ch = usart_data_receive(port_uart);
|
|||
|
|
Put_in_fifo(&Slave_serial_rx_fifo, (uint8_t *)&ch, 1);
|
|||
|
|
prvvUARTRxISR();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(port_uart->ctrl1_bit.tdbeien == SET)
|
|||
|
|
{
|
|||
|
|
if(usart_flag_get(port_uart, USART_TDBE_FLAG) == SET)
|
|||
|
|
{
|
|||
|
|
prvvUARTTxReadyISR();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//void UART7_IRQHandler(void)
|
|||
|
|
//{
|
|||
|
|
// vUSARTHandler( );
|
|||
|
|
//}
|