分享一个自己写的模拟串口,功能还不完善,可以自己修改

2019-08-17 04:09发布

#define        SimUartRxMax        100                //最大65535
#define        SimUartTxMax        100                //最大65535

enum{NoFinish = 0, Finish = 1};
enum{TxFinish = 0, TxStart = 1, TxData = 2, TxStop = 3, WaitStop = 4};
enum{RxFinish = 0, RxStart = 1, RxData = 2, RxStop = 3, WaitFinish = 4};
enum{LowEL = 0, HighEL = 1};
typedef enum{TXIDLEING, TXSENDING, RXIDLEING, RXRECEING} SimUartState;
typedef        enum{NOERROR = 0, TXOVERLENGTH, TXBUSYING}SimUartError;

typedef        struct
{
        volatile        unsigned char TxCache;
        volatile         unsigned char        TxFlag;
        volatile         unsigned char        TxMask;
        volatile        unsigned char        RxCache;
        volatile        unsigned char RxFlag;
        volatile         unsigned char RxMask;
        volatile         SimUartState TxState;
        volatile         SimUartState RxState;
       
}SimUartManage;


typedef struct
{
        volatile        SimUartManage SelfSimUartManage;
       
        volatile        unsigned char RxBuffer[SimUartRxMax];
        volatile        unsigned char TxBuffer[SimUartTxMax];
        volatile         unsigned short RxCnt;
        volatile        unsigned char RxFFlag;
        volatile         unsigned short TxCnt;
        volatile        unsigned short TxLength;
       
}SimUartRxTxControl;

typedef        volatile SimUartRxTxControl * SimUartRxTxControlPrtType;

#define        TIMERTYPEMACRO        TIM_HandleTypeDef

typedef        unsigned char (* READGPIO)(unsigned short);
typedef        void        (* WRITEGPIO)(unsigned short, unsigned char);
typedef void         (* UARTPROTOCOL)(SimUartRxTxControlPrtType);
typedef void        (* SETTIMERCOUNT)(TIMERTYPEMACRO ,unsigned short);



//        volatile SimUartRxTxControl MySimUartRxTxControl;
//        SimUartRxTxControlPrtType MySimUartRxTxControlPrt
//        unsigned char MyReadGPIO(unsigned short Pin);
//        void        MyWirtGPIO(unsigned short Pin, unsigned char Value);
//        void         MyUartRxProtocol(SimUartRxTxControlPrtType MySimUartRxTxControlPrt);
//        void        MySetTimerCounter(TIMERTYPEMACRO Timer,unsigned short Value);

SimUartState GetSimUartTxState(SimUartRxTxControlPrtType SimUartRxTxControlPrt)
{
        return SimUartRxTxControlPrt->SelfSimUartManage.TxState;
}

SimUartState GetSimUartRxState(SimUartRxTxControlPrtType SimUartRxTxControlPrt)
{
        return SimUartRxTxControlPrt->SelfSimUartManage.RxState;
}

void OneTimerBitRxTx(SimUartRxTxControlPrtType SimUartRxTxControlPrt,
                                                                                READGPIO ReadGPIO,unsigned short RxPin,WRITEGPIO WriteGPIO, unsigned short TxPin,UARTPROTOCOL UartRxProtocol)
{
                if(RxFinish != SimUartRxTxControlPrt->SelfSimUartManage.RxFlag)
                {
                        SimUartRxTxControlPrt->SelfSimUartManage.RxState = RXRECEING;
                        switch(SimUartRxTxControlPrt->SelfSimUartManage.RxFlag)
                        {
                                case RxStart:
                                        (LowEL == ReadGPIO(RxPin)) ? (SimUartRxTxControlPrt->SelfSimUartManage.RxFlag = RxData) : (SimUartRxTxControlPrt->SelfSimUartManage.RxFlag = RxFinish);
                                        SimUartRxTxControlPrt->SelfSimUartManage.RxCache = 0;
                                        SimUartRxTxControlPrt->SelfSimUartManage.RxMask = 0x01;
                                break;
                                case RxData:
                                        if(LowEL != ReadGPIO(RxPin))
                                        {
                                                SimUartRxTxControlPrt->SelfSimUartManage.RxCache |= SimUartRxTxControlPrt->SelfSimUartManage.RxMask;
                                        }
                                        SimUartRxTxControlPrt->SelfSimUartManage.RxMask <<= 1;
                                        if(0 == SimUartRxTxControlPrt->SelfSimUartManage.RxMask)
                                        {
                                                SimUartRxTxControlPrt->SelfSimUartManage.RxFlag = RxStop;
                                        }
                                break;
                                case RxStop:
                                        (LowEL == ReadGPIO(RxPin)) ? (SimUartRxTxControlPrt->SelfSimUartManage.RxFlag = RxFinish) : (SimUartRxTxControlPrt->SelfSimUartManage.RxFlag = WaitFinish);
                                        if(WaitFinish == SimUartRxTxControlPrt->SelfSimUartManage.RxFlag)
                                        {
                                                SimUartRxTxControlPrt->SelfSimUartManage.RxFlag = RxFinish;
                                                if(NoFinish == SimUartRxTxControlPrt->RxFFlag)
                                                {
                                                        SimUartRxTxControlPrt->RxBuffer[SimUartRxTxControlPrt->RxCnt] = SimUartRxTxControlPrt->SelfSimUartManage.RxCache;
                                                        SimUartRxTxControlPrt->RxCnt ++;
                                                        UartRxProtocol(SimUartRxTxControlPrt);
                                                        if(SimUartRxTxControlPrt->RxCnt >= SimUartRxMax)
                                                        {
                                                                SimUartRxTxControlPrt->RxFFlag = Finish;
                                                                SimUartRxTxControlPrt->RxCnt = 0;
                                                        }
                                                }
                                        }
                                break;
                        }
                }
                if(RxFinish == SimUartRxTxControlPrt->SelfSimUartManage.RxFlag)
                {
                        SimUartRxTxControlPrt->SelfSimUartManage.RxState = RXIDLEING;
                }
               
                if(TxFinish != SimUartRxTxControlPrt->SelfSimUartManage.TxFlag)
                {
                        switch(SimUartRxTxControlPrt->SelfSimUartManage.TxFlag)
                        {
                                case TxStart:
                                        WriteGPIO(TxPin, LowEL);
                                        SimUartRxTxControlPrt->SelfSimUartManage.TxFlag = TxData;
                                        SimUartRxTxControlPrt->SelfSimUartManage.TxMask = 0x01;
                                break;
                                       
                                case TxData:
                                        if(SimUartRxTxControlPrt->SelfSimUartManage.TxCache & SimUartRxTxControlPrt->SelfSimUartManage.TxMask)
                                        {
                                                WriteGPIO(TxPin, HighEL);
                                        }
                                        else
                                        {
                                                WriteGPIO(TxPin, LowEL);
                                        }
                                        SimUartRxTxControlPrt->SelfSimUartManage.TxMask <<= 1;
                                        if(0 == SimUartRxTxControlPrt->SelfSimUartManage.TxMask)
                                        {
                                                SimUartRxTxControlPrt->SelfSimUartManage.TxFlag = TxStop;
                                        }
                                break;
                               
                                case TxStop:
                                        WriteGPIO(TxPin, HighEL);
                                        SimUartRxTxControlPrt->SelfSimUartManage.TxFlag = WaitStop;
                                break;
                               
                                case WaitStop:
                                        if(SimUartRxTxControlPrt->TxCnt == SimUartRxTxControlPrt->TxLength)
                                        {
                                                SimUartRxTxControlPrt->SelfSimUartManage.TxFlag = TxFinish;
                                                SimUartRxTxControlPrt->TxCnt = 0;
                                                SimUartRxTxControlPrt->TxLength = 0;
                                                SimUartRxTxControlPrt->SelfSimUartManage.TxState = TXIDLEING;
                                        }
                                        else
                                        {
                                                SimUartRxTxControlPrt->SelfSimUartManage.TxFlag = TxStart;
                                                SimUartRxTxControlPrt->SelfSimUartManage.TxCache = SimUartRxTxControlPrt->TxBuffer[SimUartRxTxControlPrt->TxCnt];
                                                SimUartRxTxControlPrt->TxCnt ++;
                                        }
                                break;
                        }
                }       
}


SimUartError SimUartRxEXTIOHandler(SimUartRxTxControlPrtType SimUartRxTxControlPrt, SETTIMERCOUNT SetTimerCounter,TIMERTYPEMACRO Timer, unsigned short Value)
{
                if(RxFinish == SimUartRxTxControlPrt->SelfSimUartManage.RxFlag)
                {
                        SimUartRxTxControlPrt->SelfSimUartManage.RxFlag = RxStart;
                        SimUartRxTxControlPrt->SelfSimUartManage.RxState = RXRECEING;
                       
                        //添加清除定时器中断的指令
                        SetTimerCounter(Timer, Value);
                }
       
        return NOERROR;
}


//1:成功 0:由于忙而失败 3:由于超过发送长度而失败(并不是发送最长)
SimUartError  SimUart_TxByte(SimUartRxTxControlPrtType SimUartRxTxControlPrt, const unsigned char *SendBuffer, size_t SendSize)
{
        if(TXIDLEING == GetSimUartTxState(SimUartRxTxControlPrt))
        {
                size_t        counter;
                if(SendSize >= SimUartTxMax)
                        return TXOVERLENGTH;
               
                SimUartRxTxControlPrt->SelfSimUartManage.TxState = TXSENDING;
                for(counter = 0; counter < SendSize; counter ++)
                {
                        SimUartRxTxControlPrt->TxBuffer[counter] = *(SendBuffer + counter);
                }
                SimUartRxTxControlPrt->TxLength = SendSize;
                SimUartRxTxControlPrt->SelfSimUartManage.TxFlag = TxStart;
                SimUartRxTxControlPrt->TxCnt = 0;
                SimUartRxTxControlPrt->SelfSimUartManage.TxCache = SimUartRxTxControlPrt->TxBuffer[SimUartRxTxControlPrt->TxCnt];
                SimUartRxTxControlPrt->TxCnt ++;
               
                return NOERROR;
        }
        else
        {
                return TXBUSYING;
        }
}

1、此模拟串口的实现使用的时一个线中断做Rx,一个定时器实现收发时序;
2、代码中红 {MOD}的部分需要用户自己去实现或者修改;
3、用户可以根据结构体成员的属性去实现一些更丰富的接口函数,例如:设置收发状态,重设收发为空闲状态等;
4、可以使用严格的宏定义来实现多个模拟串口的建立和编译前差错等等;
5、当然接收部分写的比较简单,没有做一些报错和纠错的功能,感兴趣的同志可以发挥自己所能看能否写的如硬件串口一般坚硬。


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。