TMC32_QJB/Uart/UART_main.c
2026-04-30 16:23:12 +08:00

665 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
******************************************************************************
* @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.
*
* <h2><center>&copy; COPYRIGHT 2016 TMC</center></h2>
******************************************************************************/
/* 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] huartpointer 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] huartpointer 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****/