[其它应用] 单片机软件系统框架和多任务调度

[复制链接]
8720|24
 楼主| 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[UART_0_TX_SIZE] = {0};//UART_0_TX_SIZE在uart.h头文件里根据需求和硬件资源自定义大小
                u8int Uart_0_RxBuf[UART_0_RX_SIZE] = {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[1];
               


 楼主| gwsan 发表于 2021-6-5 21:17 | 显示全部楼层
//初始化UART数据缓冲区
                void MW_Uart_Data_Init(void)
                {
                        sDrvUartInfo[UART_PORT_0].pu8TxAdd = &Uart_0_TxBuf[0];
                        sDrvUartInfo[UART_PORT_0].pu8TxValid = &Uart_0_TxBuf[0];
                        sDrvUartInfo[UART_PORT_0].pu8TxMinAddr = &Uart_0_TxBuf[0];
                        sDrvUartInfo[UART_PORT_0].pu8TxMaxAddr = &Uart_0_TxBuf[UART_0_TX_SIZE - 1];
                        sDrvUartInfo[UART_PORT_0].u8TxBufDataSize = 0;
                        sDrvUartInfo[UART_PORT_0].bTxIsStop = TRUE;
                        sDrvUartInfo[UART_PORT_0].pu8RxAdd = &Uart_0_RxBuf[0];
                        sDrvUartInfo[UART_PORT_0].pu8RxValid = &Uart_0_RxBuf[0];
                        sDrvUartInfo[UART_PORT_0].pu8RxMinAddr = &Uart_0_RxBuf[0];
                        sDrvUartInfo[UART_PORT_0].pu8RxMaxAddr = &Uart_0_RxBuf[UART_0_RX_SIZE - 1];
                        sDrvUartInfo[UART_PORT_0].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[ePort].u8TxBufDataSize) >= Size)
                        {剩余空间比要发送的数据大才会发送,否则丢弃要发送的数据
                                sDrvUartInfo[ePort].u8TxBufDataSize = sDrvUartInfo[ePort].u8TxBufDataSize + Size;更新剩余空间大小
                                while(Len < Size)
                                {
                                        *sDrvUartInfo[ePort].pu8TxAdd = buf[Len];
                                        if(sDrvUartInfo[ePort].pu8TxAdd < sDrvUartInfo[ePort].pu8TxMaxAddr)
                                        {
                                                sDrvUartInfo[ePort].pu8TxAdd ++;
                                        }
                                        else
                                        {
                                                sDrvUartInfo[ePort].pu8TxAdd = sDrvUartInfo[ePort].pu8TxMinAddr;
                                        }
                                        Len ++;
                                }
                                if(sDrvUartInfo[ePort].bTxIsStop)
                                {
                                        sDrvUartInfo[ePort].bTxIsStop = FALSE;
                                        Drv_Hardware_uart_SendByte(ePort,*sDrvUartInfo[ePort].pu8TxValid);
                                }
                        }
                }


 楼主| gwsan 发表于 2021-6-5 21:20 | 显示全部楼层
//这个是中断发送函数
                void MW_Uart_Tx_It_Handle(UART_PORT_TYPE ePort)
                {       
                        对上次中断进行指针移动同时更新剩余空间大小
                        sDrvUartInfo[ePort].u8TxBufDataSize --;
                        if(sDrvUartInfo[ePort].pu8TxValid < sDrvUartInfo[ePort].pu8TxMaxAddr)
                        {
                                sDrvUartInfo[ePort].pu8TxValid ++;
                        }
                        else
                        {
                                sDrvUartInfo[ePort].pu8TxValid = sDrvUartInfo[ePort].pu8TxMinAddr;
                        }
                       
                        如果发送剩余空间小于缓冲区大小说明还有数据等待发送
                        if(sDrvUartInfo[ePort].u8TxBufDataSize > 0)
                        {
                                Drv_Hardware_uart_SendByte(ePort,*sDrvUartInfo[ePort].pu8TxValid);
                        }
                        else
                        {
                                sDrvUartInfo[ePort].bTxIsStop = TRUE;
                        }
                }


 楼主| gwsan 发表于 2021-6-5 21:21 | 显示全部楼层
//这个是中断接收函数
                void MW_Uart_Rx_It_Handle(UART_PORT_TYPE ePort,u8int Data)
                {
                        //if(sDrvUartInfo[ePort].u8RxBufDataSize < UART_0_RX_SIZE)缓冲区空间没满,填数据,否则丢弃数据
                        {
                                直接往缓冲里填接收到的数据
                                *sDrvUartInfo[ePort].pu8RxAdd = Data;
                                sDrvUartInfo[ePort].u8RxBufDataSize ++;
                                if(sDrvUartInfo[ePort].pu8RxAdd == sDrvUartInfo[ePort].pu8RxMaxAddr)
                                {
                                        sDrvUartInfo[ePort].pu8RxAdd = sDrvUartInfo[ePort].pu8RxMinAddr;
                                }
                                else
                                {
                                        sDrvUartInfo[ePort].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[0];
                        pu8GetData = sDrvUartInfo[ePort].pu8RxValid;
                        while(u16Count < sDrvUartInfo[ePort].u8RxBufDataSize)复制所有数据
                        {
                                *pu8UserBuf = *pu8GetData;
                                if(pu8GetData == sDrvUartInfo[ePort].pu8RxMaxAddr)
                                {
                                        pu8GetData = sDrvUartInfo[ePort].pu8RxMinAddr;
                                }
                                else
                                {
                                        pu8GetData++;
                                }
                                pu8UserBuf++;
                                u16Count ++;
                        }
                        psData->u16Size = sDrvUartInfo[ePort].u8RxBufDataSize;
                }


 楼主| gwsan 发表于 2021-6-5 21:22 | 显示全部楼层
//用户获取从串口接收到的数据后应当释放相应大小的缓冲区数据
                void MW_Uart_Free_Rx_Buffer(UART_PORT_TYPE ePort, u8int u8Len)
                {
                        while (u8Len --)
                        {
                                if (sDrvUartInfo[ePort].pu8RxValid == sDrvUartInfo[ePort].pu8RxMaxAddr)
                                {
                                        sDrvUartInfo[ePort].pu8RxValid = sDrvUartInfo[ePort].pu8RxMinAddr;
                                }
                                else
                                {
                                        sDrvUartInfo[ePort].pu8RxValid ++;
                                }
                                sDrvUartInfo[ePort].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 | 显示全部楼层
单片机中如何实现多线程,多任务?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

69

主题

3439

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部