GD32E23x GPIO 模拟串口

news/2024/11/17 4:29:12/

因项目需要使用3个UART,  但该系列只有2个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
//endtypedef 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;//ADDSoftUart_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){// Startif(SU->TxBitCounter==0){SU->TxNComplated=1;SU->TxBitShift=0;SoftUartTransmitBit(SU,0);SU->TxBitCounter++;}// Dataelse if(SU->TxBitCounter<SoftUart_DATA_LEN_C1){SoftUartTransmitBit(SU,((SU->Buffer->Tx[SU->TxIndex])>>(SU->TxBitShift))&0x01);SU->TxBitCounter++;SU->TxBitShift++;}// Stopelse if(SU->TxBitCounter==SoftUart_DATA_LEN_C1){SoftUartTransmitBit(SU,1);SU->TxBitCounter++;}//Completeelse if(SU->TxBitCounter==SoftUart_DATA_LEN_C2){// Reset Bit CounterSU->TxBitCounter=0;// Ready To Send Another DataSU->TxIndex++;// Check Size of Dataif(SU->TxSize > SU->TxIndex){// Continue SendingSU->TxNComplated=1;SU->TxEnable=1;}else{// FinishSU->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){// Startif(SU->RxBitCounter==0){// Start Bit is 0if(B0_1)return;SU->RxBitShift=0;SU->RxBitCounter++;SU->Buffer->Rx[SU->RxIndex]=0;}// Dataelse if(SU->RxBitCounter<SoftUart_DATA_LEN_C1){SU->Buffer->Rx[SU->RxIndex]|=((B0_1&0x01)<<SU->RxBitShift);SU->RxBitCounter++;SU->RxBitShift++;}// Stop and Completeelse if(SU->RxBitCounter==SoftUart_DATA_LEN_C1){SU->RxBitCounter=0;SU->RxTimingFlag=0;//Stop Bit must be 1if(B0_1){// Received successfully// Change RX Buffer Indexif((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;i<Len;i++){SUart[SoftUartNumber].Buffer->Tx[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<Number_Of_softUarts;i++){// Read RX GPIO ValueBit=SoftUartGpioReadPin(SUart[i].RxPort,SUart[i].RxPin);// Starting conditionsif(!SUart[i].RxBitCounter && !SUart[i].RxTimingFlag && !Bit){// Save RX Bit Offset// Calculate middle position of data pulsSUart[i].RxBitOffset=((SU_Timer+2)%5);// Timing Offset is SetSUart[i].RxTimingFlag=1;}// Add all RX GPIO State to BufferBuffer|=((Bit&0x01)<<i);}return Buffer;
}// SoftUartHandler must call in interrupt every 0.2*(1/BR)
// if BR=9600 then 0.2*(1/9600)=20.8333333 uS
void SoftUartHandler(void){int     	i;uint8_t 	SU_DBuffer;// Capture RX and Get BitOffsetSU_DBuffer = SoftUartScanRxPorts();for(i=0;i < Number_Of_softUarts;i++){// Receive Data if we in middle data pulse positionif(SUart[i].RxBitOffset == SU_Timer){SoftUartRxDataBitProcess(&SUart[i],((SU_DBuffer>>i)&0x01));}}// Sending always happens in the first time slotif(SU_Timer==0){// Transmit Datafor(i=0;i < Number_Of_softUarts;i++){SoftUartTxProcess(&SUart[i]);}}// Timing processSU_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->RxSoftUartTimerConfig(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<SoftUartRx;i++){printf("Rx,i:%d__    0x%x, \r\n",i,mm_Rx[i]);}SoftUartPuts(SoftUartID,mm_Rx,SoftUartRx);}}return 0;
}

STM32 见github地址:

STM32 模拟串口 的使用 - github地址


http://www.ppmy.cn/news/796575.html

相关文章

maven伺服搭建_Maven私服搭建

1、下载配置nexus&#xff0c;创建对应仓库 2、Maven接入 在Android工程根目录build.gradle中配置 buildscript { repositories { google() jcenter() mavenCentral() maven{ url http://localhost:8081/repository/imooc-releases/ credentials{ username admin password admi…

[bmim][Tf2N]离子液体(IL)负载UiO-66-PEI

[bmim][Tf2N]离子液体&#xff08;IL&#xff09;负载UiO-66-PEI 离子液体&#xff08;IL&#xff09;改性的UiO-66-NH2填料被引入微孔有机聚合物材料&#xff08;PIM-1&#xff09;中&#xff0c;以通过涂层改性和底漆制备致密且无缺陷的混合基质膜。IL[bmim][Tf2N]不仅提高了…

获得淘宝商品详情高级版api接口

item_get_pro-获得淘宝商品详情高级版 注册开通key测试 API返回结果完整数据 { "item": { "num_iid": "520813250866", "title": "三刃木折叠刀创意迷你钥匙扣钥匙刀户外随身多功能锋利开箱小刀", "desc_short"…

2021-05-07

支持测试 Result Object: { “item”: { “num_iid”: “520813250866”, “title”: “三刃木折叠刀过安检创意迷你钥匙扣钥匙刀军刀随身多功能小刀包邮”, “desc_short”: “”, “price”: “25.8”, “total_price”: 0, “suggestive_price”: 0, “orginal_price”: “…

高斯输出文件批量读取能量

批量读取能量 问题背景解决办法后记 问题背景 在量化计算时&#xff0c;能量是比较重要的概念&#xff0c;而在高斯的输出文件中能量数值往往藏在巨大的文本文件.log中。根据计算任务的大小&#xff0c;.log文件大小也有变化&#xff0c;不过日常计算中获得的文件基本大于十万…

怎么获取淘宝商品详情

Request address: num_iid520813234250866&is_promotion1&api_nameitem_get&langzh-CN&keytest_api_key&secret CN&keytest_api_key&secret Result Object: 请点击注册测试 { “item”: { “num_iid”: “520813234250866”, “title”: “三刃木…

利用高斯和Amber生成乙酰辅酶A配体的拓扑文件

最近在做带有乙酰辅酶A为配体的复合物动力学模拟&#xff0c;前期工作摸索了很久&#xff0c;也参考了很多资料&#xff0c;尤其是生成小分子拓扑的过程。这里想记录一下学习步骤。 在利用Amber生成乙酰辅酶A拓扑之前&#xff0c;需要先计算和拟合它的静电势。 打开GaussView软…

gaussian 初步 input file 的编写

input file basic form usually to calculate HOMO and LUMO, we first optimize the structure and then we calculate the energy&#xff08;单点能&#xff09;&#xff0c;which includes the kinetic and potential energy of the electrons. To calulate the optimaze…