gwsan 发表于 2021-6-5 21:15

单片机软件系统框架和多任务调度

这里我用的单片机算是中颖的sh79f9401芯片


gwsan 发表于 2021-6-5 21:15

UART底层驱动相关函数:
       
                //UART相关寄存器初始化
                void Uart_Init(void)
                {
                        PCON = 0x00;//选择SSTAT0
                        SCON = 0x50;//01000000方式一
                        SBRTL = (u8int)(_SBRT & 0xFF);
                        SBRTH= (u8int)((0x80)|((_SBRT >> 8) & 0xFF));
                        SFINE = _SFINE;
                        ES0 = 1;//允许EUART0中断
                }
               
                //UART中断服务程序
                void        EUART_0_ISP(void) interrupt 4
                {
                        if(TI)
                        {
                                TI = 0;
                                Drv_Uart_Tx_It_Handle(UART_PORT_0);
                        }
                        if(RI)
                        {
                                RI = 0;
                                Drv_Uart_Rx_It_Handle(UART_PORT_0,SBUF);
                        }
                }
               
                //UART发送一Byte数据
                void Drv_Hardware_uart_SendByte(UART_PORT_TYPE ePort,char Data)
                {
                        if(ePort == UART_PORT_0)
                        {
                                ACC = Data;
                                SBUF = ACC;载入要发送的数据       
                        }
                }


gwsan 发表于 2021-6-5 21:16

中间层UART相关函数:
                #define _DRV_UART_C_
                #include "drv.h"
                #include "mw_uart.h"
               
                //这里是发送和接受数据的缓冲区
                u8int Uart_0_TxBuf = {0};//UART_0_TX_SIZE在uart.h头文件里根据需求和硬件资源自定义大小
                u8int Uart_0_RxBuf = {0};//UART_0_RX_SIZE在uart.h头文件里根据需求和硬件资源自定义大小
               
                //UART相关结构体
                typedef struct
                {
                        u8int * pu8TxAdd;//添加数据的地址,该地址数据无效
                        u8int * pu8TxValid;//有效数据的首
                        u8int * pu8TxMinAddr;//缓冲区最小地址
                        u8int * pu8TxMaxAddr;//缓冲区最大地址
                        u8int u8TxBufDataSize;//缓冲区已使用空间,有效数据大小
                        BOOL bTxIsStop;//中断是否在发送标记
               
                        u8int * pu8RxAdd;
                        u8int * pu8RxValid;
                        u8int * pu8RxMinAddr;
                        u8int * pu8RxMaxAddr;
                        u8int u8RxBufDataSize;
                }DRV_UART_INFO;
                DRV_UART_INFO sDrvUartInfo;
               


gwsan 发表于 2021-6-5 21:17

//初始化UART数据缓冲区
                void MW_Uart_Data_Init(void)
                {
                        sDrvUartInfo.pu8TxAdd = &Uart_0_TxBuf;
                        sDrvUartInfo.pu8TxValid = &Uart_0_TxBuf;
                        sDrvUartInfo.pu8TxMinAddr = &Uart_0_TxBuf;
                        sDrvUartInfo.pu8TxMaxAddr = &Uart_0_TxBuf;
                        sDrvUartInfo.u8TxBufDataSize = 0;
                        sDrvUartInfo.bTxIsStop = TRUE;
                        sDrvUartInfo.pu8RxAdd = &Uart_0_RxBuf;
                        sDrvUartInfo.pu8RxValid = &Uart_0_RxBuf;
                        sDrvUartInfo.pu8RxMinAddr = &Uart_0_RxBuf;
                        sDrvUartInfo.pu8RxMaxAddr = &Uart_0_RxBuf;
                        sDrvUartInfo.u8RxBufDataSize = 0;
                }


gwsan 发表于 2021-6-5 21:19

//将需要发送的数据添加到待发送的数据缓冲区,所有数据实际上是再终端里面发送
                void MW_Uart_Send_Data_Add(UART_PORT_TYPE ePort,u8int * buf,u16int Size)
                {
                        u8int Len = 0;
                        //if((UART_0_TX_SIZE - sDrvUartInfo.u8TxBufDataSize) >= Size)
                        {剩余空间比要发送的数据大才会发送,否则丢弃要发送的数据
                                sDrvUartInfo.u8TxBufDataSize = sDrvUartInfo.u8TxBufDataSize + Size;更新剩余空间大小
                                while(Len < Size)
                                {
                                        *sDrvUartInfo.pu8TxAdd = buf;
                                        if(sDrvUartInfo.pu8TxAdd < sDrvUartInfo.pu8TxMaxAddr)
                                        {
                                                sDrvUartInfo.pu8TxAdd ++;
                                        }
                                        else
                                        {
                                                sDrvUartInfo.pu8TxAdd = sDrvUartInfo.pu8TxMinAddr;
                                        }
                                        Len ++;
                                }
                                if(sDrvUartInfo.bTxIsStop)
                                {
                                        sDrvUartInfo.bTxIsStop = FALSE;
                                        Drv_Hardware_uart_SendByte(ePort,*sDrvUartInfo.pu8TxValid);
                                }
                        }
                }


gwsan 发表于 2021-6-5 21:20

//这个是中断发送函数
                void MW_Uart_Tx_It_Handle(UART_PORT_TYPE ePort)
                {       
                        对上次中断进行指针移动同时更新剩余空间大小
                        sDrvUartInfo.u8TxBufDataSize --;
                        if(sDrvUartInfo.pu8TxValid < sDrvUartInfo.pu8TxMaxAddr)
                        {
                                sDrvUartInfo.pu8TxValid ++;
                        }
                        else
                        {
                                sDrvUartInfo.pu8TxValid = sDrvUartInfo.pu8TxMinAddr;
                        }
                       
                        如果发送剩余空间小于缓冲区大小说明还有数据等待发送
                        if(sDrvUartInfo.u8TxBufDataSize > 0)
                        {
                                Drv_Hardware_uart_SendByte(ePort,*sDrvUartInfo.pu8TxValid);
                        }
                        else
                        {
                                sDrvUartInfo.bTxIsStop = TRUE;
                        }
                }


gwsan 发表于 2021-6-5 21:21

//这个是中断接收函数
                void MW_Uart_Rx_It_Handle(UART_PORT_TYPE ePort,u8int Data)
                {
                        //if(sDrvUartInfo.u8RxBufDataSize < UART_0_RX_SIZE)缓冲区空间没满,填数据,否则丢弃数据
                        {
                                直接往缓冲里填接收到的数据
                                *sDrvUartInfo.pu8RxAdd = Data;
                                sDrvUartInfo.u8RxBufDataSize ++;
                                if(sDrvUartInfo.pu8RxAdd == sDrvUartInfo.pu8RxMaxAddr)
                                {
                                        sDrvUartInfo.pu8RxAdd = sDrvUartInfo.pu8RxMinAddr;
                                }
                                else
                                {
                                        sDrvUartInfo.pu8RxAdd ++;
                                }
                        }
                }


gwsan 发表于 2021-6-5 21:21

//用户获取从串口接收到的数据
                void MW_Uart_Get_Rx_Data(UART_PORT_TYPE ePort,UART_UserDataType *psData)
                {
                        u16int u16Count = 0;
                        u8int* pu8UserBuf;
                        u8int *pu8GetData;
                        pu8UserBuf = &psData->u8UserData;
                        pu8GetData = sDrvUartInfo.pu8RxValid;
                        while(u16Count < sDrvUartInfo.u8RxBufDataSize)复制所有数据
                        {
                                *pu8UserBuf = *pu8GetData;
                                if(pu8GetData == sDrvUartInfo.pu8RxMaxAddr)
                                {
                                        pu8GetData = sDrvUartInfo.pu8RxMinAddr;
                                }
                                else
                                {
                                        pu8GetData++;
                                }
                                pu8UserBuf++;
                                u16Count ++;
                        }
                        psData->u16Size = sDrvUartInfo.u8RxBufDataSize;
                }


gwsan 发表于 2021-6-5 21:22

//用户获取从串口接收到的数据后应当释放相应大小的缓冲区数据
                void MW_Uart_Free_Rx_Buffer(UART_PORT_TYPE ePort, u8int u8Len)
                {
                        while (u8Len --)
                        {
                                if (sDrvUartInfo.pu8RxValid == sDrvUartInfo.pu8RxMaxAddr)
                                {
                                        sDrvUartInfo.pu8RxValid = sDrvUartInfo.pu8RxMinAddr;
                                }
                                else
                                {
                                        sDrvUartInfo.pu8RxValid ++;
                                }
                                sDrvUartInfo.u8RxBufDataSize --;
                        }
                }


两只袜子 发表于 2021-6-9 16:37

很不错的帖子,支持下

xxx715 发表于 2021-8-30 12:05

谢谢分享,支持共享!

七毛钱 发表于 2021-9-1 16:33

很不错的,支持一下

armcortex 发表于 2023-1-8 20:33

感谢楼主的讲解

vivilyly 发表于 2023-2-2 09:57

单片机如何实现多任务               

sdCAD 发表于 2023-2-2 11:40

单片机 怎么替换pc指针值            

cashrwood 发表于 2023-2-2 13:56

单片机能同时执行多少个任务?               

wujiawen8000 发表于 2023-2-2 14:15

大神

bestwell 发表于 2023-2-2 15:42

通过实现中断来完成任务之间的切换么?

elsaflower 发表于 2023-2-4 14:44

那个如何实现单片机多个函数同时运行?

10299823 发表于 2023-2-4 15:23

单片机中如何实现多线程,多任务?
页: [1] 2
查看完整版本: 单片机软件系统框架和多任务调度