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

📄 main.c

📁 此程序是RS485从机通讯
💻 C
字号:
/****************************************************************************
* File :  main.c                                                            *
* COPYRIGHT BY HUOYAN LTD.COMPANY                                           *
* Version:      V1.0                                       			        *
*                                                                           *
* Created:      15.Aug.2006                                                 *
* Last Change:  17.Aug.2006                                                 *
*                                                                           *
* Author:       huzi                                                        *
*                                                                           *
* Compiler:     KEIL C51 V7.10                                              *
*                                                                           *
* Description:  STC89C52RD+ Firmware for HY502  Serial Reader               *	 
* OSC use 11.0592MHz crystal.  										        *
*****************************************************************************/

/********************************************************************************	
此程序是RS485从机通讯,包含3部分:接收帧程序、发送帧程序及执行命令程序。  
从机通讯地址从地址开关读取4位
由于485的通信规约差别很大,这里只是提供参考,具体请参照自己的项目特点做修改。
********************************************************************************/
//#include<reg52.h>
#include<main.h>
#include<hy502.h> 

/*宏定义*/
#define uchar unsigned char
#define uint unsigned int

// 按键端口定义
sbit P20=P2^0;
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;

bit ack;	//应答标志
uchar code cStatus1[]="Ok!";

/*通讯变量定义*/
sbit CTRL485=P3^7;         /*RS485切换控制信号*/	  

#define N 32                  /*通讯缓存区长度*/
uchar idata Serial_buf[N];    /*定义通讯缓存区*/

/*数据结构:地址域A0A1A2A3 4个,命令字节1个,长度字节1个,数据区(标识符2个,数据)*/

/*主程序变量定义*/	  
uchar data Command_status1=0x00; /*程序运行状态字节*/

/********************************************************************
延时函数
原型:void Delay(uchar);
功能:延时1ms*i
入口参数: i是设定延时时间
出口参数:无
********************************************************************/
void Delay(uchar i)
{
	uint j;
	for(;i>0;i--)
	for(j=0;j<700;j++);
}


/********************************************************************
蜂鸣器函数
原型:void beep(uchar n);
功能:设定响的次数
入口参数:n
出口参数:无
********************************************************************/
void beep(uchar n)
{
	uchar i;
	for(i=0;i<n;i++)
	{
	    BUZ=0;          //产生周期为1s的方波
	    Delay(500);     //delay 0.5s
		BUZ=1;
		Delay(500);
		BUZ=0;
	}
}
/********************************************************************
LED闪烁函数
原型:void splash(uchar n);
功能:设定LED闪烁的次数
入口参数:n
出口参数:无
********************************************************************/
void splash(uchar n)
{
	uchar i;

	for(i=0;i<n;i++)
	{
		LED_YELLOW=1;
		Delay(500);     //delay 0.5s
		LED_YELLOW=0;
		Delay(500);
		LED_YELLOW=1;
	}
}
/********************************************************************
CPU各个部件的初始化函数
原型:void InitializeSystem();
功能:初始化系统各个部件
入口参数:无
出口参数:无
********************************************************************/
void InitializeSystem()
{
	ET2 = 0;
	T2CON = 0x04;
    PCON&=0x3f; /*UART设置工作方式3,11位数据*/
    SCON=0xd0;
    TMOD = 0x21;        //TMOD = 0x22;

	TH1   = BAUD_19200;  //默认波特率
	TL1   = TH1;
	TR1   = TRUE;             // 波特率发生器

	TH0 = 0xDC;
    TL0 = 0x00;
    TR0 = 1;
    ET0=1;

	ET1=0;
	EA=1;
	EX0=1;
	IT0 = 1;
	TR2=0;
 
	g_bReceCommandOk=0;	   
   	Delay(100); /*延时100ms,以稳定CPU*/
						//喇叭和指示灯测试
	splash(1);
	beep(1);

	CTRL485=1; /*485通讯为接收状态*/	 
	ES = TRUE;
}

/********************************************************************
接收一个字节通讯函数
原型:uchar RecByte();
功能:接收一个字节通讯
入口参数:无
出口参数:返回接收值
********************************************************************/
uchar RecByte()
{
	RI=0;
	while(!RI);
	RI=0;
	ACC=SBUF;
	if(P!=RB8)      /*偶校验正确吗?*/
	{
	SP--;SP--;CY=0;return CY; /*错误返回*/
	}
	return (ACC); /*接收一个字节,并进行偶校验*/
}

/********************************************************************
接收一帧通讯函数
原型:void RecFrame(uchar *s);
功能:接收一帧通讯
入口参数:接收存取地址指针
出口参数:接收正确标志,1为接收正确
********************************************************************/
bit RecFrame(uchar *s)
{
	uchar CS=0x00,Serial_data;
	char i,j;

	RI=0;
	Serial_data=SBUF; /*接收第一字节*/
	while(Serial_data!=0xfe)
	return 0; /*不是前导字节*/
	do
	Serial_data=RecByte(); /*是前导字节,继续查询*/  
	 
	while(Serial_data==0xfe); /*是前导字节吗?*/
	if(Serial_data!=0x68) /*是帧头吗?*/
	return 0;
	CS+=0x68;
	for(i=0;i<=3;i++) /*接收通讯地址*/
	{
	*(s+i)=RecByte();
	CS+=*(s+i);
	}
	if(RecByte()!=0x68) /*是数据帧头吗?*/
	return 0;
	CS+=0x68;
	CS+=(*(s+6)=RecByte()); /*接收通讯命令*/
	j=*(s+7)=RecByte(); /*接收通讯数据长度*/
	CS+=j;
	for(i=0;i<=(j-1);i++) /*接收N个数据*/
	{
	CS+=(*(s+i+8)=RecByte());
	*(s+i+8)-=0x33;
	}
	if(CS!=RecByte()) /*校验正确吗?*/
	return 0;
	if(RecByte()!=0x16) /*是帧尾吗?*/
	return 0;
	ES=0;
	return 1;
}

/********************************************************************
串口接收中断服务程序
功能:接收数据
********************************************************************/
void RXD_Int(void) interrupt 4
{
	CY=RecFrame(Serial_buf);
	if(CY)
	Command_status1|=0x04; /*一帧接收成功,通知主程序进行通讯处理*/
} 

/********************************************************************
串口发送一个字节
功能:发送一个字节数据
入口参数:发送数据
出口参数:无
********************************************************************/	
void SendByte(uchar Serial_data)
{
	ACC=Serial_data;
	TB8=P;TI=0;
	SBUF=Serial_data;
	while(!TI);
	TI=0; /*发送一个字节,并进行偶校验*/
}
 
/********************************************************************
发送一帧数据函数
原型:void TXD_Int(uchar *s);
功能:发送一帧数据
入口参数:发送数据帧地址指针
出口参数:无
********************************************************************/
void TXD_Int(uchar *s)
{
	uchar CS=0x68;
	char i,j;

	CTRL485=0;       /*RS485通讯,切换为发送状态*/
	Delay(1);
	TI=0;
	SendByte(0xfe); /*发送2个前到字节*/
	SendByte(0xfe);
	SendByte(0x68); /*发送帧头*/
	for(i=0;i<=3;i++) /*发送通讯地址*/
	{CS+=*(s+i);SendByte(*(s+i));}
	CS+=0x68;SendByte(0x68); /*发送数据帧头*/
	CS+=*(s+6);SendByte(*(s+6)); /*发送帧命令*/
	CS+=*(s+7);j=*(s+7);SendByte(j); /*发送数据长度*/
	for(i=0;i<=j-1;i++) /*发送数据*/
	{
	(*(s+i+8))+=0x33;
	SendByte(*(s+i+8));CS+=(*(s+i+8));
	}
	SendByte(CS); /*发送校验字节*/
	SendByte(0x16); /*发送帧尾*/
	RI=0;TI=0;
	Delay(1);
	CTRL485=1; /*一帧发送完毕,恢复信道切换功能*/
	
}

/********************************************************************
通讯地址判断函数
原型:uchar Serial_Address(uchar *);
功能:通讯地址判断
全局变量:
入口参数:s1指向从通讯地址
出口参数:0x00错误,0x01正确,0x02广播地址
********************************************************************/
uchar Serial_Address(uchar *s1)
{
	uchar i,a[4];
	a[0]=P20; /*读取通讯地址*/
	a[1]=P21;
	a[2]=P22;
	a[3]=P23;
	for(i=0;i<=3;i++)
	{
	if((*(s1+i))!=0x99)
	break; /*不是广播地址*/
	if(i==5)
	return(0x02); /*是广播地址*/
	}
	for(i=0;i<=3;i++)
	{
	if((*(s1+i))!=a[i])
	return(0x00); /*地址不相同*/
	}
	return(0x01); /*地址相同*/
}

/********************************************************************
通讯执行函数
原型:bit Serial_Command_Run(uchar *);
功能:执行通讯命令
入口参数:帧地址
出口参数:是否正确及是否完毕,0为错误和通讯没有完成,1为正确和通讯完成
********************************************************************/
bit Serial_Command_Run(uchar *s)
{
	switch(Serial_Address(s)) /*判断地址是否正确*/
	{
	case 0x02: /*广播地址99999999H*/
	break;
	case 0x01: /*正常地址*/
	switch(*(s+4))
	{	  	   	
	(*(s+6))|=0x80;(*(s+7))=0x04; /*存入命令码及长度字节*/
	TXD_Int(s); /*发送一帧数据*/
	break;
	case 0x01: /*读数据*/
	break;
	case 0x04: /*写数据*/
	break;
	default: /*其他命令*/
	break;
	}
	break;
	case 0x00: /*地址错误*/
	return 0;
	break;
	}
	return 1; /*帧执行正确,返回*/

}
/********************************************************************
通讯主函数
原型:void Serial_Command();
功能:执行通讯命令
入口参数:无
出口参数:无
********************************************************************/
void Serial_Command()
{
	if(Command_status1&0x04) /*通讯事件发送*/
	{
	if(~Serial_Command_Run(Serial_buf)) /*帧执行*/
	{ES=1;Command_status1&=0xfb;return;} /*帧错误,恢复信道功能*/
	ES=1; /*恢复信道功能*/
	Command_status1&=0xfb; /*j清除通讯处理事件*/
	}
}

/********************************************************************
主函数
原型:void main();
功能:完成通讯主流程
入口参数:无
出口参数:无
********************************************************************/
void main()
{
	InitializeSystem(); /*对CPU各个部件初始化*/	   	
	while(1)
	{
		Serial_Command();
	}
}

⌨️ 快捷键说明

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