发表于:2008-03-18 18:49:00
11楼
/*
*
* 文件名称:组态王与单片机通迅
* 文件标识:07.11.21.c
* 摘 要:组态王与单片机通迅,包括显示,收和发.与18b20温度传感器接合使用.
* 组态王串口通迅口为com1,设备地址为15.0(15表示地址,0表示不打包
* 也可不限地址,但不打包).
* 当前版本:1.0
* 作 者:黄双明
* 完成日期:2007年11月28日
*/
/*
* 组态协议: 字头 设备地址 标志 数据地址 数据字节数 数据… 异或 CR
* 字头:1字节1个ASCII码,40H
* 设备地址: 1字节2个ASCII码,0—255(即0---0x0ffH)
* 标志:1字节2个ASCII码,bit0~bit7, //把接收值将它发出即可
* bit0= 0:读,bit0= 1:写。
* bit1= 0:不打包。
* bit3bit2 = 00,数据类型为字节。
* bit3bit2 = 01,数据类型为字。
* bit3bit2 = 1x,数据类型为浮点数。
* 数据地址: 2字节4个ASCII码,0x0000~0xffff //把接收值将它发出即可
* 数据字节数:1字节2个ASCII码,1—100,实际读写的数据的字节数。 //把接收值将它发出即可
* 数据…:为实际的数据转换为ASCII码,个数为字节数乘2。
* 异或:异或从设备地址开始异或,到异或字节前结束得异或值,异或值转换成2个ASCII码
* //如得0x4b,对应Ascll为0x34和0x42.
* CR:0x0d。
*/////////
// 读格式为:字头 设备地址 标志 数据地址 数据字节数 异或 CR
// 写格式: 字头 设备地址 标志 数据地址 数据字节数 数据… 异或 CR
#include "reg52.h"
#define uchar unsigned char
#define CTH0 0xfe
#define CTL0 0x0c
sbit led1=P2^7;//定义LED.
sbit led2=P2^6;
sbit led3=P2^5;
sbit led4=P2^4;
//unsigned char i10=0; //收数据标
//unsigned int j=0; //动态显示数据用
unsigned char i=0; //动态显示用
int j=0; ////调试用
unsigned char k=0; ////调试用1~100.
//unsigned char k4=0; //K4为发送的数据 ;K6为组态下传数据标志。k6=0;
int k2=0; //接收死机保护。
uchar duan_tabled[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//需要显示的段选码
char pp1[22]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,
0x0a,0x0a,0x0a,0x0a,0x0a,0x0a}; //接收上位机读写暂存
char pp2[10]={0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d}; //数据发送暂存
uchar pp3[8]={0x40,0x00,0x00,0x2a,0x2a,0x00,0x00,0x0d} ; //uchar pp4[8]={0x40,0x00,0x00,0x23,0x23,0x37,0x36,0x0d} ; //
delay(unsigned int i) //延时子程序。
{
unsigned int j=0;
for(;j<=i;j++);;;
}
void Init() //初始化
{
// TMOD=0x01;
TMOD=0X21; //设置T1为方式2
TH0=CTH0; //1MS
TL0=CTL0;
ET0=1;
TR0=1;
EX0=1;
IT0=1;
TH1=0Xfd; //设置波特率为9600
TL1=0Xdf;
SCON=0X50; //设置串口位方式1
PCON=0X00;
// SPCTL=0x4d;
TR1=1; //定时器1开始计数
ES=1;
EA=1;
}
void timer0() interrupt 1 //显示中断;前两位调试用,
//第三位显示——接收上位机读写暂存——的第几位.
{ //第四位显示对比。
TH0=CTH0;
TL0=CTL0;
i++;
if(i==5)
{
P0=duan_tabled[pp1[21]%10]; //第二位 显示上面传下来的数据的个位
P1=0xfd;
}
if(i==10)
{
P0=duan_tabled[pp1[21]/10];// 第一位 显示上面传下来的数据的十位
P1=0xfe;
}
if(i==15)
{
P0=duan_tabled[k%10];//第三位 ////K调试用 1~100显示
P1=0xf7;
}
if(i==20)
{
P0=duan_tabled[k/10]; //第四位
P1=0xfb;
i=0;
if(j++>=100){j=0; k++;} ////j调试用
}
if(k>=100) k=0;////K调试用,1~100显示
}
void UART() interrupt 4 //接收中断,只接收
{
uchar ii ;
unsigned int temp;
if(RI)
{
if(SBUF==0x40) //简单判断是否为组态发送数据,否则RI=0。
{
for(ii=0;ii<18;ii++) //不管发多少Bit,按最多收18个Bit。
{
pp1[ii]=SBUF;
RI=0;
if(pp1[ii]==0x0d) {k2=1;return;} //也可用break; 跳出for语句
temp=0;
while(RI==0&&temp<1000)temp++; //while(!RI&&temp)temp--;也可退出
if(temp>=1000)return;
}
}
}
RI=0; //
}
void write(uchar k5) //写子程序,写的格式为:字头 设备地址 标志 数据地址 数据字节数 异或 CR
{
uchar ii; //变量
uchar yihou1,yihou2,yihou3; //计算暂存变量
yihou1 = pp1[1]^pp1[2]^pp1[3]^pp1[4]^pp1[5]^pp1[6]^pp1[7]^pp1[8]^pp1[9]^pp1[10];
//异或较验;组态协议。
yihou2 = yihou1; //转换成ACall码。如73的AsAALL为0x37和0x33
yihou1 = yihou1>>4 ;
yihou2 = yihou2&0x0f ;
if(yihou2>0x09) yihou2=yihou2-9+0x40;
else yihou2=yihou2 +0x30;
if(yihou1>0x09) yihou1=yihou1-9+0x40;
else yihou1=yihou1 + 0x30; ///转换
if( yihou1==pp1[11]&&yihou2==pp1[12] ) //较验
{
pp2[1] = pp1[1]; pp2[2] = pp1[2]; // 放入需发送的内容。
pp2[3] = pp1[9]; pp2[4] = pp1[10]; // 组态协议。
pp2[5]=pp2[6]=k5; // 把数据转换成Asall码
pp2[5] = (pp2[5]>>4)&0x0f;
pp2[6] = pp2[6]&0x0f;
if(pp2[5]>=0x0a)
pp2[5] = pp2[5]-9+0x40; //0x0a~0x0f的转换,a对应Ascll值为0x40。
else
pp2[5] = pp2[5]+0x30; //0~9的转换。
if(pp2[6]>=0x0a)
pp2[6] = pp2[6]-9+0x40;
else
pp2[6] = pp2[6]+0x30 ;
yihou3 = pp2[1]^pp2[2]^pp2[3]^pp2[4]^pp2[5]^pp2[6]; //取得异域较验值。
pp2[7] = yihou3>>4;
pp2[8] = yihou3&0x0f;
if(pp2[7]>=0x0a)
pp2[7] = (pp2[7]-9)+0x40;
else
pp2[7] = pp2[7]+0x30;
if(pp2[8]>=0x0a)
pp2[8] = (pp2[8]-9)+0x40;
else
pp2[8] = pp2[8]+0x30;
for(ii=0;ii<10;ii++) //发送。
{
SBUF = pp2[ii] ;
while(!TI);
TI=0;
}
}
else //错误发送见组态协议。
{
pp3[1] = pp1[1]; pp3[2] = pp1[2];
yihou3 = pp3[1]^pp3[2]; //错误代码的较验
pp3[5] = yihou3>>4; //Aacll转换。
pp3[6] = yihou3&0x0f;
if(pp3[5]>=0x0a)
pp3[5] = pp3[5]-9+0x40;
else
pp3[5] = pp3[5] +0x30;
if(pp3[6]>=0x0a)
pp3[6] = pp3[6]-9+0x40;
else
pp3[6] = pp3[6] + 0x30 ;
for(ii=0;ii<8;ii++)
{
SBUF = pp3[ii] ;
while(!TI);
TI=0;
}
}
}
read() // 读程序。读格式: 字头 设备地址 标志 数据地址 数据字节数 数据… 异或 CR
{
uchar ii;
uchar yihou1,yihou2,yihou3;
yihou1 = pp1[1]^pp1[2]^pp1[3]^pp1[4]^pp1[5]^pp1[6]^pp1[7]^pp1[8]^pp1[9]^pp1[10]^pp1[11]^pp1[12];
yihou2 = yihou1;
yihou1 = yihou1>>4 ;
yihou2 = yihou2&0x0f ;
if(yihou2>0x09) yihou2=yihou2-9+0x40;
else yihou2=yihou2 +0x30;
if(yihou1>0x09) yihou1=yihou1-9+0x40;
else yihou1=yihou1 + 0x30;
if(yihou1==pp1[13]&&yihou2==pp1[14])
{
/* if(k6==2)
{
pp1[19]=pp1[11]; //取数据
pp1[20]=pp1[12];
} */
pp4[1] = pp1[1]; // 取设备地址
pp4[2] = pp1[2]; // 取设备地址
yihou3 = pp1[1]^pp1[2]; //异或效验
pp4[5] = yihou3>>4; //异或效验结果转换成ASCII码。
pp4[6] = yihou3&0x0f;
if(pp4[5]>=0x0a)
pp4[5] = pp4[5]-9+0x40;
else
pp4[5] = pp4[5]+0x30;
if(pp3[6]>=0x0a)
pp4[6] = pp4[6]-9+0x40;
else
pp4[6] = pp4[6]+0x30;
for(ii=0;ii<8;ii++)
{
delay(100);
SBUF = pp4[ii] ;
while(!TI);
TI=0;
}
}
else
{
pp3[1] = pp1[1];
pp3[2] = pp1[2];
yihou3 = pp3[1]^pp3[2];
pp3[5] = yihou3>>4;
pp3[6] = yihou3&0x0f;
if(pp3[5]>=0x0a)
pp3[5] = pp3[5]-9+0x40;
else
pp3[5] = pp3[5] +0x30;
if(pp3[6]>=0x0a)
pp3[6] = pp3[6]-9+0x40;
else
pp3[6] = pp3[6] + 0x30 ;
for(ii=0;ii<8;ii++)
{
SBUF = pp3[ii] ;
while(!TI);
TI=0;
}
}
}
main ()
{
unsigned char k4=0;
//delay(1000);
//uchar ii ;
Init(); //初始化
while (1)
{
if(k2==1) //
{
k2=0;
if(pp1[4]==0x30) //pp1[4]判断组态是要读还是写数据
{
k4=k;
if(pp1[8]==0x31) //
write(k4);
if(pp1[8]==0x32)
write(pp1[21]);
}
if(pp1[4]==0x31) /
{
read(); //
pp1[19]=pp1[11]; //
pp1[20]=pp1[12];
if(pp1[19]>=0x41)
pp1[19] = pp1[19]-0x37;
else
pp1[19] = pp1[19]-0x30;
if(pp1[20]>=0x41)
pp1[20] = pp1[20]-0x37;
else
pp1[20] = pp1[20]-0x30;
pp1[19]=pp1[19]<<4 ;
pp1[21]=(pp1[19]&0xf0)|(0x0f&pp1[20]);
}
}
}
}