/** ****************************************************************************** * @file TMC_UART.c * @author TMC Terminal Team * @version V1.0.0 * @date 06/21/2018 * @brief UART TMC module driver. * This file provides functions for UART. * ****************************************************************************** * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, TMC SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2016 TMC

******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "global.h" static TMC_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart); Uart_Receive_PROTOCOL gUartFlag; /** * @function BccCheck * @brief 异或校验 * @param[in] pSrc 指针指向源数据 * @param[in] uLen 数据长度 * @return 校验值 */ uint8_t BccCheck(uint8_t *pSrc, uint16_t uLen) { uint32_t i = 0; uint8_t uBcc = 0; for(i = 0; i < uLen; i++) { uBcc ^= pSrc[i]; } return uBcc; } /** * @function AppUartInit * @brief 串口初始化 * @param[in] baudRate 串口波特率 * @param[in] parityMode 校验模式 * @return 无 */ void AppUartInit(uint32_t baudRate, uint32_t parityMode) { ghuart1.UARTx = UART1; TMC_UART_DeInit(&ghuart1); UART_StructInit(&ghuart1.Init); ghuart1.Init.BaudRate = baudRate; ghuart1.Init.ParityMode = parityMode; TMC_UART_Init(&ghuart1); gUartFlag = UART_PROTOCOL_STX; //设置通过中断接收一个字节,将数据放到gUartBuff SET_UART_Receive_IT(&ghuart1, gUartBuff, 1); } /** * @function AppUartSendData * @brief 串口数据发送 * @param[in] buf 发送数据buf * @param[in] len 发送长度 * @return TMC_OK/TMC_ERROR/TMC_TIMEOUT/TMC_BUSY */ uint8_t AppUartSendDataComm(uint8_t *buf, uint32_t len) { uint8_t *pUARTbuf, *pOff; uint8_t status; //根据FID组织数据并发送,格式为 5A 01 [len] [data] Bcc A5 pUARTbuf = pOff = (uint8_t *) POSOUTBUF; *pOff++ = UART_PROTOCOL_STX_VALUE; *pOff++ = UART_PROTOCOL_RESPONSE_FID_VALUE; *pOff++ = (uint8_t) (len >> 8); *pOff++ = (uint8_t)(len); memcpy(pOff, buf, len); pOff += len; *pOff++ = BccCheck(pUARTbuf + 1, len + 3); *pOff++ = UART_PROTOCOL_ETX_VALUE; NVIC_DisableIRQ(UART1_IRQn); status = TMC_UART_Transmit(&ghuart1, pUARTbuf, len + 6); NVIC_EnableIRQ(UART1_IRQn); TimerDelay(TIM2, 1); return status; } /** * @function AppUartSendData * @brief 串口数据发送 * @param[in] buf 发送数据buf * @param[in] len 发送长度 * @return TMC_OK/TMC_ERROR/TMC_TIMEOUT/TMC_BUSY */ uint8_t AppUartSendData(uint8_t *buf, uint32_t len) { uint8_t *pUARTbuf, *pOff; /* 扫码后串口上发数据,支持两种协议 (1) ScanCodeData Responce: 格式为 5A 02 [len] [data] Bcc A5 (2) 无协议格式上送 */ if(gConfgBuf.uartOutputProtocal) { //根据FID组织数据并发送,格式为 5A 01/02 [len] [data] Bcc A5 pUARTbuf = pOff = (uint8_t *) POSOUTBUF; *pOff++ = UART_PROTOCOL_STX_VALUE; *pOff++ = UART_PROTOCOL_SEND_FID_VALUE; *pOff++ = (uint8_t) (len >> 8); *pOff++ = (uint8_t)(len); memcpy(pOff, buf, len); pOff += len; *pOff++ = BccCheck(pUARTbuf + 1, len + 3); *pOff++ = UART_PROTOCOL_ETX_VALUE; return TMC_UART_Transmit(&ghuart1, pUARTbuf, len + 6); } else { return TMC_UART_Transmit(&ghuart1, buf, len); } } /** * @function AppUartReceiveData * @brief 串口数据接收 * @param[in] buf 接收数据buf * @param[in] len 接收长度 * @return TMC_OK */ uint8_t AppUartReceiveData(uint8_t *buf, uint32_t len) { uint16_t realLen = 0; //如果串口按定义协议接收到完整数据,则拷贝数据到buf if(gUartFlag == UART_PROTOCOL_FINISH) { //如果期望的接收长度小于串口实际接收完成的数据,则用期望的数据长度,否则用实际串口接收到的长度 if(len < gUartLen) { realLen = len; } else { realLen = gUartLen ;// } memcpy(buf, gUartBuff + UART_PROTOCOL_DAT_OFFS, realLen); //串口接收完成后,设置为初始标记 gUartFlag = UART_PROTOCOL_STX; //设置通过中断接收一个字节,将数据放到gUartBuff SET_UART_Receive_IT(&ghuart1, gUartBuff, 1); } else if((gUartFlag != UART_PROTOCOL_STX) && (TimerHSIClockCount(TIM3, GET_TIMER) > UART_RECEIVE_TIMEOUT)) { TimerHSIClockCount(TIM3, STOP_TIMER); UART_ClearState(&ghuart1); gUartFlag = UART_PROTOCOL_STX; //设置通过中断接收一个字节,将数据放到gUartBuff SET_UART_Receive_IT(&ghuart1, gUartBuff, 1); } return realLen; } /** * @function UARTRecieveData * @brief 串口数据接收 * @param[in] 无 * @return RECIEVE_FINISH/RECEIVE_FAIL */ uint8_t UARTRecieveData(void) { uint32_t len = 0; //接收下发数据 len = AppUartReceiveData(gReceiveBuf, MAX_RECEIVE_DATA_LEN); if(len > 0) { gReceiveLen = len; return RECIEVE_FINISH; } return RECEIVE_FAIL; } /** * @brief Rx Transfer completed callbacks. * @param[in] huart:pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval None */ void TMC_UART_RxCpltCallback(UART_HandleTypeDef *huart) { uint8_t ucBcc; // uint16_t gUartLen; //如果是5A,则启动Timer,接收其他数据 /*串口协议说明: STX:0x5A FID:0x00 LEN:0xXXXX CMD:XXXX... BCC:0xXX ETX:0xA5 */ switch(gUartFlag) { case UART_PROTOCOL_STX: /*如果第一字节为开始字节0x5A,则继续接收下一字节*/ if(gUartBuff[0] == UART_PROTOCOL_STX_VALUE) { TimerHSIClockCount(TIM3, START_TIMER); gUartFlag = UART_PROTOCOL_FID; gUartLen = 0; SET_UART_Receive_IT(&ghuart1, &gUartBuff[1], 1); return; } break; case UART_PROTOCOL_FID: /*如果第二字节为开始字节0x00,则继续接收两长度字节*/ /* the received data is non-encrypted */ if(gUartBuff[1] == UART_PROTOCOL_RECEIVE_FID_VALUE) { gUartFlag = UART_PROTOCOL_LEN; SET_UART_Receive_IT(&ghuart1, &gUartBuff[2], 2); // gDataCrypted = 0; return; } /*如果第二字节为开始字节0x03,则继续接收两长度字节*/ /* the received data is encrypted */ if(gUartBuff[1] == PACK_TYPEA||gUartBuff[1] == PACK_TYPEB||gUartBuff[1] == PACK_TYPEC) { gUartFlag = UART_PROTOCOL_LEN; SET_UART_Receive_IT(&ghuart1, &gUartBuff[2], 2); // gDataCrypted = 1; return; } break; case UART_PROTOCOL_LEN: /*接收剩余所有数据*/ gUartFlag = UART_PROTOCOL_DATA; gUartLen = (gUartBuff[2] << 8) | gUartBuff[3]; SET_UART_Receive_IT(&ghuart1, &gUartBuff[4], gUartLen + 2); return; case UART_PROTOCOL_DATA: /*接收数据校验*/ ucBcc = BccCheck(gUartBuff + 1, gUartLen + 3); if((gUartBuff[gUartLen + 5] == UART_PROTOCOL_ETX_VALUE) && (gUartBuff[gUartLen + 4] == ucBcc)) { TimerHSIClockCount(TIM3, STOP_TIMER); /*完成全部协议数据接收*/ gUartFlag = UART_PROTOCOL_FINISH; return; } break; default: break; } gUartFlag = UART_PROTOCOL_STX; gUartLen = 0; UART_ClearState(&ghuart1); SET_UART_Receive_IT(&ghuart1, gUartBuff, 1); TimerHSIClockCount(TIM3, STOP_TIMER); } /** * @brief Initializes the UART mode according to the specified parameters in * the UART_InitTypeDef and create the associated handle. * @param[in] huart: pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval TMC status */ TMC_StatusTypeDef TMC_UART_Init(UART_HandleTypeDef *huart) { /* Check the UART handle allocation */ if(huart == NULL) { return TMC_ERROR; } if(huart->gState == TMC_UART_STATE_RESET) { /* Allocate lock resource and initialize it */ huart->Lock = HAL_UNLOCKED; /* Init the low level hardware */ TMC_UART_MspInit(huart); } huart->gState = TMC_UART_STATE_BUSY; /* Set the UART Communication parameters */ UART_Init(huart->UARTx, &(huart->Init)); /* Initialize the UART state */ huart->ErrorCode = TMC_UART_ERROR_NONE; huart->gState = TMC_UART_STATE_READY; // huart->RxState= TMC_UART_STATE_READY; NVIC_ClearPendingIRQ(UART1_IRQn); NVIC_EnableIRQ(UART1_IRQn); return TMC_OK; } /** * @brief DeInitializes the UART peripheral. * @param[in] huart: pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval TMC status */ TMC_StatusTypeDef TMC_UART_DeInit(UART_HandleTypeDef *huart) { /* Check the UART handle allocation */ if(huart == NULL) { return TMC_ERROR; } huart->gState = TMC_UART_STATE_BUSY; UART_DeInit(huart->UARTx); huart->ErrorCode = TMC_UART_ERROR_NONE; huart->gState = TMC_UART_STATE_RESET; // huart->RxState = TMC_UART_STATE_RESET; /* Process Lock */ __HAL_UNLOCK(huart); return TMC_OK; } /** * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion). * @param[in] huart: UART handle. * @retval None */ static void UART_EndRxTransfer(UART_HandleTypeDef *huart) { /* Enable the UART Receive buffer full interrupt and Error Interrupt: (Frame error, Parity error, Overflow error) */ UART_ITConfig(huart->UARTx, UART_FLAG_RXF | UART_FLAG_PE | UART_FLAG_OF | UART_FLAG_FE, DISABLE); /* At end of Rx process, restore huart->RxState to Ready */ // huart->RxState = TMC_UART_STATE_READY; } /** * @brief DMA UART communication abort callback, when initiated by TMC services on Error * (To be called at end of DMA Abort procedure following error occurrence). * @param[in] hdma: DMA handle. * @retval None */ static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma) { UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; huart->RxXferCount = 0U; huart->TxXferCount = 0U; TMC_UART_ErrorCallback(huart); } /** * @brief Sends an amount of data in query mode. * @param[in] huart: pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @param[in]: pData: Pointer to data buffer * @param[in]: Size: Amount of data to be sent * @param[in]: Timeout: Timeout duration * @retval TMC status */ TMC_StatusTypeDef TMC_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint32_t Size) { if(huart->gState == TMC_UART_STATE_READY) { if((pData == NULL) || (Size == 0)) { return TMC_ERROR; } /* Process Locked */ // __HAL_LOCK(huart); huart->ErrorCode = TMC_UART_ERROR_NONE; huart->gState = TMC_UART_STATE_BUSY_TX; // /* Init tickstart for timeout managment */ huart->TxXferSize = Size; huart->TxXferCount = Size; while(huart->TxXferCount > 0U) { huart->TxXferCount--; while(!(huart->UARTx->STS & UART_FLAG_TXE)); /* Wait transmit data is ready. */ UART_SendData(huart->UARTx, *pData); pData++; } /* At end of Tx process, restore huart->gState to Ready */ huart->gState = TMC_UART_STATE_READY; /* Process Unlocked */ // __HAL_UNLOCK(huart); return TMC_OK; } else { return TMC_BUSY; } } void UART_Transmit(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size) { uint16_t len = Size; while(len > 0) { len--; while(!(huart->UARTx->STS & UART_FLAG_TXE)); /* Wait transmit data is ready. */ UART_SendData(huart->UARTx, *pData); pData++; } } /* void JJJ_Prompt(char *buf) { uint16_t len = strlen(buf); UART_Transmit(&ghuart1, (uint8_t *)buf, len); } */ /** * @brief Receives an amount of data in interrupt mode. * @param[in] huart: pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @param[in] pData: Pointer to data buffer * @param[in] Size: Amount of data to be received * @retval TMC status */ TMC_StatusTypeDef SET_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint32_t Size) { // if(huart->RxState == TMC_UART_STATE_READY) { if((pData == NULL) || (Size == 0)) { return TMC_ERROR; } /* Process Locked */ // __HAL_LOCK(huart); huart->pRxBuffPtr = pData; huart->RxXferSize = Size; huart->RxXferCount = Size; huart->ErrorCode = TMC_UART_ERROR_NONE; huart->gState = TMC_UART_STATE_READY; /* Process Unlocked */ // __HAL_UNLOCK(huart); /* Enable the UART Receive buffer full interrupt and Error Interrupt: (Frame error, Parity error, Overflow error) */ UART_ITConfig(huart->UARTx, UART_FLAG_RXF | UART_FLAG_PE | UART_FLAG_OF | UART_FLAG_FE, ENABLE); return TMC_OK; } // else // { // return TMC_BUSY; // } } /** * @brief This function handles UART interrupt request. * @param[in] huart: pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval None */ void TMC_UART_IRQHandler(UART_HandleTypeDef *huart) { uint32_t errorflags = 0x00; uint32_t errorIT = 0x00; errorflags = UART_GetFlagStatus(huart->UARTx, UART_FLAG_PE | UART_FLAG_OF | UART_FLAG_FE); errorIT = UART_GetITStatus(huart->UARTx, UART_FLAG_PE) | UART_GetITStatus(huart->UARTx, UART_FLAG_OF) | UART_GetITStatus(huart->UARTx, UART_FLAG_FE); /* If no error occurs */ if(errorflags == RESET) { /* UART in mode Receiver -------------------------------------------------*/ if(UART_GetITStatus(huart->UARTx, UART_FLAG_RXF) != RESET) { UART_Receive_IT(huart); return; } } /* If some errors occur */ if((errorIT != RESET) || ((errorflags != RESET) && (UART_GetITStatus(huart->UARTx, UART_FLAG_RXF) != RESET))) { /* UART parity error interrupt occurred ----------------------------------*/ if(UART_GetITStatus(huart->UARTx, UART_FLAG_PE) != RESET) { huart->ErrorCode |= TMC_UART_ERROR_PE; } /* UART frame error interrupt occurred -----------------------------------*/ if(UART_GetITStatus(huart->UARTx, UART_FLAG_FE) != RESET) { huart->ErrorCode |= TMC_UART_ERROR_FE; } /* UART Over-flow interrupt occurred --------------------------------------*/ if(UART_GetITStatus(huart->UARTx, UART_FLAG_OF) != RESET) { huart->ErrorCode |= TMC_UART_ERROR_OFE; } /* Call UART Error Call back function if need be --------------------------*/ if(huart->ErrorCode != TMC_UART_ERROR_NONE) { /* Call user error callback */ TMC_UART_ErrorCallback(huart); /* UART in mode Receiver -----------------------------------------------*/ if(UART_GetITStatus(huart->UARTx, UART_FLAG_RXF) != RESET) { UART_Receive_IT(huart); } /* If Overflow error occurs, or if any error occurs in DMA mode reception, consider error as blocking */ if(((huart->ErrorCode & TMC_UART_ERROR_OFE) != RESET) || (UART_GetDMAStatus(huart->UARTx, UART_DMA_RX) != RESET)) { /* Blocking error : transfer is aborted Set the UART state ready to be able to start again the process, Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ UART_EndRxTransfer(huart); /* Disable the UART DMA Rx request if enabled */ if(UART_GetDMAStatus(huart->UARTx, UART_DMA_RX) != RESET) { UART_DMACmd(huart->UARTx, UART_DMA_RX, DISABLE); /* Abort the UART DMA Rx channel */ if(huart->hdmarx != NULL) { /* Set the UART DMA Abort callback : will lead to call TMC_UART_ErrorCallback() at end of DMA abort procedure */ huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError; if(TMC_DMA_Abort_IT(huart->hdmarx) != TMC_OK) { /* Call Directly XferAbortCallback function in case of error */ huart->hdmarx->XferAbortCallback(huart->hdmarx); } } else { /* Call user error callback */ TMC_UART_ErrorCallback(huart); } } else { /* Call user error callback */ TMC_UART_ErrorCallback(huart); } } else { /* Non Blocking error : transfer could go on. Error is notified to user through user error callback */ TMC_UART_ErrorCallback(huart); huart->ErrorCode = TMC_UART_ERROR_NONE; } } return; } /* End if some error occurs */ /* UART in mode Transmitter ------------------------------------------------*/ if(UART_GetITStatus(huart->UARTx, UART_FLAG_TXE) != RESET) { return; } } /** * @brief UART MSP Init. * @param[in] huart: pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval None */ void TMC_UART_MspInit(UART_HandleTypeDef *huart) { RCC_APB3PeriphClockCmd(RCC_APB3Periph_GPIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE); GPIO_ControlMode(GPIOC, 8, ALTERNATE); GPIO_ConfigAFR1(GPIOC, 8, Function1); GPIO_ControlMode(GPIOC, 9, ALTERNATE); GPIO_ConfigAFR1(GPIOC, 9, Function1); } /** * @brief Receives an amount of data in non query mode * @param[in] huart: pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval TMC status */ static TMC_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) { // if(huart->RxState == TMC_UART_STATE_BUSY_RX) { *huart->pRxBuffPtr++ = (uint8_t)(huart->UARTx->RxDATA); if(--huart->RxXferCount == 0U) { /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ UART_ITConfig(huart->UARTx, UART_FLAG_RXF | UART_FLAG_PE | UART_FLAG_OF | UART_FLAG_FE, DISABLE); /* Tx process is ended, restore huart->gState to Ready */ huart->gState = TMC_UART_STATE_RECEIVEFINISH; TMC_UART_RxCpltCallback(huart); } return TMC_OK; } // else // { // return TMC_BUSY; // } } /** * @brief UART error callbacks. * @param[in] huart:pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval None */ __weak void TMC_UART_ErrorCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ UNUSED(huart); /* NOTE: This function Should not be modified, when the callback is needed, the TMC_UART_ErrorCallback could be implemented in the user file */ } void UART_ClearState(UART_HandleTypeDef *huart) { // huart->RxState = TMC_UART_STATE_READY; huart->gState = TMC_UART_STATE_READY; } /************************ (C) COPYRIGHT TMC *****END OF FILE****/