单片机软件系统框架和多任务调度
这里我用的单片机算是中颖的sh79f9401芯片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;载入要发送的数据
}
}
中间层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;
//初始化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;
}
//将需要发送的数据添加到待发送的数据缓冲区,所有数据实际上是再终端里面发送
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);
}
}
}
//这个是中断发送函数
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;
}
}
//这个是中断接收函数
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 ++;
}
}
}
//用户获取从串口接收到的数据
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;
}
//用户获取从串口接收到的数据后应当释放相应大小的缓冲区数据
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 --;
}
}
很不错的帖子,支持下 谢谢分享,支持共享! 很不错的,支持一下 感谢楼主的讲解 单片机如何实现多任务 单片机 怎么替换pc指针值 单片机能同时执行多少个任务? 大神 通过实现中断来完成任务之间的切换么? 那个如何实现单片机多个函数同时运行? 单片机中如何实现多线程,多任务?
页:
[1]
2