📄 main.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 + -