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

📄 main.c

📁 单片机与计算机的通讯应用程序,运行KEIL C51软件,可以直接使用!
💻 C
字号:
/*
   //*************************************************************************
   //
   //                  串口输入输出控制器
   //
   //           COPYRIGHT (c)   2005 BY 11 
   //                     --  ALL RIGHTS RESERVED  --
   //
   // File Name:	main.c
   // Created:		2005.7.4
   // Modified:		2005.7.5
   // Revision:		1.0
   //
   //*************************************************************************
   // 芯片类型 AT89S51
   //*************************************************************************
*/

#include <at89x52.h>
#include <INTRINS.H>

void InitCom(void);
void ComOutChar(unsigned char OutData);
void PackCheck(void);
void SendErrMsg(void);
void SendCRCMsg(void);
void SendTeMsg(void);
void SendNSMsg(void);
void RunPack(void);
void CheckID(void);
void SendPack(void);
void Write(void);
void Read(void);

static unsigned char Pack[9]; //数据包数组
static unsigned char PN = 0; //接收指针
static unsigned char TN = 0; //超时标识
static unsigned char SN = 0;	
unsigned char code SNID[] = {"SN0001"}; //固件的序列号

void main(void)
{
	unsigned int a;

	InitCom();
	do
		{	
			for (a=0; a<30000; a++)
				P3_6 = 1;
			for (a=0; a<30000; a++) //指示灯闪动
				P3_6 = 0;
		}
	while(1);
}

//串口初始化 晶振为11.0592M 方式1 波特率57600
void InitCom(void)
{
	SCON = 0x50; //串口方式1,允许接收
	TMOD = 0x21; //定时器1定时方式2,定时0为模式1,16位模式
	TCON = 0x40; //设定时器1开始计数
	TH1 = 255;	//设波特率为57600
	TL1 = 255;
	PCON = 0x80; //波特率加倍控制,SMOD位
	RI = 0;	//清收发标志
	TI = 0;
	TR1 = 1; //启动定时器
	EA = 1; //开总中断
	ES = 1; //开串口中断
}


//向串口输出一个字符(非中断方式)
void ComOutChar(unsigned char OutData)
{
	SBUF = OutData; //输出字符
	while(!TI); //空语句判断字符是否发完
	TI = 0; //清TI
}

//串口接收中断
void ComInINT(void) interrupt 4
{
	if (RI) //判断是不是收完字符
		{
			ET0 = 0; //开定时中断
			TR0 = 0;
			TN = 0; //接收超时变量清零
			RI = 0; //RI清零
			Pack[PN] = SBUF; //存数据
			PN++;  //指针加1
			if (PN == 9)
				{
					PN = 0; //指针清零 一帧数据收完后
					PackCheck(); //调用数据包检查
				}
			else
				{
					TH0 = 0x70; //设定时值,收到数据时设定时值
					TL0 = 0x43;
					ET0 = 1; //定时器中断0开
					TR0 = 1; //启动定时器 定时器用于在一帧数据接收时如有丢包则返回错误信息12个0xEE
				}
		}
}

//定时器中断用于处理丢包
void Timer0(void) interrupt 1
{
	if (TN>2) // 帧中的两字符间隔tn*40ms则为出错
		{
			ET0 = 0;
			TR0 = 0; //关定时中断

			SendTeMsg(); //发送超时错误信息
			PN = 0; //pack指针清零
			TN = 0;
		}
	else
		TN++;		
}

//信息包校验
void PackCheck(void)
{
	unsigned char CRCL = 0, CRCH = 0; //CRC高低字节暂存
	unsigned char TempCyc;
	
	for (TempCyc=0; TempCyc<7; TempCyc++)
		{
			CRCL = CRCL + Pack[TempCyc]; //把信息包中的前十个相加
			if (CY) //当CRCL大于0xFF时,CY为1
				CRCH++; //CY为1时CRCH加1
		}
	if ((CRCL == Pack[8]) && (CRCH == Pack[7]))
		RunPack(); //校验正确时执行包
	else
		SendCRCMsg(); //CRC校验不对时,这个包将不执行,并向PC发送CRC错误信息		
}

//发送SN错误信息
void SendErrMsg(void)
{
	ComOutChar(0x0A);
}

//发送命令完成
void SendOKMsg(void)
{
	ComOutChar(0x0B);
}

//发送CRC错误
void SendCRCMsg(void)
{
	ComOutChar(0x0C);
}

//发送超时错误
void SendTeMsg(void)
{
	ComOutChar(0x0D);
}


//发送命令不支持错误
void SendNSMsg(void)
{
	ComOutChar(0x0E);
}

//运行信息包
void RunPack(void)
{
	switch(Pack[0])
		{
			case 1: CheckID(); 	break;
			case 2: Write();   	break;
			case 3: Read();	break;
			default: SendNSMsg(); //命令不支持
		}
}

//校验序列号
void CheckID(void)
{
	unsigned char TempCyc;
	for (TempCyc=1; TempCyc<7; TempCyc++)
		{
			if (SNID[TempCyc-1]!=Pack[TempCyc])
				{
					TempCyc=7; //如有一个不对时跳出循环
					SN = 0;
				}
			else
				{
					SN = 1;
				}
		}
	if (SN)
		SendOKMsg(); //返回OK
	else
		SendErrMsg(); //发送SN错误信息
}

//发送信息包
void SendPack(void)
{
	unsigned char CRCL = 0, CRCH = 0; //CRC高低字节暂存
	unsigned char TempCyc;
	
	for (TempCyc=0; TempCyc<7; TempCyc++)
		{
			CRCL = CRCL + Pack[TempCyc]; //把信息包中的前十个相加
			if (CY) //当CRCL大于0xFF时,CY为1
				CRCH++; //CY为1时CRCH加1
		}
	Pack[7] = CRCH;
	Pack[8] = CRCL; //计算要发送的信息包CRC
	for (TempCyc=0; TempCyc<9; TempCyc++)
		ComOutChar(Pack[TempCyc]); //发送错误信息包
}

//写命令的信息包处理
void Write(void)
{
if (SN)
{
	switch(Pack[1])  //0为P0,1为P1,2为P2,3为关闭所有
		{
			case 0:
				P0 = Pack[2];
				SendOKMsg();
			break;
			case 1:
				P1 = Pack[2];
				SendOKMsg();
			break;
			case 2:
				P2 = Pack[2];
				SendOKMsg();	
			break;
			case 3:
				P0 = 0xFF;
				P1 = 0xFF;
				P2 = 0xFF;
				SendOKMsg();
			break;
			case 4:
				P0 = 0x00;
				P1 = 0x00;
				P2 = 0x00;
				SendOKMsg();
			break;
			default: SendNSMsg();
		}
}
else
{
	SendErrMsg();
}
}


//跟据相应的芯片类型去读芯片
void Read(void)
{
if (SN)
{
	switch(Pack[1])  //0为P0,1为P1,2为P2,3为返回全部
		{
			case 0:
				Pack[1] = P0;
				Pack[2] = 0;
				Pack[3]	= 0;
				SendPack();
			break;
			case 1:
				Pack[1] = 0;
				Pack[2] = P1;
				Pack[3]	= 0;
				SendPack();
			break;
			case 2:
				Pack[1] = 0;
				Pack[2] = 0;
				Pack[3]	= P2;
				SendPack();
			break;
			case 3:
				Pack[1] = P0;
				Pack[2] = P1;
				Pack[3]	= P2;
				SendPack();
			break;
			default: SendNSMsg();
		}
}
else
{
	SendErrMsg();
}
}


⌨️ 快捷键说明

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