GD32E23x GPIO 模拟串口
时间:2023-09-01 00:37:01
三个项目需要使用UART, 但只有两个系列UART.
只好模拟一个使用。
因此,本文通过使用两篇文章GPIO 口,加 定时器, 来达到 模拟串口的 功能。
代码仅供参考:
1. IO_USART.h
#include "gd32e23x.h" #define Number_Of_softUarts 1 #define SoftUartTxBufferSize 32 #define SoftUartRxBufferSize 64 #define SoftUart_DATA_LEN 8 // Max 8 Bit //ADD #ifndef SoftUartID #define SoftUartID 0 #endif #define SOFTUART_COUNTER_PERIOD 20 //end typedef enum { SoftUart_OK, SoftUart_Error }SoftUartState_E; typedef struct{ uint8_t Tx[SoftUartTxBufferSize]; uint8_t Rx[SoftUartTxBufferSize]; }SoftUartBuffer_S; typedef struct{ __IO uint8_t TxNComplated; uint8_t TxEnable; uint8_t RxEnable; uint8_t TxBitShift,TxBitCounter; uint8_t RxBitShift,RxBitCounter; uint8_t TxIndex,TxSize; uint8_t RxIndex; SoftUartBuffer_S *Buffer; uint32_t TxPort; uint16_t TxPin; uint32_t RxPort; uint16_t RxPin; uint8_t RxTimingFlag; uint8_t RxBitOffset; }SoftUart_S; void SoftUartHandler(void); void SoftUartWaitUntilTxComplete(uint8_t SoftUartNumber); uint8_t SoftUartRxAlavailable(uint8_t SoftUartNumber); SoftUartState_E SoftUartPuts(uint8_t SoftUartNumber,uint8_t *Str,uint8_t Len); SoftUartState_E SoftUartEnableRx(uint8_t SoftUartNumber); SoftUartState_E SoftUartDisableRx(uint8_t SoftUartNumber); SoftUartState_E SoftUartInit(uint8_t SoftUartNumber,uint32_t TxPort,uint16_t TxPin,uint32_t RxPort,uint16_t RxPin); SoftUartState_E SoftUartReadRxBuffer(uint8_t SoftUartNumber,uint8_t* Buffer,uint8_t Len); void SoftUart_GPIO_Config(uint32_t TxPort,uint16_t TxPin,uint32_t RxPort,uint16_t RxPin); void SoftUartTimerConfig(uint32_t timer_n,rcu_periph_enum periph,uint32_t periods);
2.IO_USART.c
#include "IO_USART.h" /**/ // Some internal define #define SoftUart_DATA_LEN_C1 (SoftUart_DATA_LEN 1) #define SoftUart_DATA_LEN_C2 (SoftUart_DATA_LEN 2) SoftUart_S SUart[Number_Of_softUarts]; // TX RX Data Buffer SoftUartBuffer_S SUBuffer[Number_Of_softUarts]; // For timing division __IO uint8_t SU_Timer=0; static FlagStatus SoftUartGpioReadPin(uint32_t gpio_periph, uint32_t pin){ return gpio_input_bit_get(gpio_periph,pin); } // Write TX single Pin Value static void SoftUartGpioWritePin(uint32_t gpio_periph, uint32_t pin,FlagStatus Pinstate){ gpio_bit_write(gpio_periph,pin,Pinstate); } // Initial Soft Uart SoftUartState_E SoftUartInit(uint8_t SoftUartNumber,uint32_t TxPort,uint16_t TxPin,uint32_t RxPort,uint16_t RxPin) { if(SoftUartNumber>=Number_Of_softUarts)return SoftUart_Error; //ADD SoftUart_GPIO_Config(TxPort,TxPin,RxPort,RxPin); SUart[SoftUartNumber].TxNComplated=0; SUart[SoftUartNumber].RxBitCounter=0; SUart[SoftUartNumber].RxBitShift=0; SUart[SoftUartNumber].RxIndex=0; SUart[SoftUartNumber].TxEnable=0; SUart[SoftUartNumber].RxEnable=0; SUart[SoftUartNumber].TxBitCounter=0; SUart[SoftUartNumber].TxBitShift=0; SUart[SoftUartNumber].TxIndex=0; SUart[SoftUartNumber].TxSize=0; SUart[SoftUartNumber].Buffer=&SUBuffer[SoftUartNumber]; SUart[SoftUartNumber].RxPort=RxPort; SUart[SoftUartNumber].RxPin=RxPin; SUart[SoftUartNumber].TxPort=TxPort; SUart[SoftUartNumber].TxPin=TxPin; SUart[SoftUartNumber].RxTimingFlag=0; SUart[SoftUartNumber].RxBitOffset=0; return SoftUart_OK; } static void SoftUartTransmitBit(SoftUart_S *SU,uint8_t Bit0_1){ SoftUartGpioWritePin(SU->TxPort,SU->TxPin,(FlagStatus)Bit0_1); } SoftUartState_E SoftUartEnableRx(uint8_t SoftUartNumber){ if(SoftUartNumber >= Number_Of_softUarts)return SoftUart_Error; SUart[SoftUartNumber].RxEnable = 1; return SoftUart_OK; } SoftUartState_E SoftUartDisableRx(uint8_t SoftUartNumber){ if(SoftUartNumber >= Number_Of_softUarts)return SoftUart_Error; SUart[SoftUartNumber].RxEnable = 0; return SoftUart_OK; } uint8_t SoftUartRxAlavailable(uint8_t SoftUartNumber){ return SUart[SoftUartNumber].RxIndex; } SoftUartState_E SoftUartReadRxBuffer(uint8_t SoftUartNumber,uint8_t* Buffer,uint8_t Len){ int i; if(SoftUartNumber >= Number_Of_softUarts)return SoftUart_Error; for ( i = 0; i < Len; i ) { /* code */ Buffer[i] = SUart[SoftUartNumber].Buffer->Rx[i]; } for ( i = 0; i < SUart[SoftUartNumber].RxIndex; i ) { /* code */ SUart[SoftUartNumber].Buffer->Rx[i] = SUart[SoftUartNumber].Buffer->Rx[i Len]; } SUart[SoftUartNumber].RxIndex -=Len; return SoftUart_OK; } // Soft Uart Transmit Data Process static void SoftUartTxProcess(SoftUart_S *SU) { if(SU->TxEnable) { // Start if(SU->TxBitCounter==0) { SU->TxNComplated=1; SU->TxBitShift=0; SoftUartTransmitBit(SU,0); SU->TxBitCounter ; } // Data else if(SU->TxBitCounterBuffer->Tx[SU->TxIndex])>>(SU->TxBitShift))&0x01);
SU->TxBitCounter++;
SU->TxBitShift++;
}
// Stop
else if(SU->TxBitCounter==SoftUart_DATA_LEN_C1)
{
SoftUartTransmitBit(SU,1);
SU->TxBitCounter++;
}
//Complete
else if(SU->TxBitCounter==SoftUart_DATA_LEN_C2)
{
// Reset Bit Counter
SU->TxBitCounter=0;
// Ready To Send Another Data
SU->TxIndex++;
// Check Size of Data
if(SU->TxSize > SU->TxIndex)
{
// Continue Sending
SU->TxNComplated=1;
SU->TxEnable=1;
}
else
{
// Finish
SU->TxNComplated=0;
SU->TxEnable=0;
//printf(" Send Finish\r\n");
}
}
}
}
// Soft Uart Receive Data Process
static void SoftUartRxDataBitProcess(SoftUart_S *SU,uint8_t B0_1)
{
if(SU->RxEnable)
{
// Start
if(SU->RxBitCounter==0)
{
// Start Bit is 0
if(B0_1)return;
SU->RxBitShift=0;
SU->RxBitCounter++;
SU->Buffer->Rx[SU->RxIndex]=0;
}
// Data
else if(SU->RxBitCounterBuffer->Rx[SU->RxIndex]|=((B0_1&0x01)<RxBitShift);
SU->RxBitCounter++;
SU->RxBitShift++;
}
// Stop and Complete
else if(SU->RxBitCounter==SoftUart_DATA_LEN_C1)
{
SU->RxBitCounter=0;
SU->RxTimingFlag=0;
//Stop Bit must be 1
if(B0_1)
{
// Received successfully
// Change RX Buffer Index
if((SU->RxIndex)<(SoftUartRxBufferSize-1))(SU->RxIndex)++;
}
// if not : ERROR -> Overwrite data
}
}
}
// Wait Until Transmit Completed
// You do not usually need to use this function!
void SoftUartWaitUntilTxComplete(uint8_t SoftUartNumber)
{
while(SUart[SoftUartNumber].TxNComplated);
}
// Copy Data to Transmit Buffer and Start Sending
SoftUartState_E SoftUartPuts(uint8_t SoftUartNumber,uint8_t *Str,uint8_t Len)
{
int i;
if(SoftUartNumber>=Number_Of_softUarts)return SoftUart_Error;
if(SUart[SoftUartNumber].TxNComplated) return SoftUart_Error;
SUart[SoftUartNumber].TxIndex=0;
SUart[SoftUartNumber].TxSize=Len;
for(i=0;iTx[i]= Str[i];
}
SUart[SoftUartNumber].TxNComplated=1;
SUart[SoftUartNumber].TxEnable=1;
//printf("SoftUartPuts OK ok \r\n");
return SoftUart_OK;
}
// Capture RX and Get BitOffset
static uint8_t SoftUartScanRxPorts(void)
{
int i;
uint8_t Buffer=0x00,Bit;
for(i=0;i>i)&0x01));
}
}
// Sending always happens in the first time slot
if(SU_Timer==0)
{
// Transmit Data
for(i=0;i < Number_Of_softUarts;i++)
{
SoftUartTxProcess(&SUart[i]);
}
}
// Timing process
SU_Timer++;
if(SU_Timer >= 5){
SU_Timer=0;
}
}
void SoftUart_GPIO_Config(uint32_t TxPort,uint16_t TxPin,uint32_t RxPort,uint16_t RxPin){
gpio_mode_set(TxPort, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, TxPin);
gpio_output_options_set(TxPort, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, TxPin);
gpio_mode_set(RxPort, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, RxPin);
gpio_output_options_set(RxPort, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RxPin);
}
void SoftUartTimerConfig(uint32_t timer_n,rcu_periph_enum periph,uint32_t periods){
timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;
/* enable the peripherals clock */
rcu_periph_clock_enable(periph);
/* deinit a TIMER */
timer_deinit(timer_n);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER2 configuration */
timer_initpara.prescaler = 74;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = (periods-1);
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_init(timer_n, &timer_initpara);
/* clear channel 0 interrupt bit */
timer_interrupt_flag_clear(timer_n, TIMER_INT_FLAG_UP);
/* enable the TIMER interrupt */
timer_interrupt_enable(timer_n, TIMER_INT_UP);
/* enable a TIMER */
timer_enable(timer_n);
//add ...
nvic_irq_enable(TIMER16_IRQn, 0);
}
void TIMER16_IRQHandler(void){
if(SET == timer_interrupt_flag_get(TIMER16, TIMER_INT_FLAG_UP)){
/* clear channel 0 interrupt bit */
timer_interrupt_flag_clear(TIMER16, TIMER_INT_FLAG_UP);
SoftUartHandler();
}
}
//for example:
//1. init timer::
// SoftUartTimerConfig(TIMER16,RCU_TIMER16,20);
//2. next :
// SoftUartInit(0,GPIOA,GPIO_PIN_5,GPIOA,GPIO_PIN_6);
//:
3. main.c
#include "IO_USART.h"
int main()
{
uint8_t SoftUartRx;
uint8_t i= 0;
uint8_t mm_Rx[SoftUartTxBufferSize]={0};
systick_config();
gd_eval_com_init(EVAL_COM);
SoftUartInit(SoftUartID,GPIOA,GPIO_PIN_5,GPIOA,GPIO_PIN_6);//A5->Tx A6->Rx
SoftUartTimerConfig(TIMER16,RCU_TIMER16,SOFTUART_COUNTER_PERIOD);
SoftUartEnableRx(SoftUartID);//使能接收
while (1)
{
delay_1ms(500);
delay_1ms(500);
SoftUartRx = SoftUartRxAlavailable(SoftUartID);
if(SoftUartRx > 0){
memset(mm_Rx,0,SoftUartTxBufferSize);
SoftUartReadRxBuffer(SoftUartID,mm_Rx,SoftUartRx);
for(i=0;i
STM32 见github地址: