/* * FreeModbus Libary: BARE Port * Copyright (C) 2006 Christian Walter * * 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.1 2006/08/22 21:35:13 wolti Exp $ */ #include "port.h" /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" #include "mbport.h" #include "RS485.h" #include "sizhu_communication_protocol.h" /* ----------------------- static functions ---------------------------------*/ static void prvvUARTTxReadyISR(void); static void prvvUARTRxISR(void); /* ----------------------- Start implementation -----------------------------*/ /** * @brief ´®¿ÚÊÕ·¢¿ª¹Øº¯Êý * @param ÎÞ * @retval ÎÞ */ void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ) { /* If xRXEnable enable serial receive interrupts. If xTxENable enable * transmitter empty interrupts. */ USART_ITConfig(UARTNUM,USART_IT_RXNE,(xRxEnable==TRUE)?ENABLE:DISABLE); USART_ITConfig(UARTNUM,USART_IT_TXE,(xTxEnable==TRUE)?ENABLE:DISABLE); } /** * @brief ´®¿Ú³õʼ»¯º¯Êý * @param ÎÞ * @retval ״̬±êÖ¾ */ BOOL xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity ) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; //ʹÄÜGPIOºÍUARTʱÖÓ RCC_APB2PeriphClockCmd(APB_GPIO_GROUP , ENABLE); RCC_APB1PeriphClockCmd( RCC_APB_Periph_UART, ENABLE); USART_DeInit(UARTNUM); GPIO_InitStructure.GPIO_Pin = V_RS485_TXD_EN_PIN_NUM; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(V_RS485_TXD_EN_PIN_GROUP, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = V_RS485_RXD_EN_PIN_NUM; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(V_RS485_RXD_EN_PIN_GROUP, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = V_RS485_CON_EN_PIN_NUM; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(V_RS485_CON_EN_PIN_GROUP, &GPIO_InitStructure); //³õʼ»¯USART USART_InitStructure.USART_BaudRate = ulBaudRate; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //È·¶¨Ð£Ñ鷽ʽ if(eParity == MB_PAR_NONE) { USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_WordLength = USART_WordLength_8b; } else if(eParity == MB_PAR_ODD) { USART_InitStructure.USART_Parity = USART_Parity_Odd; USART_InitStructure.USART_WordLength = USART_WordLength_9b; } else { USART_InitStructure.USART_Parity = USART_Parity_Even; USART_InitStructure.USART_WordLength = USART_WordLength_9b; } USART_Init(UARTNUM, &USART_InitStructure); //******************************************************************************************// RCC_AHBPeriphClockCmd(RCC_AHB_Preiph_UART_DMA, ENABLE); DMA_DeInit(DMA_RS485_Channel); DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)(&(UARTNUM->DR)) ; /*ÉèÖÃDMAÔ´£º´®¿ÚÊý¾Ý¼Ä´æÆ÷µØÖ·*/ DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(rs485_receive_g.RS485_BUF);/*ÄÚ´æµØÖ·(Òª´«ÊäµÄ±äÁ¿µÄÖ¸Õë)*/ DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;/*·½Ïò£º´ÓË«Ïòµ½ÄÚ´æ*/ DMA_InitStructure.DMA_BufferSize = REC_LENGTH;/*´«Êä´óСDMA_BufferSize=SENDBUFF_SIZE*/ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;/*ÍâÉèµØÖ·²»Ôö*/ DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /*ÄÚ´æµØÖ·×ÔÔö*/ DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/*ÍâÉèÊý¾Ýµ¥Î»*/ DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; /*ÄÚ´æÊý¾Ýµ¥Î» 8bit*/ //DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; /*DMAģʽ£º²»¶ÏÑ­»·*/ DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; /*ÓÅÏȼ¶£ºÖÐ*/ DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;/*½ûÖ¹ÄÚ´æµ½ÄÚ´æµÄ´«Êä */ DMA_Init(DMA_RS485_Channel, &DMA_InitStructure); USART_DMACmd(UARTNUM, USART_DMAReq_Rx, ENABLE); DMA_Cmd(DMA_RS485_Channel, ENABLE); //*********************************************************************************************// USART_Cmd(UARTNUM, ENABLE); //USARTÖжÏÓÅÏȼ¶ÅäÖà ¹Ø±Õ´®¿ÚʹÄÜ // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; NVIC_Init(&NVIC_InitStructure);*/ // USART_ClearITPendingBit(UARTNUM, USART_IT_TC);//Çå³ýTC±êÖ¾ USART_ClearFlag(UARTNUM, USART_FLAG_TC); //¿ªÆôTX DMA // RS485_TXDMA_Init(log_send_buffer,SEND_BUFFER_LENGTH); V_RS485_EN_LOW; return TRUE; } /** * @brief Êä³öÊý¾Ýº¯Êý * @param ÎÞ * @retval ÎÞ */ BOOL xMBPortSerialPutByte( CHAR ucByte ) { extern u8 RS485_status,BT_status; /* Put a byte in the UARTs transmit buffer. This function is called * by the protocol stack if pxMBFrameCBTransmitterEmpty( ) has been * called. */ if(RS485_status) { V_RS485_EN_HIGH; //while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); USART_SendData(UARTNUM,ucByte); while(USART_GetFlagStatus(UARTNUM, USART_FLAG_TC) == RESET); V_RS485_EN_LOW; } else if(BT_status) { //while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); USART_SendData(UARTNUM,ucByte); while(USART_GetFlagStatus(UARTNUM, USART_FLAG_TC) == RESET); } return TRUE; } /** * @brief ½ÓÊÕÊý¾Ýº¯Êý * @param ÎÞ * @retval Íê³É״̬ */ BOOL xMBPortSerialGetByte( CHAR * pucByte ) { /* Return the byte in the UARTs receive buffer. This function is called * by the protocol stack after pxMBFrameCBByteReceived( ) has been called. */ *pucByte=USART_ReceiveData(UARTNUM); 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. */ static 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. */ static void prvvUARTRxISR(void) { pxMBFrameCBByteReceived(); } /** * @brief ´®¿ÚÖжϺ¯Êý * @param ÎÞ * @retval ÎÞ */ void UART4_IRQHandler(void) { //½ÓÊÕÖÐ¶Ï if(USART_GetITStatus(UARTNUM, USART_IT_RXNE)!=RESET) { // prvvUARTRxISR(); //Çå³ýÖжϱêÖ¾ USART_ClearITPendingBit(UARTNUM, USART_IT_RXNE); } //·¢ËÍÍê³ÉÖÐ¶Ï if(USART_GetITStatus(UARTNUM, USART_IT_TXE)!=RESET) { // prvvUARTTxReadyISR(); //Çå³ýÖжϱêÖ¾ USART_ClearITPendingBit(UARTNUM, USART_IT_TXE); } }