/**
******************************************************************************
* @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****/