⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.c

📁 ZLG500的应用软件
💻 C
字号:
#define UART_GLOBALS
#include "main.h"
#include "UART.h"
//#include "string.h"
#include "delay.h"

void UART_Init()
{
	PCON = 0x80;              	// SMOD = 1;
	SCON = 0x50;              	// Mode 1, 8-bit UART, enable receiption
	TMOD = 0x21;	      		// Timer 1, mode 2, 8-bit auto reload,
	
	MyAddr = 0;
	BaudNum = 7;
		
	TH1=BaudRateTable[BaudNum];
	TL1=BaudRateTable[BaudNum];
	TR1 = 1;	
	
    RcvStatus = RCVSTX;
    SerDTValid = FALSE;
    SerTmOut = 0;
    
    SendFlag = FALSE;
    SendStatus = SENDIDLE;
    RS485_TXen = 0;
    REN = 1;
    ES = 1;
}

void UART_Isr() interrupt 4 using 1
{
	INT8U temp;
	static INT8U SerLen,ExtData;
	static INT8U LenSend;	//已发送的有效数据长度
	
    if(RI)
    {
		temp = SBUF;
		
    	if(temp == STX)
		{			//在任何时候收到STX,即可视为一帧的开始
			RcvStatus = RCVDATA;
			SerLen = 0;
			RcvDTLen = 0;
			SerTmOut = 2;	//启动超时定时器
		}
		else if(temp == ETX)
		{
			if(RcvStatus == RCVDATA)
			{	
				if(SerTmOut)		
				{				//在未超时的情况下,接收数据后又收到一个ETX,则本帧数据有效
					SerDTValid = TRUE;
				}
				RcvStatus = RCVSTX;
			}
		}
		else if(RcvStatus == RCVDATA)
		{					
			if((SerTmOut==0) || (temp&0x80))
				RcvStatus = RCVSTX;		//超时或数据中的bit7为1,则本帧数据作废
			else
			{
				SerTmOut = 2;		
        		if((SerLen&0x07) == 0)
				{				//扩展字节
					ExtData = temp;
				}
				else
				{
					if(ExtData & 0x01)
					{
						temp |= 0x80;
					}
					SerBfr[RcvDTLen++] = temp;
					ExtData >>= 1;
				}
				SerLen++;
			}
		}
		
		if(SerDTValid)
		{
			SerDTValid = FALSE;
			if(RcvDTLen == (SerBfr[LENGTH]+6))
			{
				temp = 0;
				for(SerLen=0;SerLen<RcvDTLen;SerLen++)
					temp ^= SerBfr[SerLen];
				if(temp == 0xff)
				{
					if(SerBfr[RADDR] == MyAddr)
					{
						SerDTValid = TRUE;
					}
				}
			}
		}	
        RI = 0;
    }
    else
    {
        if(SendStatus == SENDSTX)
		{
			SBUF = STX;
			SendStatus = SENDDATA;	//下次中断发送数据
			SerLen = 0;
			LenSend = 0;
		}
		else if(SendStatus == SENDDATA)
		{
			if((SerLen&0x07) == 0)
			{
				ExtData = 0;
				temp = LentoSend>=7?7:LentoSend;	//计算扩展数据位长度
				do
				{
					ExtData <<= 1;
					if(SerBfr[LenSend+(temp-1)]&0x80)
						ExtData |=0x01;
					temp--; 
				}while(temp);
				SBUF = ExtData;		//发送扩展数据
			}
			else
			{
				SBUF = SerBfr[LenSend]&0x7f;
				LenSend++;
				LentoSend--;
				if(LentoSend == 0)
				{					//有效数据已发送完毕
					SendStatus = SENDETX;	//下次中断发送ETX
				}
			}
			SerLen++;
		}
		else if(SendStatus == SENDETX)
		{
			SBUF = ETX;		//发送ETX
			SendStatus = SENDSTOP;	//下次中断结束本次发送
		}
		else if(SendStatus == SENDSTOP)
		{
			RS485_TXen = FALSE;
			SendFlag = FALSE;
			SendStatus = SENDIDLE;	//发送器空闲
		}
        TI = 0;
    }
}

INT8U Ser_Send(INT8U SlvAddr)
{
    INT8U i;
    
    if(SendStatus == SENDIDLE)
	{
		SerBfr[RADDR] = SlvAddr;  //从机地址
     	SerBfr[SADDR] = MyAddr;
     	
	    LentoSend = SerBfr[LENGTH]+5;
	    SerBfr[LentoSend] = 0;
	    for(i=0;i<LentoSend;i++)
	    {
	        SerBfr[LentoSend] ^= SerBfr[i];
	    }
	    SerBfr[LentoSend] = ~SerBfr[LentoSend];
	    LentoSend++;
	    
	    RS485_TXen = 1;
	    SendStatus = SENDSTX;
	    TI = 1;
	    return TRUE;
	}
	else
		return FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -