/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url] SoftwareUARRT.c
* [url=home.php?mod=space&uid=895143]@version[/url] V1.00
* [url=home.php?mod=space&uid=247401]@brief[/url] M051 Using GPIO emulation UART driver source file
*
* @note
* Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include "SoftwareUART.h"
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables */
/*---------------------------------------------------------------------------------------------------------*/
sUART_Config g_sSoftwareUART_Config;
sUART_Config *g_psSoftwareUART_Config;
uint16_t g_au16TxBuff[256];
uint16_t g_au16RxBuff[256];
/*---------------------------------------------------------------------------------------------------------*/
/* Init SoftwareUART */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_Init(sUART_Config *psConfig)
{
/* Configure P2.6 as Input mode(Rx) */
GPIO_SetMode(P2, BIT6, GPIO_PMD_INPUT);
/* Configure P2.7 as Output mode(Tx) */
GPIO_SetMode(P2, BIT7, GPIO_PMD_OUTPUT);
/* Initial the SoftwareUART configuration setting */
SoftwareUART_ConfigInit(psConfig);
/* Configure SoftwareUART and set SoftwareUART baudrate */
SoftwareUART_Open(psConfig,115200);
}
/*---------------------------------------------------------------------------------------------------------*/
/* Init SoftwareUART configuration */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_ConfigInit(sUART_Config *psConfig)
{
g_psSoftwareUART_Config = psConfig;
psConfig->u32BaudRate = 0;
psConfig->u8DataBits = 0;
psConfig->u8Parity = 0;
psConfig->u8StopBit = 0;
psConfig->u8RxStatus = eRxIdel;
psConfig->u8TxStatus = eTxIdel;
psConfig->u8CommunBitsLen = 0;
psConfig->pu16TxBuff = &g_au16TxBuff[0];
psConfig->pu16RxBuff = &g_au16RxBuff[0];
psConfig->u32SendLen = 0;
psConfig->u32ReceiveLen = 0;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Init SoftwareUART interface */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_Open(sUART_Config *psConfig,uint32_t u32BaudRate)
{
uint32_t u32TimePeriodic;
psConfig->u32BaudRate = u32BaudRate;
/* Setting the UART Rx bit rate */
u32TimePeriodic = psConfig->u32BaudRate*2;
/* Open Timer0 frequency in periodic mode, and enable interrupt */
TIMER_Open(TIMER0,TIMER_PERIODIC_MODE,u32TimePeriodic);
/* Enable Timer0 INT */
TIMER_EnableInt(TIMER0);
/* Setting the UART Tx bit rate */
u32TimePeriodic = psConfig->u32BaudRate;
/* Open Timer0 frequency in periodic mode, and enable interrupt */
TIMER_Open(TIMER1,TIMER_PERIODIC_MODE,u32TimePeriodic);
/* Enable Timer0 INT */
TIMER_EnableInt(TIMER1);
SoftwareUART_DataFormartConfig(psConfig);
}
/*---------------------------------------------------------------------------------------------------------*/
/* SoftwareUART data format setting */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_DataFormartConfig(sUART_Config *psConfig)
{
psConfig->u8DataBits = 8; /* Setting data length is 8 bits */
psConfig->u8Parity = PARITY_NONE; /* No Parity */
psConfig->u8StopBit = STOP_BIT_1; /* 1 Stop bit */
psConfig->u8TxLatency = 2; /* Transmission interval is 2 bits rate */
psConfig->u32SendLen = 16; /* Send 16 bytes(Tx) */
psConfig->u32ReceiveLen = 16; /* Receive 16 bytes(Rx) */
/*Building UART Tx serial number*/
BuildTxDataPattern(psConfig);
/* Configure the parity bit */
SoftwareUART_ParityBitConfig(psConfig);
/* Configure the stop bit */
SoftwareUART_StopBitConfig(psConfig);
psConfig->u8CommunBitsLen = psConfig->u8DataBits;
if(psConfig->u8Parity != PARITY_NONE)
psConfig->u8CommunBitsLen += 1; /* Parity bit */
if(psConfig->u8StopBit != STOP_BIT_1)
psConfig->u8CommunBitsLen += 3; /* Start bit + 2 Stop bits */
else
psConfig->u8CommunBitsLen += 2; /* Start bit + 1 Stop bit*/
}
/*---------------------------------------------------------------------------------------------------------*/
/* SoftwareUART Tx Send Data */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_SendData(sUART_Config *psConfig)
{
uint32_t u32Index;
uint32_t u16SendData;
/* Enable Timer1 NVIC */
NVIC_EnableIRQ(TMR1_IRQn);
/* Start Timer1 counting */
TIMER_Start(TIMER1);
psConfig->u8TxStatus = eTxIdel;
psConfig->u8TxTiming =0;
for(u32Index=0 ;u32Index < psConfig->u32SendLen ;u32Index++)
{
GPIO_UART_TX = 1;
u16SendData = psConfig->pu16TxBuff[u32Index];
while( psConfig->u8TxStatus != eTxActive){};
psConfig->u8TxStatus = eTxSendData;
/* Use TIMER1 to emulate the bit rate of UART transmission */
do{
psConfig->u8TxTiming =0;
if((u16SendData & 0x01) == 0x01)
GPIO_UART_TX =1;
else
GPIO_UART_TX =0;
u16SendData = u16SendData >> 1;
while(psConfig->u8TxTiming == 0){};
/* Total bits Length(start bit(1) + data bits(5~8) + parity bit(0~1)+ stop bit(1~2)) */
}while(psConfig->u8TxSendCount < (psConfig->u8CommunBitsLen+ psConfig->u8TxLatency ));
psConfig->u8TxStatus = eTxIdel;
psConfig->u8TxSendCount =0;
}
/* Disable Timer1 NVIC */
NVIC_DisableIRQ(TMR1_IRQn);
/* Stop Timer1 counting */
TIMER_Stop(TIMER1);
}
/*---------------------------------------------------------------------------------------------------------*/
/* SoftwareUART Rx Receive Data */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_ReadData(sUART_Config *psConfig)
{
uint32_t u32Index;
uint8_t u8RxCount;
/* Enable Timer0 NVIC */
NVIC_EnableIRQ(TMR0_IRQn);
/* Start Timer0 counting */
TIMER_Start(TIMER0);
for(u32Index=0 ;u32Index < psConfig->u32ReceiveLen ;u32Index++)
{
u8RxCount = 0;
/* Use TIMER0 to emulate the bit rate of UART reception */
psConfig->u8RxTiming =0;
/* Wait to Receive the start bit */
while(GPIO_UART_RX == 1){};
psConfig->u8RxStatus = eRxRcvData;
do{
while(psConfig->u8RxTiming == 0){};
if(GPIO_UART_RX == 0)
psConfig->pu16RxBuff[u32Index] |= (0 << u8RxCount);
else
psConfig->pu16RxBuff[u32Index] |= (1 << u8RxCount);
psConfig->u8RxTiming =0;
while(psConfig->u8RxTiming == 0){};
psConfig->u8RxTiming =0;
u8RxCount++;
/* Total bits length(start bit(1) + data bits(5~8) + parity bit(0-1)+ stop bit(1~2)) */
}while(u8RxCount < psConfig->u8CommunBitsLen);
u8RxCount =0;
/* End of reception */
psConfig->u8RxStatus = eRxIdel;
psConfig->u8RxTiming =0;
}
/* Disable Timer0 NVIC */
NVIC_DisableIRQ(TMR0_IRQn);
/* Stop Timer0 counting */
TIMER_Stop(TIMER0);
for(u32Index=0 ;u32Index < psConfig->u32ReceiveLen ;u32Index++)
{
SoftwareUART_ReceiveDateParse(psConfig,u32Index);
psConfig->pu16RxBuff[u32Index] = 0;
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* Parse reduction receive data */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_ReceiveDateParse(sUART_Config *psConfig,uint32_t u32Index)
{
uint8_t u8ParityCheck;
uint8_t u8TempData;
uint8_t u8DataMask;
uint8_t u8ParityBit;
uint8_t u8StopBit;
/*Get the Parity bits number*/
u8DataMask = GetDataMsk(psConfig);
/*Check start bit*/
if((psConfig->pu16RxBuff[u32Index] & 0x01) !=0)
{
printf("Start Bit Error\n");
}
/*Remove start bit */
u8TempData = ((psConfig->pu16RxBuff[u32Index]>>1) & u8DataMask);
if(psConfig->u8Parity != PARITY_NONE)
{
/*Get the parity number */
u8ParityCheck = GetParityBitsNumber(psConfig,u8TempData);
/*Get Parity bit*/
u8ParityBit = ((psConfig->pu16RxBuff[u32Index] >> (psConfig->u8DataBits+1)) &0x1);
}
/*Check EVEN or ODD Parity bit*/
if( (psConfig->u8Parity == PARITY_EVEN ) || (psConfig->u8Parity == PARITY_ODD ) )
{
if(psConfig->u8Parity == PARITY_ODD)
{
if((u8ParityCheck % 2) == 0)
{
if(u8ParityBit != 1) printf("ODD Error\n");
}
else
{
if(u8ParityBit == 1) printf("ODD Error\n");
}
}
else
{
if((u8ParityCheck % 2) == 0)
{
if(u8ParityBit != 0) printf("Even Error\n");
}
else
{
if(u8ParityBit != 1) printf("Even Error\n");
}
}
}/*Check MARK Parity bit*/
else if(psConfig->u8Parity == PARITY_MARK)
{
if(u8ParityBit != 1) printf("MARK Error\n");
}/*Check Space Parity bit*/
else if(psConfig->u8Parity == PARITY_SPACE)
{
if(u8ParityBit != 0) printf("SPACE Error\n");
}
/*Check Stop bit*/
if(psConfig->u8Parity == PARITY_NONE)
u8StopBit = (psConfig->pu16TxBuff[u32Index] >> (psConfig->u8DataBits + 1));
else
u8StopBit = (psConfig->pu16TxBuff[u32Index] >> (psConfig->u8DataBits + 2));
if(psConfig->u8StopBit == STOP_BIT_1 )
{
if(u8StopBit != 1)printf("STOP bit Error\n");
}
else
{
if(u8StopBit != 3)printf("STOP bits Error\n");
}
psConfig->pu16RxBuff[u32Index] = u8TempData;
printf("Rx Data[%d] =0x%x\n",u32Index,psConfig->pu16RxBuff[u32Index]) ;
}
uint8_t GetDataMsk(sUART_Config *psConfig)
{
uint8_t u8DataMask;
if(psConfig->u8DataBits == 8) u8DataMask = 0xFF; /* 8 bits (0x0~0xFF) */
else if(psConfig->u8DataBits == 7) u8DataMask = 0x7F; /* 7 bits (0x0~0x7F) */
else if(psConfig->u8DataBits == 6) u8DataMask = 0x3F; /* 6 bits (0x0~0x3F) */
else u8DataMask = 0x1F; /* 5 bits (0x0~0x1F) */
return u8DataMask;
}
uint8_t GetParityBitsNumber(sUART_Config *psConfig,uint8_t u8Data)
{
uint8_t u8Index,u8ParityCheck;
u8ParityCheck =0;
for(u8Index = 0;u8Index < psConfig->u8DataBits ; u8Index++)
{
if((u8Data & (1 << u8Index)) != 0)
u8ParityCheck++;
}
return u8ParityCheck;
}
void BuildTxDataPattern(sUART_Config *psConfig)
{
uint32_t u32Index;
uint8_t u8DataMask;
u8DataMask = GetDataMsk(psConfig);
for(u32Index =0 ; u32Index < psConfig->u32SendLen ;u32Index++)
{
psConfig->pu16TxBuff[u32Index] = (u32Index & u8DataMask);
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* SoftwareUART Stop bit configuration */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_StopBitConfig(sUART_Config *psConfig)
{
uint32_t u32Index;
for(u32Index =0 ; u32Index < psConfig->u32SendLen ; u32Index++)
{
if(psConfig->u8StopBit == STOP_BIT_1 )
{
/* No Parity bit,offset value(start bit + data bits) */
if(psConfig->u8Parity == PARITY_NONE)
psConfig->pu16TxBuff[u32Index] |= (0x01 << (psConfig->u8DataBits + 1));
else /* offset offset value(start bit + data bits + parity bit) */
psConfig->pu16TxBuff[u32Index] |= (0x01 << (psConfig->u8DataBits + 2));
}
else
{
/* No Parity bit,offset value(start bit + data bits) */
if(psConfig->u8Parity == PARITY_NONE)
psConfig->pu16TxBuff[u32Index] |= (0x03 << (psConfig->u8DataBits + 1));
else /* offset value (start bit + data bits + parity bit) */
psConfig->pu16TxBuff[u32Index] |= (0x03 << (psConfig->u8DataBits + 2));
}
}
}
/*---------------------------------------------------------------------------------------------------------*/
/* SoftwareUART Parity bit configuration */
/*---------------------------------------------------------------------------------------------------------*/
void SoftwareUART_ParityBitConfig(sUART_Config *psConfig)
{
uint8_t u8ParityCheck;
uint32_t u32DatIndex;
for(u32DatIndex =0 ; u32DatIndex < psConfig->u32SendLen ; u32DatIndex++)
{
if((psConfig->u8Parity == PARITY_EVEN ) || (psConfig->u8Parity == PARITY_ODD ) )
{
u8ParityCheck = GetParityBitsNumber(psConfig,(uint8_t)psConfig->pu16TxBuff[u32DatIndex]);
if(psConfig->u8Parity == PARITY_ODD)
{
if((u8ParityCheck % 2) == 0)
psConfig->pu16TxBuff[u32DatIndex] = (psConfig->pu16TxBuff[u32DatIndex]<< 1) | (0x01 << (psConfig->u8DataBits+1));
else
psConfig->pu16TxBuff[u32DatIndex] = (psConfig->pu16TxBuff[u32DatIndex]<< 1);
}
else
{
if((u8ParityCheck % 2) == 1)
psConfig->pu16TxBuff[u32DatIndex] = (psConfig->pu16TxBuff[u32DatIndex]<< 1)|(0x01 << (psConfig->u8DataBits+1));
else
psConfig->pu16TxBuff[u32DatIndex] = (psConfig->pu16TxBuff[u32DatIndex]<< 1);
}
}
else if(psConfig->u8Parity == PARITY_MARK)
{
psConfig->pu16TxBuff[u32DatIndex] = (psConfig->pu16TxBuff[u32DatIndex]<< 1)|(0x01 << (psConfig->u8DataBits+1));
}
else
{
psConfig->pu16TxBuff[u32DatIndex] = (psConfig->pu16TxBuff[u32DatIndex]<< 1);
}
}
}
/**
* @brief Timer0 IRQ
*
* @param None
*
* [url=home.php?mod=space&uid=266161]@return[/url] None
*
* [url=home.php?mod=space&uid=1543424]@Details[/url] The Timer0 default IRQ, declared in startup_M051Series.s.
*/
void TMR0_IRQHandler(void)
{
/* Clear Timer0 time-out interrupt flag */
TIMER_ClearIntFlag(TIMER0);
/* Receiving data */
if( g_psSoftwareUART_Config->u8RxStatus == eRxRcvData)
g_psSoftwareUART_Config->u8RxTiming = 1;
}
/**
* @brief Timer1 IRQ
*
* @param None
*
* @return None
*
* @details The Timer1 default IRQ, declared in startup_M051Series.s.
*/
void TMR1_IRQHandler(void)
{
/* Clear Timer1 time-out interrupt flag */
TIMER_ClearIntFlag(TIMER1);
g_psSoftwareUART_Config->u8TxSendCount++;
/*Wait for the Tx transfer start bit to complete*/
if(g_psSoftwareUART_Config->u8TxStatus == eTxIdel)
{
if(g_psSoftwareUART_Config->u8TxSendCount == g_psSoftwareUART_Config->u8TxLatency)
g_psSoftwareUART_Config->u8TxStatus = eTxActive;
}/* Tx transfer timing */
else if(g_psSoftwareUART_Config->u8TxStatus == eTxSendData)
g_psSoftwareUART_Config->u8TxTiming = 1;
}
/*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/
|