- /**************************************************************************//**
- * [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. ***/
|