切换到宽版
  • 804阅读
  • 3回复

[C51]组态王与单片机通讯 [复制链接]

上一主题 下一主题
离线liwenjiefa
 

发帖
97
M币
507
专家
3
粉丝
75



/***********************************************************************************************************
与组态王通讯时请注意选择的单片机晶震频率和波特率及效验否则无法通讯成功
本次测试组态王只支持19200波特率,再高的波特率没有成功,不知道是何原因难道组态的原因吗?
************************************************************************************************************/
#include "kongview.h"
//#define MODE1T                        //Timer clock mode, comment this line is 12T mode, uncomment is 1T mode
#ifdef  MODE1T
#define T1MS (65536-(MAIN_Fosc/1000))      //1ms timer calculation method in 1T mode
#else
#define T1MS (65536-(MAIN_Fosc/12/1000))      //1ms timer calculation method in 12T mode
#endif
#define N 5                             //ADC采样使用递推平均滤波算法,采样次数
/*------------------选择波特率改CH1--------------------------------------------*/
#define CH4   1200             //串口波特率
#define CH2   2400             //串口波特率
#define CH3   4800             //串口波特率
#define CH5   9600             //串口波特率
#define CH1  19200             //串口波特率
#define CH0 115200             //串口波特率
#if (CH1==     1200)
    #define        BAUD    CH1
#elif (CH1==   2400)
    #define        BAUD    CH1
#elif (CH1==   4800)
    #define        BAUD    CH1
#elif (CH1==   9600)
    #define        BAUD    CH1
#elif (CH1==  19200)
    #define        BAUD    CH1
#elif (CH1== 115200)
    #define        BAUD    CH1
#endif
/*------------------选择校验改PARITYBIT---------------------------------------------*/
#define NONE_PARITY     0               //无校验
#define ODD_PARITY      1               //奇校验
#define EVEN_PARITY     2               //偶校验
#define MARK_PARITY     3               //标记校验
#define SPACE_PARITY    4               //空白校验
#define PARITYBIT EVEN_PARITY           //定义校验位
#define ReadMode        14              //根据组态王发送来的数据14个字节都是读
#define WritMode1byte   16              //16个字节是写1bite
#define WritMode2byte   18              //18个字节是写整数
#define WritMode4byte   22              //22个字节是写浮点数
/**********组态王读写标记固定在recbuf[3],recbuf[4]******************************************/
#define TYPEReadB            160        //字节读
#define TYPEReadB2           162        //打包字节读
#define TYPEWrirB             81        //字节写
#define TYPEWrirB2            83        //打包字节写
#define TYPEReadW            164        //字读
#define TYPEReadW2           166        //打包字读
#define TYPEWritw             85        //字节写
#define TYPEWritw2            87        //打包字写
#define TYPEReadF            168        //双字读
#define TYPEReadF2           170        //打包双字读
#define TYPEWritF             89        //双字读
#define TYPEWritF2            71        //打包双字读
unsigned char DateRitLen;    //计算组态王传到单片机的数据格式是否匹配
unsigned char ReceiveLen;    //计算组态王传到单片机的字节长度
/*************单片机向组态王回传的信息有***********************/
#define TYPEReadOK            10      //读正确回传10字节
#define TYPEReadER             8      //读错误回传8字节
#define TYPEWritOK             8      //写正确回传8字节
#define TYPEWritER             8      //写错误回传8字节
#define Div(X) (X/10)
#define ANL(X) (X%10)
#define DEC2BCD(X) ((X/10)<<4 | (X%10))               //用于将十进制转成BCD码的宏
#define ASSICDEC(X) (((X<<4)&0XF0) + (X&0x0F))      //用于将BCD码转成十进制的宏
//data uchar x1 _at_ 0x40;      //在data区中定义字节变量x1,地址为0x40H,这里是uchar
//xdata uint x2 _at_ 0x2000;    //在xdata区中定义字变量x2,它的地址为0x2000H,这里是uint

//unsigned int xdata dat[10]={1,7,3,4,5,6,7,8,9,10};
unsigned char  xdata datBYTE[3]={ 5,
                                 6,
                                 7,

                                 };
unsigned int   xdata datWORD[10];
unsigned long  xdata datFOALT[10];    




unsigned char  recbuf[22]={     0x40,      //字头---------组态王向单片机回读写的数据
                                0x30,      //设备地址2
                                0x31,      //设备地址1
                                0x30,      //标志11111111   B(000001100)
                                0x31,      //标志bit0= 0:读,bit0= 1:写 bit1= 0:不打包。
                                   0,      //数据地址
                                   0,      //数据地址
                                   0,      //数据地址
                                   0,      //数据地址
                                   0,      //数据字节数
                                   0,      //数据字节数
                                   0,      //数据
                                   0,      //数据
                                   0,      //数据 CR结束符号读写数据类型为字节为14个数据
                                   0,      //数据
                                   0,      //异或
                                   0,      //异或
                                0x0d,      //CR结束符号读写数据类型为字为18个数据
                                   0,
                                0x0d,      //CR结束符号读写数据类型为浮点型为20个数据
                                   0,
                                0X0D,      //CR结束符号读写数据类型为浮点型为22个数据
                                };
unsigned char xdata sendbuf[16]={0x40,      //字头---------单片机向组态王回复读一个BYTE数据
                                 0x30,      //设备地址
                                 0x31,      //设备地址
                                 0x30,      //标志bit0~bit7-bit0= 0:读,bit0= 1:写。bit1= 0:不打包。bit3bit2 = 00,数据类型为字节。
                                 0x31,      //标志bit3bit2 = 01,数据类型为字。1bit3bit2 = 1x,数据类型为浮点数
                                 0X36,      //数据字节数2
                                 0X34,      //数据字节数。
                                 0X30,      //异或
                                 0X32,      //异或
                                 0x0D,      //CR结束符号
                                    };      //sendbuf[1-2]本机地址位,多机修改此处


/*unsigned char xdata sendbuf1[12]={0x40,        //字头---------单片机向组态王回复读一个BYTE数据
                                  0x30,        //设备地址
                                  0x31,        //设备地址
                                  0x30,        //标志
                                  0x32,        //标志
                                  0x30,        //数据地址  
                                  0x30,        //数据地址
                                  0x30,        //数据字节
                                  0x31,        //数据字节
                                  0x30,        //异或
                                  0x30,        //异或
                                  0x0d,        //CR结束符号
                                  };    */
unsigned char xdata Answer[8]={0x40,        //字头---------单片机向组态王回复读一个BYTE数据    40    30    31    23    23    30    31    0d
                               0x30,        //设备地址
                               0x31,        //设备地址
                                  0,        //数据高位若正确回复23不正确回复2a
                                  0,        //数据低位若正确回复23不正确回复2a
                               0X30,        //异或
                               0X31,        //异或
                               0x0D,        //CR结束符号
                               };
                           //通讯尝试恢复命令(COMERROR),请求地址为0的一个BYTE数据
/*unsigned char xdata Answer2[8]={0x40,        //字头---------单片机向组态王回复读一个BYTE数据    40    30    31    23    23    30    31    0d
                               0x30,        //设备地址
                               0x30,        //设备地址
                               0X30,        //数据高位若正确回复23不正确回复2a
                               0X31,        //数据低位若正确回复23不正确回复2a
                               0X30,        //异或
                               0X30,        //异或
                               0x0D,        //CR结束符号
                               };  */

///40 30 31 32 30 30 30 30 30 30 31 30 32 0D
unsigned char count=0;
BIT flag=0;
BIT recok=0;
//BIT startrec=0;
//BOOL Tempurekey;
unsigned char Li=0;   //动态显示用
unsigned char SendNum;//组态王读单片机回传的字节数

//unsigned char Pv;
unsigned char Pv1;
/*------------------数码管脚定义------------------------------------------*/
sbit     Led_Bit_A   = P3^7;   //段码A段
sbit     Led_Bit_B   = P2^1;   //段码B段
sbit     Led_Bit_C   = P2^2;   //段码C段
sbit     Led_Bit_D   = P2^3;   //段码D段
sbit     Led_Bit_E   = P2^4;   //段码E段
sbit     Led_Bit_F   = P2^5;   //段码F段
sbit     Led_Bit_G   = P2^6;   //段码G段
sbit     Led_Bit_dip = P2^7;   //小数点
sbit     COM1        = P3^6;//数码管个位位选为P3.7
sbit     COM2        = P3^5;//数码管十位位选为P3.6
sbit     COM3        = P3^4;//数码管百位位选为P3.5
/*******************************************************************************************
三位数码管    LEDTYPE =1,共阳数码管 ;LEDTYPE =0,共阴数码管试 LED显示相关定义
    a
   |---|
f |__g| b
   |   |
e |___| c
    d
** 作 者: 李文杰
** 日 期: 2017年11月28日
** 说  明:
        ______       ______       ______      
       |      |     |      |     |      |    
       |      |     |      |     |      |    
       |   1  |     |   2  |     |   3  |    
       |      |     |      |     |      |    
       |______| 3   |______| 2   |______| 1  
           |    |       |    |       |    |      
           |   dot      |   dot      |   dot    
           |            |            |          
      ShowCase[0]  ShowCase[1]  ShowCase[2]  
********************************************************************************************************/
#define LEDTYPE        0     //如果用共阴还是共阳数码管只要改变这里就行了
#if LEDTYPE
#define    LED_TYPE    0xFF     //定义LED类型, 0x00--共阴, 0xff--共阳
#define    LED_TYP2    0x00
#else
#define    LED_TYPE    0x00     //定义LED类型, 0x00--共阴, 0xff--共阳
#define    LED_TYP2    0xFF
#endif
/*************************************************************************************************************/
#define                  b_0000_0001             1
#define                  b_0000_0010             2    
#define                  b_0000_0100             4    
#define                  b_0000_1000             8    
#define                  b_0001_0000            16        
#define                  b_0010_0000             32
#define                  b_0100_0000            64    
#define                  b_1000_0000            128  
/*------------------------------------------------------------------------------------------------------------*/  
#define _a               b_0000_0001
#define _b                  b_0000_0010
#define _c                  b_0000_0100  
#define _d                  b_0000_1000  
#define _e                  b_0001_0000  
#define _f                  b_0010_0000  
#define _g                  b_0100_0000  
#define _p                  b_1000_0000    
/**************************************************************************************************************/    
#define LED_0             LED_TYPE^(_a|_b|_c|_d| _e|_f)
#define LED_1             LED_TYPE^(_b|_c)
#define LED_2             LED_TYPE^(_a|_b|_g|_e|_d)
#define LED_3             LED_TYPE^(_a|_b|_g|_c|_d)
#define LED_4            LED_TYPE^(_f|_g|_b|_c)
#define LED_5            LED_TYPE^(_a|_f|_g|_c|_d)
#define LED_6            LED_TYPE^(_a|_f|_g|_c|_d|_e)
#define LED_7            LED_TYPE^(_a|_b|_c)
#define LED_8            LED_TYPE^(_a|_b|_c|_d|_e|_f|_g)
#define LED_9            LED_TYPE^(_a|_b|_c|_d|_f|_g)
#define LED_a            LED_TYPE^(_a|_b|_c|_e|_f|_g)
#define LED_H            LED_TYPE^(_b|_c|_e|_f|_g)
#define LED_V            LED_TYPE^(_b|_c|_d|_e|_f)
#define LED_e            LED_TYPE^(_a|_d|_d|_e|_f|_g)
#define LED_OF           LED_TYP2^(_a|_b|_c|_d|_e|_f|_g|_p)
#define LED_Y            LED_TYPE^(_b|_c|_d|_f|_g)
#define LED_U            LED_TYPE^(_c|_d|_e)
#define LED_L            LED_TYPE^(_f|_e|_d)
#define LED_P            LED_TYPE^(_a|_b|_e|_f|_g)
#define LED_I            LED_TYPE^(_e|_f )
#define LED_d            LED_TYPE^(_b|_c |_d|_e|_g)
#define LED_r            LED_TYPE^(_e|_g)
#define LED_T            LED_TYPE^(_a|_e|_f)
#define LED_b            LED_TYPE^(_c|_d|_e|_f|_g)
#define LED_c            LED_TYPE^(_a|_d|_e|_f)
#define LED_K            LED_TYPE^(_b|_d|_e|_f|_g)
#define LED_S            LED_TYPE^(_a|_c|_d|_f|_g)
#define LED_O_1             LED_TYPE^(_a|_b|_f|_g)                //上层'o'
#define LED_O_2          LED_TYPE^(_c|_d|_e|_g)                 //下层'o'      
#define LED_Z             LED_TYPE^(_a|_b|_e|_d)  
#define LED_f             LED_TYPE^(_a|_e|_f|_g)  
#define LED_n            LED_TYPE^(_c|_e|_g)
#define LED_fu           LED_TYPE^(_g)
#define LED_DROP         LED_TYPE^(_p)
/*******************************************************************************************************************/
/*#define kCode            LED_K     //k段码
#define hCode            LED_H     //h段码
#define offCode          LED_OF    //熄灭段码
#define lCode            LED_L     //L段码
#define pCode            LED_P     //P段码
#define sCode            LED_S     //s段码
#define vCode            LED_V     //v段码
#define eCode            LED_E     //e段码
#define rCode            LED_r     //r段码
#define oCode            LED_O_2   //o段码
#define negativeCode     LED_fu    //负号段码
#define aCode            LED_A     //a段码
#define bCode            LED_b     //b段码
#define cCode            LED_C     //c段码
#define dCode            LED_d     //d段码
#define fCode            LED_F     //d段码
#define iCode            LED_I     //i段码
#define tCode            LED_T     //t段码
#define yCode            LED_Y     //y段码
#define uCode            LED_U     //y段码
#define CHAR_A           LED_TYP2^0x88
#define CHAR_b           LED_TYP2^0x83
#define CHAR_B           LED_TYP2^0x80
#define CHAR_C           LED_TYP2^0xC6
#define CHAR_c           LED_TYP2^0xA7
#define CHAR_d           LED_TYP2^0xA1
#define CHAR_E           LED_TYP2^0x86
#define CHAR_F           LED_TYP2^0x8E
#define CHAR_H           LED_TYP2^0x89
#define CHAR_h           LED_TYP2^0x8B
#define CHAR_i           LED_TYP2^0xFB
#define CHAR_I           LED_TYP2^0xF9
#define CHAR_J           LED_TYP2^0xE1
#define CHAR_K           LED_TYP2^0x85
#define CHAR_L           LED_TYP2^0xC7
#define CHAR_m           LED_TYP2^0xEA
#define CHAR_n           LED_TYP2^0xAB
#define CHAR_o           LED_TYP2^0xA3
#define CHAR_O           LED_TYP2^0xC0
#define CHAR_P           LED_TYP2^0x8C
#define CHAR_r           LED_TYP2^0xAF
#define CHAR_S           LED_TYP2^0x92
#define CHAR_t           LED_TYP2^0x87
#define CHAR_T           LED_TYP2^0xCE
#define CHAR_U           LED_TYP2^0xC1
#define CHAR_u           LED_TYP2^0xE3
#define CHAR_y           LED_TYP2^0x91
#define CHAR_dot         LED_TYP2^0x7F
#define CHAR_zero        LED_TYP2^0xC0      //0
#define CHAR_neg         LED_TYP2^0xBF      //-
#define CHAR_neg1        LED_TYP2^0xB9      //-1
#define CHAR_dseg        LED_TYP2^0xF7
#define CHAR_off         LED_TYP2^0xFF
#define CHAR_on          LED_TYP2^0x00
#define CHAR_od          LED_TYP2^0x9C
#define CHAR_1           LED_TYP2^0xF9
#define CHAR_2           LED_TYP2^0xA4
#define CHAR_3           LED_TYP2^0xB0
#define CHAR_4           LED_TYP2^0x99
#define CHAR_5           LED_TYP2^0x92
#define CHAR_6           LED_TYP2^0x82
/*------------------数码管段码表----------------------------------------*/
unsigned char code table[18]=     {         //需要显示的段选码
                                  LED_0,     //0
                                  LED_1,     //1
                                  LED_2,     //2
                                  LED_3,     //3
                                  LED_4,     //4
                                  LED_5,     //5
                                  LED_6,     //6
                                  LED_7,     //7
                                  LED_8,     //8
                                  LED_9,     //9
                                  LED_a,
                                  LED_b,
                                  LED_c,
                                  LED_d,
                                  LED_e,
                                  LED_f,
                                  LED_fu,
                                  LED_P,
                                 };

/********************************************************************************************************
**     函数名称:            void    digital_CODE()
**    功能描述:            驱动数码管位码
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
void digital_CODE(unsigned char ch)  //led段码发送函数开始  
{      ACC=ch;
    COM1=COM2=COM3=1;
    Led_Bit_A  = ACC0;
    Led_Bit_B  = ACC1;
    Led_Bit_C  = ACC2;
    Led_Bit_D  = ACC3;
    Led_Bit_E  = ACC4;
    Led_Bit_F  = ACC5;
    Led_Bit_G  = ACC6;
    Led_Bit_dip= ACC7;
}


/********************************************************************************************************
**     函数名称:            void    uartsends()
**    功能描述:            串口发送数据串
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
void uartsends(unsigned char buff[],uchar len)
{   unsigned char i;
    for(i=0;i<len;i++)
    {   SBUF=buff;
        while(!TI);
        TI=0;
    }
}
/*************把组态王中的ASSIC码转换成16进制两个ASSIC组成1BYTE16进制码与常规的ASSIC转法不一样*********/
unsigned char CharToHex(unsigned char bHex)  
{   unsigned char temp;
    if(   bHex>0x40)
    temp=(bHex-0x37)&0x0f;    //只取低四位00001111----bit0-bit1--bit2--bit3
    else
    temp=(bHex-0x30)&0x0f;    //只取低四位00001111----bit0-bit1--bit2--bit3
    return temp;  
}
/********************************************************************************************************
**     函数名称:            unsigned char read_write_flag()
**    功能描述:            判断是读组态王的数据还是回传组态王数据
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
/*unsigned char read_write_flag(void)
{
     unsigned char temp;
//    temp=CharToHex(recbuf[4]);
    if(   recbuf[4]>0x40)
    temp=(recbuf[4]-0x37)&0x0f;    //只取低四位00001111----bit0-bit1--bit2--bit3
    else
    temp=(recbuf[4]-0x30)&0x0f;    //只取低四位00001111----bit0-bit1--bit2--bit3
    return temp;
}
/********************************************************************************************************
**     函数名称:            data_num(void)
**    功能描述:            判断发送和写的字节数
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
unsigned char data_num(void)        //data_num=1byte;data_num=2word;data_num=4folat
{                                    
    unsigned char temp;
    temp=CharToHex(recbuf[9]);
    temp=(temp<<4)&0XF0;
    temp+=CharToHex(recbuf[10]);
    return temp;
}

/********************************************************************************************************
**     函数名称:            Dat_trans(unsigned char hight_v,uchar low_v)
**    功能描述:            双字节ASCII码转换成16进制1BYTE
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
/*unsigned char TwoAssitoHEX(unsigned char hight_v,uchar low_v)
{
unsigned char value;//hight,low;
value=(CharToHex(hight_v)<<4)&0X0F;
value+=CharToHex(low_v);
/*if(hight_v>0x40)
hight=hight_v-0x37;          //当0xa<=x<=0xf时对应的ASCII码是x+0x37
else hight=hight_v-0x30;  //当0<=x<=9时对应的ASCII码是x+0x30;
if(low_v>0x40)
low=low_v-0x37;
else
low=low_v-0x30;
value=(hight&0x0f)<<4;
value+=(low&0x0f); */
/*return value;
}

/****************根据接收到的信息处理回传的信息**************************/
void write()
{
unsigned char ctmp1=0,ctmp2=0,xordat=0,i;
unsigned int send_temp=0;
sendbuf[1]=recbuf[1];     //地址同步
sendbuf[2]=recbuf[2];
sendbuf[3]=recbuf[9];     //字节数同步
sendbuf[4]=recbuf[10];
/********读1字节数************************************/
if(data_num()==1) {
// sendbuf[5]=0X36;
// sendbuf[6]=0X34;
  ctmp1=(datBYTE[0]>>4)&0x0f;
  if(ctmp1>9)                //异或高位
  sendbuf[5]=ctmp1%9+0x40;
  else
  sendbuf[5]=ctmp1+0x30;  
  ctmp2=datBYTE[0]&0x0f;
  if(ctmp2>9)                //异或低位
  sendbuf[6]=ctmp2%9+0x40;    
  else
  sendbuf[6]=ctmp2+0x30;  
//  sendbuf[5]=datBYTE[0];
//  sendbuf[6]=datBYTE[0];


  xordat=0;
  for(i=1;i<7;i++)
  xordat^=sendbuf;
  send_temp=xordat;
  ctmp1=(send_temp>>4)&0x0f;
  if(ctmp1>9)                //异或高位
  sendbuf[7]=ctmp1%9+0x40;
  else
  sendbuf[7]=ctmp1+0x30;    
  ctmp2=send_temp&0x0f;
  if(ctmp2>9)                //异或低位
  sendbuf[8]=ctmp2%9+0x40;    
  else
  sendbuf[8]=ctmp2+0x30;
  sendbuf[9]=0X0D;    
  SendNum=10;                //字节读回传10个数据
  uartsends(sendbuf,SendNum);
                   }
/********读2字节数************************************/
//40 30 31 41 34 30 30 30 30 30 32 37 36 0D
//40 30 31 30 32 30 30 36 34 30 33 0D
if(data_num()==2) {
sendbuf[5]=0X30;     //00
sendbuf[6]=0X30;
sendbuf[7]=0X36;     //120
sendbuf[8]=0X34;
xordat=0;
for(i=1;i<9;i++)
xordat^=sendbuf;
send_temp=xordat;
ctmp1=(send_temp>>4)&0x0f;
if(ctmp1>9)                        //异或高位
sendbuf[9]=ctmp1%9+0x40;
else sendbuf[9]=ctmp1+0x30;
ctmp2=send_temp&0x0f;
if(ctmp2>9)                        //异或低位
sendbuf[10]=ctmp2%9+0x40;
else sendbuf[10]=ctmp2+0x30;
sendbuf[11]=0x0D;
uartsends(sendbuf,12);            //字节读回传12个数据
                   }        
/********读4字节数************************************/

if(data_num()==4) {
sendbuf[5] =0X30;     //字节数同步
sendbuf[6] =0X30;
sendbuf[7] =0X46;     //字节数同步
sendbuf[8] =0X46;
sendbuf[9] =0X46;     //字节数同步
sendbuf[10]=0X46;
sendbuf[11]=0X30;     //字节数同步
sendbuf[12]=0X30;
xordat=0;
for(i=1;i<13;i++)
xordat^=sendbuf;
send_temp=xordat;
ctmp1=(send_temp>>4)&0x0f;
if(ctmp1>9)
sendbuf[13]=ctmp1%9+0x40;
else
sendbuf[13]=ctmp1+0x30;     //异或高位
ctmp2=send_temp&0x0f;
if(ctmp2>9)
sendbuf[14]=ctmp2%9+0x40;    //异或低位
else
sendbuf[14]=ctmp2+0x30;    //异或低位
sendbuf[15]=0X0D;
SendNum=16;                //字节读回传16个数据
uartsends(sendbuf,SendNum);
                   }

}

/****************组态王写字节数据处理**************************/
// 40  30 31 35 31 30 30 30 30 30 31  30 31  30 35 0D
// 40  30 31 35 31 30 30 30 30 30 31  43 38  37 46 0D--寄存器选择X0---BYTE--数据是200
//字头-地址--模 式-数据-- 地址-字-节--数-值--异-或
//--0  1  2  3  4  5--6--7--8  9  10  11 12  13 14 15

void writeMCU()
{   unsigned char temp;          //组态王写入MCU的数据值
    unsigned int  tempAddr;      //组态王写入MCU的地址值X0,X1--X200
    temp=CharToHex(recbuf[11]);
    temp=(temp<<4)&0XF0;
    temp+=CharToHex(recbuf[12]);
    datBYTE[0]=temp;
    tempAddr=CharToHex(recbuf[5]);
    tempAddr=(tempAddr<<4)&0XF0;
    tempAddr+=CharToHex(recbuf[6]);
    tempAddr=(tempAddr<<4)&0XF0;
    tempAddr+=CharToHex(recbuf[7]);
    tempAddr=(tempAddr<<4)&0XF0;
    tempAddr+=CharToHex(recbuf[8]);
    Pv1=datBYTE[0];
    Pv1=tempAddr;



}
/********************************************************************************************************
**     函数名称:            Dat_trans(unsigned char hight_v,uchar low_v)
**    功能描述:            双字节ASCII码转换成16进制1BYTE
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
/*unsigned char TwoAssitoHEX(unsigned char hight_v,uchar low_v)
{
unsigned char value,hight,low;
//value=CharToHex(hight_v)<<4;
//value+=CharToHex(low_v);
if(hight_v>0x40)
hight=hight_v-0x37;          //当0xa<=x<=0xf时对应的ASCII码是x+0x37
else hight=hight_v-0x30;  //当0<=x<=9时对应的ASCII码是x+0x30;
if(low_v>0x40)
low=low_v-0x37;
else
low=low_v-0x30;
value=(hight&0x0f)<<4;
value+=(low&0x0f);
return value;
}
/********************************************************************************************************
**     函数名称:            write_inform(unsigned char dat)
**    功能描述:            单片机向计算机组态王发送8字节数据
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
void write_inform(unsigned char dat)
{
unsigned char xordat,i,ctmp1,ctmp2,send_temp;
Answer[1]=recbuf[1];
Answer[2]=recbuf[2];
Answer[3]=dat;         //数据高位若正确回复23不正确回复2a
Answer[4]=dat;         //数据低位若正确回复23不正确回复2a
xordat=0;
for(i=1;i<5;i++)
xordat^=Answer;
send_temp=xordat;
ctmp1=(send_temp>>4)&0x0f;
if(ctmp1>9)
Answer[5]=ctmp1%9+0x40;
else
Answer[5]=ctmp1+0x30;     //异或高位
ctmp2=send_temp&0x0f;
if(ctmp2>9)
Answer[6]=ctmp2%9+0x40;    //异或低位
else
Answer[6]=ctmp2+0x30;    //异或低位
uartsends(Answer,8);
}
/********************************************************************************************************
**     函数名称:            AddrInit()
**    功能描述:            地址数据初始化
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
/*void AddrInit(void)
{
unsigned char ctmp;
ctmp=(MyAddr>>4);
if(ctmp>9)
{
sendbuf [1]=0x40+ctmp%9;
sendbuf1[1]=0x40+ctmp%9;
}
else
{
sendbuf [1]=ctmp+0x30;
sendbuf1[1]=ctmp+0x30;
}
ctmp=MyAddr&0x0f;
if(ctmp>9)
{
sendbuf [2]=0x40+ctmp%9;
sendbuf1[2]=0x40+ctmp%9;
}
else
{
sendbuf [2]=ctmp+0x30;
sendbuf1[2]=ctmp+0x30;
}
}





void Sendkingviow()
{                    switch(ReceiveLen)
                           {
                           /*组态王读数据单片机回传*/
                             case 14:    
                                          write();                                        
                                        ;break;
                           /*组态王写字节数据单片机回传40    30    31    23    23    30    31    0d不正确回传40    30    31    2A    2A    30    31    0d*/
                            case 16:  
                                        write_inform('#');
                                        writeMCU();
                                       ;break;
                            /*组态王写双字节数据单片机回传*/
                            case 18:  
                                        write_inform('#');
                                       ;break;
                            /*组态王写四字节数据单片机回传*/
                            case 22:  
                                        write_inform('#');
                                       ;break;
                            default://write_inform('*');
                                        write_inform('*');
                                        break;    

                           }
            

}


/********************************************************************************************************
**     函数名称:            serial_init()
**    功能描述:            串口1初始化函数
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
void serial_init()
{
/*****************AT89C52单片机定时器1做波特率发生器***************************/
/*
    SCON=0x50;
    TMOD=0X20;
    TH1=0xfd;
    TL1=0xfd;
    TR1=1;       */
/*****************STC15F2K60S2定时器1做波特率发生器***************************/
/*    PCON &= 0x7F;        //波特率不倍速
    SCON = 0x50;        //8位数据,可变波特率
    AUXR |= 0x40;        //定时器1时钟为Fosc,即1T
    AUXR &= 0xFE;        //串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;        //清除定时器1模式位
    TMOD |= 0x21;        //设定定时器1为8位自动重装方式
#if (CH1==   9600)
    TL1 = 0xdc;        //设定定时初值
    TH1 = 0xdc;        //设定定时器重装值 0xdc
#elif (CH1==   19200)
    TL1 = 0xEE;        //设定定时初值
    TH1 = 0xEE;        //设定定时器重装值
#endif
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
/*****************STC15F2K60S2定时器2做波特率发生器**************************/
    T2L = (65536 - (MAIN_Fosc/4/BAUD));   //设置波特率重装值
    T2H = (65536 - (MAIN_Fosc/4/BAUD))>>8;
    AUXR = 0x14;                //T2为1T模式, 并启动定时器2
    AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器    
#if (PARITYBIT   == NONE_PARITY)
    SCON = 0X50;                //8位可变波特率
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
    SCON = 0XDA;                //9位可变波特率,校验位初始为1
#elif (PARITYBIT == SPACE_PARITY)
    SCON = 0XD2;                //9位可变波特率,校验位初始为0
#endif    
    ES = 1;                     //使能串口1中断
    EA = 1;                        //使能总中断

}



//unsigned char  LED;
/********************************************************************************************************
**     函数名称:            void    main()
**    功能描述:            主函数
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
void main (void)//主函数
{ TH0=T1MS>>8;                                                  //1MS
  TL0=T1MS;
  ET0=1;
  TR0=1;
  serial_init();
  P1M0=B(00000000);//P1除P1.0,P1.1,P1.2为输入模式外均为正常模式
  P1M1=B(00000111);
  P1ASF=(00000111);//设置P1相应ADC转换的I/O口为ADC输入模式
  P2M0=B(11111111);//P2都是推挽模式
  P2M1=B(00000000);
  P3M0=B(11110000);//P3.4,P3.5,P3.6,P3.7为推挽模式,P3.2,P3.3为输入模式,其余正常模式
  P3M1=B(00000000);

  while(1){    
             if(recok)
            {
               ET0=0;
               // Pv=ReceiveLen;
             //  Pv1=data_num();
               Sendkingviow();
               recok=0;
               ET0=1;    
             }

  }

}
/********************************************************************************************************
**     函数名称:            recive(void)
**    功能描述:            串口中断函数
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
void recive(void) interrupt UART1_VECTOR
{  if(RI){
    if(SBUF==Start)         //如果接收到的是开头符号(ASCII码为0X40--"@  ")
    flag=1,ReceiveLen=0X00;
    if(flag==1)
    {   recbuf[count]=SBUF;
        count++;
        if(SBUF==ReceivEND)    //如果接收到的是结束符号(ASCII码为0X0D--"*")
        {   flag=0;
            ReceiveLen=count;
            count=0;
            recok=1;

          }
      }
     RI=0;                 //从新开启串口中断    
  }
    if (TI)
    {
        TI = 0;                 //清除TI位
    //    busy = 0;               //清忙标志
    }
                                
}
/*
void sio_int() interrupt 4 using 3   //串口中断函数
{
ES=0;
  //串口中断处理
if(RI)
{
  if(SBUF!=0x08)  //如果接收到的是退格(ASCII码为0x08)
   cmd_buf[counter++]=SBUF;
  else
   counter--;
  RI=0;
}

if((SBUF==0x0d)&(file_ok!=1))      //如果file_ok=0,且串口输入回车,那么命令结束
{
  cmd_buf[counter-1]=0;
  counter=0;
  flag=1;
}

if((SBUF==0x0a)&(file_ok!=0))      //如果file=1,且串口输入换行,则该次输入结束
{
  cmd_buf[counter]=0;
  counter=0;
  flag=1;
}
ES=1;
}
/********************************************************************************************************
**     函数名称:            timer0()
**    功能描述:            定时器0中断函数
**    创 建 者:            李文杰
**    创建时间:            2017-11-28 3:48
**    版    本:            v1.0.0
*********************************************************************************************************/
void  timer0() interrupt TIMER0_VECTOR //显示中断;前两位调试用,
{    
TH0=T1MS>>8;                                                  //1MS
TL0=T1MS;
Li++;  
if(Li==2)///
{ digital_CODE(table[Pv1/100%10]);
COM3=0; COM1=1;
}
if(Li==4)
{
  digital_CODE(table[Pv1/10%10]);
  COM3=1;  COM2=0;
}

if(Li==6)
{ digital_CODE(table[Pv1%10]);
  COM1=0;  COM2=1;

}
if(Li==8)
{

Li=0;

}
}
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖提到的人: @
本帖最近打赏记录:共1条打赏M币+8
huchuan987 M币 +8 原創內容,收藏一个! 01-02
离线huchuan987

发帖
4480
M币
140
专家
10
粉丝
103
只看该作者 1楼 发表于: 01-02
原創內容,收藏一个!
离线yht7891984

发帖
2024
M币
1176
专家
5
粉丝
45
只看该作者 2楼 发表于: 01-09
学习一下modbus协议, 然后发现很好写.不用这么复杂的
离线chw321401

发帖
751
M币
168
专家
3
粉丝
57
只看该作者 3楼 发表于: 01-13
李老师  潜水多长了呀?
快速回复
限80 字节
温馨提示:所有技术区严禁灌水,“沙发”“顶”字样;禁止广告贴;以免被删除
 
上一个 下一个