rt-thread-official/bsp/acm32f0x0-nucleo/libraries/HAL_Driver/Src/HAL_UART_EX.c

245 lines
8.7 KiB
C

/*
******************************************************************************
* @file HAL_UART_EX.c
* @version V1.0.0
* @date 2021
* @brief LIN HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the extensional module: Local Interconnect Network Peripheral (LIN).
* @ Initialization and de-initialization functions
* @ IO operation functions
* @ Peripheral Control functions
******************************************************************************
*/
#include "ACM32Fxx_HAL.h"
/************************************************************************
* function : HAL_UART_LIN_Master_Transmit
* Description: Uart lin master transmit data
* input :none
* UART_HandleTypeDef *huart: Serial port number
* uint8_t Lin_Version: LIN version ,should be UART_LIN_V1D3 or UART_LIN_V2DX.
* uint8_t Lin_Id: LIN id
* uint8_t *pData: point to the transmit data buffer.
* uint8_t Size: Transmit buffer Size.
* return: none
************************************************************************/
void HAL_UART_LIN_Master_Transmit(UART_HandleTypeDef *huart, uint8_t Lin_Version, uint8_t Lin_Id, uint8_t *pData, uint8_t Size)
{
uint8_t Lin_P0,Lin_P1,ucI;
uint16_t Lin_Check_Sum = 0;
if((Size>8)||(pData == 0))
return;
CLEAR_BIT(huart->Instance->IE, UART_EX_IE_LBDI);
huart->Instance->CR = 0x0101; //disable uart_rx
MODIFY_REG(huart->Instance->BCNT, UART_EX_BCNT_VALUE_MASK, (13)<<UART_EX_BCNT_VALUE_POS);
//Transmit break field.
SET_BIT(huart->Instance->BCNT, UART_EX_BCNT_START);
SET_BIT(huart->Instance->LCRH, UART_LCRH_BRK);
while(!(READ_BIT(huart->Instance->RIS, UART_EX_RIS_BCNTI))){} //Check BCNTI.
CLEAR_BIT(huart->Instance->LCRH, UART_LCRH_BRK);
HAL_UART_Transmit(huart, (uint8_t*)"\x55", 1, 0); //Transmit sync field
Lin_Id &= 0x3F; //Lin address check, 0-63.
Lin_P0 = (Lin_Id^(Lin_Id>>1)^(Lin_Id>>2)^(Lin_Id>>4))&0x01; //P0 = ID0^ID1^ID2^ID4
Lin_P1 = (~((Lin_Id>>1)^(Lin_Id>>3)^(Lin_Id>>4)^(Lin_Id>>5)))&0x01; //P1 = ~(ID1^ID3^ID4^ID5)
Lin_Id = Lin_Id | (Lin_P0<<6) | (Lin_P1<<7);
HAL_UART_Transmit(huart, &Lin_Id, 1, 0); //Transmit pid field
if((Lin_Version==UART_LIN_V2DX)&&(Lin_Id !=0x3C && Lin_Id!=0x3D))
Lin_Check_Sum = Lin_Id; //LIN 2.X check sum calc with PID.
if(Size)
{
for(ucI=0;ucI<Size;ucI++)
{
Lin_Check_Sum += pData[ucI];
if(Lin_Check_Sum>0xFF)
Lin_Check_Sum = ((Lin_Check_Sum>>8)+Lin_Check_Sum)&0xFF;
}
Lin_Check_Sum = (~Lin_Check_Sum) & 0xFF;
HAL_UART_Transmit(huart, pData, Size, 0); //Transmit data field
HAL_UART_Transmit(huart, (uint8_t*)&Lin_Check_Sum, 1, 0); //Transmit Lin_Check_Sum field
}
}
/************************************************************************
* function : HAL_UART_LIN_Slave_Transmit
* Description: Uart lin slave transmit data
* input :none
* UART_HandleTypeDef *huart: Serial port number
* uint8_t Lin_Version: LIN version ,should be UART_LIN_V1D3 or UART_LIN_V2DX.
* uint8_t Lin_Id: LIN id
* uint8_t *pData: point to the transmit data buffer.
* uint8_t Size: Transmit buffer Size.
* return: none
************************************************************************/
void HAL_UART_LIN_Slave_Transmit(UART_HandleTypeDef *huart, uint8_t Lin_Version, uint8_t Lin_Id, uint8_t *pData, uint8_t Size)
{
uint8_t ucI;
uint16_t Lin_Check_Sum = 0;
if((Size>8)||(pData == 0))
return;
CLEAR_BIT(huart->Instance->IE, UART_EX_IE_LBDI);//disable LBDI int
huart->Instance->CR = 0x0101; //disable uart_rx
if((Lin_Version==UART_LIN_V2DX)&&(Lin_Id !=0x3C && Lin_Id!=0x3D))
Lin_Check_Sum = Lin_Id; //LIN 2.X check sum calc with PID.
for(ucI=0;ucI<Size;ucI++)
{
Lin_Check_Sum += pData[ucI];
if(Lin_Check_Sum>0xFF)
Lin_Check_Sum = ((Lin_Check_Sum>>8)+Lin_Check_Sum)&0xFF;
}
Lin_Check_Sum = (~Lin_Check_Sum) & 0xFF;
HAL_UART_Transmit(huart, pData, Size, 0); //Transmit data field
HAL_UART_Transmit(huart, (uint8_t*)&Lin_Check_Sum, 1, 0); //Transmit Lin_Check_Sum field
}
/************************************************************************
* function : HAL_UART_LIN_Master_Receive
* Description: Uart lin master receive data
* input :none
* UART_HandleTypeDef *huart: Serial port number
* uint8_t Lin_Version: LIN version ,should be UART_LIN_V1D3 or UART_LIN_V2DX.
* uint8_t Lin_Id: LIN id
* uint8_t *pData: point to the data buffer.
* return: uint8_t RxSize
************************************************************************/
uint8_t HAL_UART_LIN_Master_Receive(UART_HandleTypeDef *huart, uint8_t Lin_Version, uint8_t Lin_Id, uint8_t *pData, uint32_t Timeout)
{
uint8_t ucI,RxSize;
uint8_t Lin_Rx_Buf[16];
uint16_t Lin_Check_Sum = 0;
if(pData == 0)
return 0;
huart->Instance->CR = 0x0201; //disable uart_tx
huart->Instance->ICR = 0xfff; //clear int
huart->Instance->LCRH = 0x70; //8 data bit,1 stop bit,0 verify bit,enable FIFO
huart->Instance->IFLS = 0x12; //FIFO send and receive number is 8
huart->Instance->IE = 0x00; //Disable all interrupt
HAL_UART_Receive(huart, Lin_Rx_Buf, sizeof(Lin_Rx_Buf), Timeout);
if((Lin_Version==UART_LIN_V2DX)&&(Lin_Id !=0x3C && Lin_Id!=0x3D))
Lin_Check_Sum = Lin_Id; //LIN 2.X check sum calc with PID.
if(huart->lu32_RxCount)
{
for(ucI=0;ucI<(huart->lu32_RxCount-1);ucI++)
{
Lin_Check_Sum += Lin_Rx_Buf[ucI];
if(Lin_Check_Sum>0xFF)
Lin_Check_Sum = ((Lin_Check_Sum>>8)+Lin_Check_Sum)&0xFF;
}
Lin_Check_Sum = (~Lin_Check_Sum) & 0xFF;
if((uint8_t)Lin_Check_Sum == Lin_Rx_Buf[ucI])
{
RxSize = huart->lu32_RxCount;
memcpy(pData, (uint8_t*)Lin_Rx_Buf, RxSize);
}
else
RxSize = 0xFF;
}
else
RxSize = 0;
return RxSize;
}
/************************************************************************
* function : HAL_UART_LIN_Slave_Receive
* Description: Uart lin slave receive head
* input :none
* UART_HandleTypeDef *huart: Serial port number
* uint8_t Lin_Version: LIN version ,should be UART_LIN_V1D3 or UART_LIN_V2DX.
* uint8_t *pData: point to the data buffer.
* return: uint8_t RxSize
************************************************************************/
uint8_t HAL_UART_LIN_Slave_Receive(UART_HandleTypeDef *huart, uint8_t Lin_Version, uint8_t *pData, uint32_t Timeout)
{
uint8_t ucI,RxSize;
uint8_t Lin_Rx_Buf[16];
uint16_t Lin_Check_Sum = 0;
uint32_t u32_Timeout;
if(pData == 0)
return 0;
huart->Instance->CR = 0x0201; //disable uart_tx
huart->Instance->ICR = 0xfff; //clear int
CLEAR_BIT(huart->Instance->IE, UART_EX_IE_LBDI); //Disable LBDI int
if (Timeout == 0)
{
while(!READ_BIT(huart->Instance->RIS, UART_EX_RIS_LBDI));
}
else
{
u32_Timeout = Timeout * 0xFF;
while(!READ_BIT(huart->Instance->RIS, UART_EX_RIS_LBDI))
{
if (u32_Timeout-- == 0)
{
return 0;
}
}
}
CLEAR_BIT(huart->Instance->RIS, UART_EX_RIS_LBDI);
huart->Instance->LCRH = 0x70; //8 data bit,1 stop bit,0 verify bit,enable FIFO
huart->Instance->IFLS = 0x12; //FIFO send and receive number is 8
huart->Instance->IE = 0x00; //Disable all interrupt
HAL_UART_Receive(huart, Lin_Rx_Buf, sizeof(Lin_Rx_Buf), Timeout); //waitting rx completed.
if(huart->lu32_RxCount > 3)
{
if((Lin_Version==UART_LIN_V2DX)&&(Lin_Rx_Buf[2] !=0x3C && Lin_Rx_Buf[2]!=0x3D))
Lin_Check_Sum = Lin_Rx_Buf[2]; //LIN 2.X check sum calc with PID.
if(huart->lu32_RxCount)
{
for(ucI=3;ucI<(huart->lu32_RxCount-1);ucI++)
{
Lin_Check_Sum += Lin_Rx_Buf[ucI];
if(Lin_Check_Sum>0xFF)
Lin_Check_Sum = ((Lin_Check_Sum>>8)+Lin_Check_Sum)&0xFF;
}
Lin_Check_Sum = (~Lin_Check_Sum) & 0xFF;
if((uint8_t)Lin_Check_Sum == Lin_Rx_Buf[ucI])
{
RxSize = huart->lu32_RxCount;
memcpy(pData, (uint8_t*)Lin_Rx_Buf, RxSize);
}
else
RxSize = 0xFF;
}
}
else if(huart->lu32_RxCount<=3)
{
RxSize = huart->lu32_RxCount;
memcpy(pData, (uint8_t*)Lin_Rx_Buf, RxSize);
}
else
RxSize = 0;
return RxSize;
}