找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6214|回复: 4
打印 上一主题 下一主题
收起左侧

组态王与单片机通讯上位机及下位机源码 附测试数据与协议

  [复制链接]
跳转到指定楼层
楼主
组态王与单片机通讯亲测.



/*********************字节读写****************************************/
组态王向地址是1的单片机读取1byte数据组态王选择效验没变化都是一样的数据
40 30 31 41 30 30 30 30 30 30 31 37 31 0D--寄存器选择X0---BYTE---160-----14个字节07 D0 31 30 31 30 31 45 31 0D
40 30 31 41 30 30 30 30 30 30 31 37 31 0D
40 30 31 41 32 30 30 30 30 30 31 37 33 0D----162----打包与不打包除了格式和效验位的数值不一样了,好像没啥区别,呵呵!!

40 30 31 41 30 30 30 36 34 30 31 37 33 0D--寄存器选择X100---BYTE--0X64=100
40 30 31 41 30 30 30 43 38 30 31 30 41 0D--寄存器选择X200---BYTE--0XC8=200
40 30 31 41 30 30 31 32 43 30 31 30 31 0D--寄存器选择X300---BYTE--0X12C=300
40 30 31 41 30 30 37 44 30 30 31 30 32 0D--寄存器选择X2000---BYTE--0X7D0=2000
40   30 31 41 30 34 45 32 30 30 31  30 32 0D--寄存器选择X20000---BYTE--0X4E20=20000
字头-地址--模 式-数据-- 地址-字-节--异-或
组态王向地址是1的单片机写入1byte数据组--------------81--------------------16个字节
40 30 31 35 31 30 30 30 30 30 31 30 31 30 35 0D--寄存器选择X0---BYTE--数据是1                            40 30 31 23 23 30 31 0D
40  30 31 35 31 30 30 30 30 30 31  30 41  37 35 0D--寄存器选择X0---BYTE--数据是10--0X41-0X37=0X0A=10     40 30 31 23 23 30 31 0D
40  30 31 35 31 30 30 30 30 30 31  36 34  30 36 0D--寄存器选择X0---BYTE--数据是100
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
/*********************字读写****************************************/
组态王向地址是1的单片机读2byte数据组------------------164------------------14个字节
40 30 31 41 34 30 30 30 30 30 32 37 36 0D--寄存器选择X0---USHORT--数据0                        40 30 31 30 32 30 30 30 31 30 32 0D
40 30 31 41 34 30 30 30 41 30 32 30 37 0D--寄存器选择X10---USHORT--数据10  0X41-0X37=0X0A=10   40 30 31 30 32 30 37 44 30 37 30 0D
40 30 31 41 34 45 41 36 30 30 32 37 34 0D--寄存器选择X60000---USHORT--EA60=60000               40 30 31 30 32 46 46 46 41 30 34 0D
字头-地址模式-数据----地址--字节-异或值
组态王向地址是1的单片机写入2byte数据组----------------85------------------18个字节
40 30 31 35 35 30 30 30 41 30 32 30 37 44 30 30 31 0D--寄存器选择X10---USHORT--数据是2000      40 30 31 23 23 30 31 0D
40 30 31 35 37 30 30 30 41 30 32 30 37 44 30 30 33 0D----87-----打包                           40 30 31 23 23 30 31 0D

/*********************浮点数读写****************************************/
组态王向地址是1的单片机读4byte数据组--------------168--------------------14个字节
40 30 31 41 38 30 30 30 30 30 34 37 43 0D--寄存器选择X0---FLOAT---14个字节
40 30 31 41 38 30 30 36 34 30 34 37 45 0D--寄存器选择X100---FLOAT
字头-地址模式-数据---地址--字节-异或值
组态王向地址是1的单片机写入4byte数据组---------------89-----------------22个字节
40 30 31 35 39 30 30 30 41 30 34 30 37 43 37 46 41 45 31 37 38 0D--寄存器选择X10---FLOAT--数据是99.99   40 30 31 23 23 30 31 0D
40 30 31 35 39 30 30 36 34 30 34 31 31 38 32 33 35 30 30 30 37 0D--寄存器选择X100---FLOAT--数据是66666  40 30 31 23 23 30 31 0D


40 30 31 41 34 30 30 36 34 30 32 37 34 0D---SHORT读
40 30 31 41 34 30 30 36 34 30 32 37 34 0D

40 30 31 41 34 30 30 36 34 30 32 37 34 0D---USHORT读
40 30 31 41 34 30 30 36 34 30 32 37 34 0D


40 30 31 32 30 30 30 30 30 30 31 30 32 0D
40 30 31 32 30 30 30 30 30 30 31 30 32 0D
40 30 31  30 31 36 34 30 32 0D


40 30 31 39 30 30 30 30 30 30 31 30 39 0D
40 30 31 30 31 36 34 30 32 0D


40 30 31 39 32 30 30 30 30 30 31 30 42 0D


40 30 31 39 30 30 30 30 30 30 31 30 39 0D


40 30 31 23 23 30 31 0D

单片机源程序如下:
  1. /***************写在前面*************************************************************************************
  2. 程序思路:组态王向单片机通讯总共就两条命令读命令和写命令
  3.           读命令共分三条,字节读和双字和浮点读三条命令
  4.                   写命令也分三条,字节读和双字和浮点读三条命令
  5.                   读时的三条命令的数据长度都一样都是14个ASSIC码
  6.                   而且单片机回传的数据分别是10个ASSIC码和12个ASSIC码和16个ASSIC码
  7.                     40  30 31 30 32 30 30 30 31  0D                                 数据是1个字节2个ASSIC码
  8.                   [字头-地-址-字节--数-据-异或值-字尾]
  9.                     40  30 31 30 32 30 30 30 31 30--30  0D                         数据是2个字节4个ASSIC码
  10.                   [字头-地-址-字节--数-------据-异或值-字尾]
  11.                     40  30 31 30 32 30 30 30 30 30-30-30-30----31-30--0D         数据是4个字节8个ASSIC码
  12.                   [字头-地-址-字节--数-------------------据---异或值-字尾]
  13.                   写时的命令组态王分别发送字节16个ASSIC到单片机,双字节是18个ASSIC和浮点22个2ASSIC码
  14.                   单片机只需回答正确和不正确的俩条命令 40 30 31 23 23 30 31 0D
  15.                   然后再把数据处理就可以了如果不理解请仔细阅读组态王与单片劫ASSIC通讯手册。
  16.           与组态王通讯时请注意选择的单片机晶震频率和波特率及效验否则无法通讯成功
  17.           本次测试组态王只支持19200波特率,再高的波特率没有成功,
  18.           不知道是何原因难道组态的原因吗?
  19. **        功能描述:                        接收组态王的数据
  20. **(组态王发送来的数据有读都是14个ASSIC,
  21.                        bite写16个ASSIC,
  22.                        word写18个ASSIC,
  23.                                           FLOAT写22个ASSIC,
  24. **单片机回传----读单字节时正确回传10个个ASSIC,读双字节时正确回传12个个ASSIC,读浮点时正确回传16个个ASSIC,
  25.                 读时不正确回传8个个ASSIC
  26. **单片机回传----写时正确回传  8个个ASSIC,
  27.                 写时不正确回传8个个ASSIC  
  28. //data_num=1byte;data_num=2word;data_num=4folat                          
  29.                                                                    
  30. **        创 建 者:                        李文杰
  31. **        创建时间:                        2017-11-28 3:48
  32. **        版    本:                        v1.0.0
  33. ************************************************************************************************************/
  34. #include "kongview.h"
  35. //#define MODE1T                        //Timer clock mode, comment this line is 12T mode, uncomment is 1T mode
  36. #ifdef  MODE1T
  37. #define T1MS (65536-(MAIN_Fosc/1000))      //1ms timer calculation method in 1T mode
  38. #else
  39. #define T1MS (65536-(MAIN_Fosc/12/1000))      //1ms timer calculation method in 12T mode
  40. #endif
  41. #define N 5                             //ADC采样使用递推平均滤波算法,采样次数
  42. /*------------------选择波特率改CH1--------------------------------------------*/
  43. #define CH4   1200             //串口波特率
  44. #define CH2   2400             //串口波特率
  45. #define CH3   4800             //串口波特率
  46. #define CH5   9600             //串口波特率
  47. #define CH1  19200             //串口波特率
  48. #define CH0 115200             //串口波特率
  49. #if (CH1==     1200)
  50.     #define                BAUD        CH1
  51. #elif (CH1==   2400)
  52.         #define                BAUD        CH1
  53. #elif (CH1==   4800)
  54.         #define                BAUD        CH1
  55. #elif (CH1==   9600)
  56.         #define                BAUD        CH1
  57. #elif (CH1==  19200)
  58.         #define                BAUD        CH1
  59. #elif (CH1== 115200)
  60.         #define                BAUD        CH1
  61. #endif
  62. /*------------------选择校验改PARITYBIT---------------------------------------------*/
  63. #define NONE_PARITY     0               //无校验
  64. #define ODD_PARITY      1               //奇校验
  65. #define EVEN_PARITY     2               //偶校验
  66. #define MARK_PARITY     3               //标记校验
  67. #define SPACE_PARITY    4               //空白校验
  68. #define PARITYBIT EVEN_PARITY           //定义校验位
  69. #define ReadMode        14              //根据组态王发送来的数据14个字节都是读
  70. #define WritMode1byte   16              //16个字节是写1bite
  71. #define WritMode2byte   18              //18个字节是写整数
  72. #define WritMode4byte   22              //22个字节是写浮点数
  73. /**********组态王读写标记固定在recbuf[3],recbuf[4]******************************************/
  74. #define TYPEReadB            160        //字节读
  75. #define TYPEReadB2           162        //打包字节读
  76. #define TYPEWrirB             81        //字节写
  77. #define TYPEWrirB2            83        //打包字节写
  78. #define TYPEReadW            164                //字读
  79. #define TYPEReadW2           166                //打包字读
  80. #define TYPEWritw             85                //字节写
  81. #define TYPEWritw2            87                //打包字写
  82. #define TYPEReadF            168                //双字读
  83. #define TYPEReadF2           170                //打包双字读
  84. #define TYPEWritF             89                //双字读
  85. #define TYPEWritF2            71                //打包双字读
  86. #define Control_MCUIO         P1        //组态王要控制的IO
  87. unsigned char DateRitLen;    //计算组态王传到单片机的数据格式是否匹配
  88. unsigned char ReceiveLen;    //计算组态王传到单片机的字节长度
  89. /*************单片机向组态王回传的信息有***********************/
  90. #define TYPEReadOK                        10      //读正确回传10字节
  91. #define TYPEReadER                         8      //读错误回传8字节
  92. #define TYPEWritOK                         8      //写正确回传8字节
  93. #define TYPEWritER                         8      //写错误回传8字节
  94. #define Div(X) (X/10)
  95. #define ANL(X) (X%10)
  96. #define ASSICDEC(X) (((X<<4)&0XF0) + (X&0x0F))      //宏
  97. unsigned char  xdata datBYTE[3]={ 0,
  98.                                                                   0,
  99.                                                                   0,

  100.                                  };
  101. //unsigned int   xdata datWORD[10];
  102. //unsigned long  xdata datFOALT[10];       




  103. unsigned char  recbuf[22]={     0x40,          //字头---------组态王向单片机回读写的数据
  104.                                                                 0x30,          //设备地址2
  105.                                                                 0x31,          //设备地址1
  106.                                                                 0x30,          //标志11111111   B(000001100)
  107.                                                                 0x31,          //标志bit0= 0:读,bit0= 1:写 bit1= 0:不打包。
  108.                                                                    0,          //数据地址
  109.                                                                    0,          //数据地址
  110.                                                                    0,          //数据地址
  111.                                                                    0,          //数据地址
  112.                                                                    0,          //数据字节数
  113.                                                                    0,          //数据字节数
  114.                                                                    0,          //数据
  115.                                                                    0,          //数据
  116.                                                                    0,          //数据 CR结束符号读写数据类型为字节为14个数据
  117.                                                                    0,          //数据
  118.                                                                    0,          //异或
  119.                                                                    0,          //异或
  120.                                                                 0x0d,          //CR结束符号读写数据类型为字为18个数据
  121.                                                                    0,
  122.                                                                 0x0d,          //CR结束符号读写数据类型为浮点型为20个数据
  123.                                                                    0,
  124.                                                                 0X0D,          //CR结束符号读写数据类型为浮点型为22个数据
  125.                                 };
  126. unsigned char xdata sendbuf[16]={0x40,          //字头---------单片机向组态王回复读一个BYTE数据
  127.                                  0x30,          //设备地址
  128.                                                                  0x31,          //设备地址
  129.                                                                  0x30,          //标志bit0~bit7-bit0= 0:读,bit0= 1:写。bit1= 0:不打包。bit3bit2 = 00,数据类型为字节。
  130.                                                                  0x31,          //标志bit3bit2 = 01,数据类型为字。1bit3bit2 = 1x,数据类型为浮点数
  131.                                                                  0X36,          //数据字节数2
  132.                                                                  0X34,          //数据字节数。
  133.                                                                  0X30,          //异或
  134.                                                                  0X32,          //异或
  135.                                                                  0x0D,          //CR结束符号
  136.                                                                         };          //sendbuf[1-2]本机地址位,多机修改此处
  137. unsigned char xdata Answer[8]={0x40,                //字头---------单片机向组态王回复读一个BYTE数据        40        30        31        23        23        30        31        0d
  138.                                0x30,                //设备地址
  139.                                                            0x31,                //设备地址
  140.                                                               0,                //数据高位若正确回复23不正确回复2a
  141.                                                               0,                //数据低位若正确回复23不正确回复2a
  142.                                                            0X30,                //异或
  143.                                                            0X31,                //异或
  144.                                                            0x0D,                //CR结束符号
  145.                                                            };
  146. unsigned char count=0; //接收组态王的数据字节计数
  147. BIT flag=0;                    //单片机接收计算机字头正确标记
  148. BIT recok=0;                   //接收组态王的数据成功
  149. unsigned char Li=0;    //动态显示用
  150. unsigned char SendNum; //组态王读单片机回传的字节数
  151. unsigned char Pv1;           //数码管显示
  152. //定义一个指针
  153. /*------------------数码管脚定义------------------------------------------*/
  154. sbit     Led_Bit_A   = P3^7;   //段码A段
  155. sbit     Led_Bit_B   = P2^1;   //段码B段
  156. sbit     Led_Bit_C   = P2^2;   //段码C段
  157. sbit     Led_Bit_D   = P2^3;   //段码D段
  158. sbit     Led_Bit_E   = P2^4;   //段码E段
  159. sbit     Led_Bit_F   = P2^5;   //段码F段
  160. sbit     Led_Bit_G   = P2^6;   //段码G段
  161. sbit     Led_Bit_dip = P2^7;   //小数点
  162. sbit     COM1        = P3^6;//数码管个位位选为P3.7
  163. sbit     COM2        = P3^5;//数码管十位位选为P3.6
  164. sbit     COM3        = P3^4;//数码管百位位选为P3.5
  165. /*******************************************************************************************
  166. 三位数码管        LEDTYPE =1,共阳数码管 ;LEDTYPE =0,共阴数码管试 LED显示相关定义
  167.     a
  168.    |---|
  169. f |__g| b
  170.    |   |
  171. e |___| c
  172.     d
  173. ** 作 者: 李文杰
  174. ** 日 期: 2017年11月28日
  175. ** 说  明:
  176.         ______       ______       ______      
  177.        |      |     |      |     |      |     
  178.        |      |     |      |     |      |     
  179.        |   1  |     |   2  |     |   3  |   
  180.        |      |     |      |     |      |   
  181.        |______| 3   |______| 2   |______| 1  
  182.            |    |       |    |       |    |      
  183.            |   dot      |   dot      |   dot   
  184.            |            |            |           
  185.       ShowCase[0]  ShowCase[1]  ShowCase[2]  
  186. ********************************************************************************************************/
  187. #define LEDTYPE        0         //如果用共阴还是共阳数码管只要改变这里就行了
  188. #if LEDTYPE
  189. #define        LED_TYPE        0xFF         //定义LED类型, 0x00--共阴, 0xff--共阳
  190. #define        LED_TYP2        0x00
  191. #else
  192. #define        LED_TYPE        0x00         //定义LED类型, 0x00--共阴, 0xff--共阳
  193. #define        LED_TYP2        0xFF
  194. #endif
  195. /*************************************************************************************************************/
  196. #define                  b_0000_0001             1
  197. #define                  b_0000_0010                     2        
  198. #define                  b_0000_0100                     4        
  199. #define                  b_0000_1000                     8        
  200. #define                  b_0001_0000                        16                
  201. #define                  b_0010_0000                 32
  202. #define                  b_0100_0000                        64        
  203. #define                  b_1000_0000                128  
  204. /*------------------------------------------------------------------------------------------------------------*/  
  205. #define _a               b_0000_0001
  206. #define _b                      b_0000_0010
  207. #define _c                      b_0000_0100   
  208. #define _d                      b_0000_1000   
  209. #define _e                      b_0001_0000   
  210. #define _f                      b_0010_0000   
  211. #define _g                      b_0100_0000   
  212. #define _p                      b_1000_0000   
  213. /**************************************************************************************************************/       
  214. #define LED_0                 LED_TYPE^(_a|_b|_c|_d| _e|_f)
  215. #define LED_1                 LED_TYPE^(_b|_c)
  216. #define LED_2                 LED_TYPE^(_a|_b|_g|_e|_d)
  217. #define LED_3                 LED_TYPE^(_a|_b|_g|_c|_d)
  218. #define LED_4            LED_TYPE^(_f|_g|_b|_c)
  219. #define LED_5            LED_TYPE^(_a|_f|_g|_c|_d)
  220. #define LED_6            LED_TYPE^(_a|_f|_g|_c|_d|_e)
  221. #define LED_7            LED_TYPE^(_a|_b|_c)
  222. #define LED_8            LED_TYPE^(_a|_b|_c|_d|_e|_f|_g)
  223. #define LED_9            LED_TYPE^(_a|_b|_c|_d|_f|_g)
  224. #define LED_a            LED_TYPE^(_a|_b|_c|_e|_f|_g)
  225. #define LED_H            LED_TYPE^(_b|_c|_e|_f|_g)
  226. #define LED_V            LED_TYPE^(_b|_c|_d|_e|_f)
  227. #define LED_e            LED_TYPE^(_a|_d|_d|_e|_f|_g)
  228. #define LED_OF           LED_TYP2^(_a|_b|_c|_d|_e|_f|_g|_p)
  229. #define LED_Y            LED_TYPE^(_b|_c|_d|_f|_g)
  230. #define LED_U            LED_TYPE^(_c|_d|_e)
  231. #define LED_L            LED_TYPE^(_f|_e|_d)
  232. #define LED_P            LED_TYPE^(_a|_b|_e|_f|_g)
  233. #define LED_I            LED_TYPE^(_e|_f )
  234. #define LED_d            LED_TYPE^(_b|_c |_d|_e|_g)
  235. #define LED_r            LED_TYPE^(_e|_g)
  236. #define LED_T            LED_TYPE^(_a|_e|_f)
  237. #define LED_b            LED_TYPE^(_c|_d|_e|_f|_g)
  238. #define LED_c            LED_TYPE^(_a|_d|_e|_f)
  239. #define LED_K            LED_TYPE^(_b|_d|_e|_f|_g)
  240. #define LED_S            LED_TYPE^(_a|_c|_d|_f|_g)
  241. #define LED_O_1                 LED_TYPE^(_a|_b|_f|_g)                                //上层'o'
  242. #define LED_O_2          LED_TYPE^(_c|_d|_e|_g)                             //下层'o'      
  243. #define LED_Z                 LED_TYPE^(_a|_b|_e|_d)  
  244. #define LED_f                 LED_TYPE^(_a|_e|_f|_g)   
  245. #define LED_n            LED_TYPE^(_c|_e|_g)
  246. #define LED_fu           LED_TYPE^(_g)
  247. #define LED_DROP         LED_TYPE^(_p)
  248. /*------------------数码管段码表----------------------------------------*/
  249. unsigned char code table[18]=         {                 //需要显示的段选码
  250.                                       LED_0,         //0
  251.                                   LED_1,         //1
  252.                                                                   LED_2,         //2
  253.                                                                   LED_3,         //3
  254.                                                                   LED_4,         //4
  255.                                                                   LED_5,         //5
  256.                                                                   LED_6,         //6
  257.                                                                   LED_7,         //7
  258.                                                                   LED_8,         //8
  259.                                                                   LED_9,         //9
  260.                                                                   LED_a,
  261.                                                                   LED_b,
  262.                                                                   LED_c,
  263.                                                                   LED_d,
  264.                                                                   LED_e,
  265.                                                                   LED_f,
  266.                                                                   LED_fu,
  267.                                                                   LED_P,
  268.                                                                  };
  269. /********************************************************************************************************
  270. **         函数名称:                        void        digital_CODE()
  271. **        功能描述:                        驱动数码管位码
  272. **        创 建 者:                        李文杰
  273. **        创建时间:                        2017-11-28 3:48
  274. **        版    本:                        v1.0.0
  275. *********************************************************************************************************/
  276. void digital_CODE(unsigned char ch)  //led段码发送函数开始  
  277. {          ACC=ch;
  278.         COM1=COM2=COM3=1;
  279.     Led_Bit_A  = ACC0;
  280.         Led_Bit_B  = ACC1;
  281.         Led_Bit_C  = ACC2;
  282.         Led_Bit_D  = ACC3;
  283.         Led_Bit_E  = ACC4;
  284.         Led_Bit_F  = ACC5;
  285.         Led_Bit_G  = ACC6;
  286.     Led_Bit_dip= ACC7;
  287. }
  288. /********************************************************************************************************
  289. **         函数名称:                        void        uartsends()
  290. **        功能描述:                        串口发送数据串
  291. **        创 建 者:                        李文杰
  292. **        创建时间:                        2017-11-28 3:48
  293. **        版    本:                        v1.0.0
  294. *********************************************************************************************************/
  295. void uartsends(unsigned char buff[],uchar len)
  296. {   unsigned char i;
  297.         for(i=0;i<len;i++)
  298.         {   SBUF=buff[i];
  299.                 while(!TI);
  300.                 TI=0;
  301.         }
  302. }
  303. /*************把组态王中的ASSIC码转换成16进制两个ASSIC组成1BYTE16进制码与常规的ASSIC转法不一样*********/
  304. unsigned char CharToHex(unsigned char bHex)  
  305. {   unsigned char temp;
  306.         if(   bHex>0x40)
  307.         temp=(bHex-0x37)&0x0f;        //只取低四位00001111----bit0-bit1--bit2--bit3
  308.         else
  309.         temp=(bHex-0x30)&0x0f;        //只取低四位00001111----bit0-bit1--bit2--bit3
  310.         return temp;   
  311. }
  312. unsigned int CharToHexn(unsigned char bHex)  
  313. {   unsigned char temp;
  314.         if(   bHex>0x40)
  315.         temp=(bHex-0x37)&0x0f;        //只取低四位00001111----bit0-bit1--bit2--bit3
  316.         else
  317.         temp=(bHex-0x30)&0x0f;        //只取低四位00001111----bit0-bit1--bit2--bit3
  318.         return temp;   
  319. }



  320. unsigned int CharToHexnall(unsigned char *redata,unsigned char number)  
  321. {   unsigned int temp,i;
  322.         if(number==1)        {
  323.         for(i=0;i<2;i++)  {
  324.         temp=CharToHexn(*redata);
  325.         temp=temp<<4|temp;
  326.         redata++;
  327.           }
  328. //        temp=(temp<<4+temp1);

  329.        
  330.         }       

  331.         if(number==2)        {
  332.         if(   temp>0x40)
  333.         temp=(temp-0x37)&0x0f;        //只取低四位00001111----bit0-bit1--bit2--bit3
  334.         else
  335.         temp=(temp-0x30)&0x0f;}        //只取低四位00001111----bit0-bit1--bit2--bit3

  336.         if(number==4)        {
  337.         if(   temp>0x40)
  338.         temp=(temp-0x37)&0x0f;        //只取低四位00001111----bit0-bit1--bit2--bit3
  339.         else
  340.         temp=(temp-0x30)&0x0f;}        //只取低四位00001111----bit0-bit1--bit2--bit3


  341.         return temp;   
  342. }



  343. /********************************************************************************************************
  344. **         函数名称:                        data_num(void)
  345. **        功能描述:                        判断发送和写的字节数
  346. **        创 建 者:                        李文杰
  347. **        创建时间:                        2017-11-28 3:48
  348. **        版    本:                        v1.0.0
  349. *********************************************************************************************************/
  350. unsigned char data_num(void)                //data_num=1byte;data_num=2word;data_num=4folat
  351. {                                                                       
  352.     unsigned char temp;
  353.         temp=CharToHex(recbuf[9]);
  354.         temp=(temp<<4)&0XF0;
  355.         temp+=CharToHex(recbuf[10]);
  356.         return temp;
  357. }
  358. /****************根据接收到的信息处理回传的信息**************************/
  359. void Information_processing(void)
  360. {
  361. unsigned char ctmp1=0,ctmp2=0,xordat=0,i;
  362. unsigned int send_temp=0;
  363. sendbuf[1]=recbuf[1];         //地址同步
  364. sendbuf[2]=recbuf[2];
  365. sendbuf[3]=recbuf[9];         //字节数同步
  366. sendbuf[4]=recbuf[10];
  367. /********读1字节数************************************/
  368. if(data_num()==1) {
  369.   datBYTE[0]=Control_MCUIO;                //组态王读单片机时只要把P0,P1,P2的数据放到datBYTE[0]中就可以读出MCUIO的状态
  370.   ctmp1=(datBYTE[0]>>4)&0x0f;
  371.   if(ctmp1>9)                                    //把十六进制码转化成ASSIC码放入sendbuf[5]sendbuf[6]中以便发送
  372.   sendbuf[5]=ctmp1%9+0x40;
  373.   else
  374.   sendbuf[5]=ctmp1+0x30;  
  375.   ctmp2=datBYTE[0]&0x0f;             //把十六进制码转化成ASSIC码放入sendbuf[5]sendbuf[6]中以便发送
  376.   if(ctmp2>9)                                 
  377.   sendbuf[6]=ctmp2%9+0x40;       
  378.   else
  379.   sendbuf[6]=ctmp2+0x30;   
  380.   xordat=0;
  381.   for(i=1;i<7;i++)
  382.   xordat^=sendbuf[i];           //异或之和
  383.   send_temp=xordat;
  384.   ctmp1=(send_temp>>4)&0x0f;
  385.   if(ctmp1>9)                                //异或高位
  386.   sendbuf[7]=ctmp1%9+0x40;
  387.   else
  388.   sendbuf[7]=ctmp1+0x30;         
  389.   ctmp2=send_temp&0x0f;
  390.   if(ctmp2>9)                                //异或低位
  391.   sendbuf[8]=ctmp2%9+0x40;       
  392.   else
  393.   sendbuf[8]=ctmp2+0x30;
  394.   sendbuf[9]=0X0D;       
  395.   SendNum=10;                                //字节读回传10个数据
  396.   uartsends(sendbuf,SendNum);
  397.                                    }
  398. /********读2字节数************************************/
  399. //40 30 31 41 34 30 30 30 30 30 32 37 36 0D
  400. //40 30 31 30 32 30 30 36 34 30 33 0D
  401. if(data_num()==2) {
  402. sendbuf[5]=0X30;         //00
  403. sendbuf[6]=0X30;
  404. sendbuf[7]=0X36;         //120
  405. sendbuf[8]=0X34;
  406. xordat=0;
  407. for(i=1;i<9;i++)                                   //异或之和8个数据
  408. xordat^=sendbuf[i];
  409. send_temp=xordat;
  410. ctmp1=(send_temp>>4)&0x0f;
  411. if(ctmp1>9)                                                //异或高位
  412. sendbuf[9]=ctmp1%9+0x40;
  413. else sendbuf[9]=ctmp1+0x30;
  414. ctmp2=send_temp&0x0f;
  415. if(ctmp2>9)                                                //异或低位
  416. sendbuf[10]=ctmp2%9+0x40;
  417. else sendbuf[10]=ctmp2+0x30;
  418. sendbuf[11]=0x0D;
  419. uartsends(sendbuf,12);                        //字节读回传12个数据
  420.                                    }                 
  421. /********读4字节数************************************/

  422. if(data_num()==4) {
  423. sendbuf[5] =0X30;         //字节数同步
  424. sendbuf[6] =0X30;
  425. sendbuf[7] =0X46;         //字节数同步
  426. sendbuf[8] =0X46;
  427. sendbuf[9] =0X46;         //字节数同步
  428. sendbuf[10]=0X46;
  429. sendbuf[11]=0X30;         //字节数同步
  430. sendbuf[12]=0X30;
  431. xordat=0;
  432. for(i=1;i<13;i++)                         //异或之和12个数据
  433. xordat^=sendbuf[i];
  434. send_temp=xordat;
  435. ctmp1=(send_temp>>4)&0x0f;
  436. if(ctmp1>9)
  437. sendbuf[13]=ctmp1%9+0x40;
  438. else
  439. sendbuf[13]=ctmp1+0x30;         //异或高位
  440. ctmp2=send_temp&0x0f;
  441. if(ctmp2>9)
  442. sendbuf[14]=ctmp2%9+0x40;        //异或低位
  443. else
  444. sendbuf[14]=ctmp2+0x30;        //异或低位
  445. sendbuf[15]=0X0D;
  446. SendNum=16;                                //字节读回传16个数据
  447. uartsends(sendbuf,SendNum);
  448.                                    }

  449. }

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

  455. void writeMCU()
  456. {   unsigned char temp;                  //组态王写入MCU的数据值
  457.     unsigned int  tempAddr;          //组态王写入MCU的地址值X0,X1--X200
  458.         temp=CharToHex(recbuf[11]);
  459.         temp=(temp<<4)&0XF0;
  460.         temp+=CharToHex(recbuf[12]);
  461.         datBYTE[0]=temp;                          //写入单片机的内存
  462.         Control_MCUIO=datBYTE[0];                  //单片机的IO等于组态王写过来的数据组态王写入MCU的数据值
  463.         tempAddr=CharToHex(recbuf[5]);
  464.         tempAddr=(tempAddr<<4)&0XF0;
  465.         tempAddr+=CharToHex(recbuf[6]);
  466.         tempAddr=(tempAddr<<4)&0XF0;
  467.         tempAddr+=CharToHex(recbuf[7]);
  468.     tempAddr=(tempAddr<<4)&0XF0;
  469.         tempAddr+=CharToHex(recbuf[8]);

  470. //        Pv1=tempAddr;          //写入单片机的地址变量



  471. }
  472. /********************************************************************************************************
  473. **         函数名称:                        write_inform(unsigned char dat)
  474. **        功能描述:                        单片机向计算机组态王发送8字节数据
  475. **        创 建 者:                        李文杰
  476. **        创建时间:                        2017-11-28 3:48
  477. **        版    本:                        v1.0.0
  478. *********************************************************************************************************/
  479. void write_inform(unsigned char dat)
  480. {
  481. unsigned char xordat,i,ctmp1,ctmp2,send_temp;
  482. Answer[1]=recbuf[1];
  483. Answer[2]=recbuf[2];
  484. Answer[3]=dat;             //数据高位若正确回复23不正确回复2a
  485. Answer[4]=dat;             //数据低位若正确回复23不正确回复2a
  486. xordat=0;
  487. for(i=1;i<5;i++)
  488. xordat^=Answer[i];
  489. send_temp=xordat;
  490. ctmp1=(send_temp>>4)&0x0f;
  491. if(ctmp1>9)
  492. Answer[5]=ctmp1%9+0x40;
  493. else
  494. Answer[5]=ctmp1+0x30;         //异或高位
  495. ctmp2=send_temp&0x0f;
  496. if(ctmp2>9)
  497. Answer[6]=ctmp2%9+0x40;        //异或低位
  498. else
  499. Answer[6]=ctmp2+0x30;        //异或低位
  500. uartsends(Answer,8);
  501. }
  502. /********************************************************************************************************
  503. **         函数名称:                        AddrInit()
  504. **        功能描述:                        地址数据初始化
  505. **        创 建 者:                        李文杰
  506. **        创建时间:                        2017-11-28 3:48
  507. **        版    本:                        v1.0.0
  508. *********************************************************************************************************/
  509. /*void AddrInit(void)
  510. {
  511. unsigned char ctmp;
  512. ctmp=(MyAddr>>4);
  513. if(ctmp>9)
  514. {
  515. sendbuf [1]=0x40+ctmp%9;
  516. sendbuf1[1]=0x40+ctmp%9;
  517. }
  518. else
  519. {
  520. sendbuf [1]=ctmp+0x30;
  521. sendbuf1[1]=ctmp+0x30;
  522. }
  523. ctmp=MyAddr&0x0f;
  524. if(ctmp>9)
  525. {
  526. sendbuf [2]=0x40+ctmp%9;
  527. sendbuf1[2]=0x40+ctmp%9;
  528. }
  529. else
  530. {
  531. sendbuf [2]=ctmp+0x30;
  532. sendbuf1[2]=ctmp+0x30;
  533. }
  534. }

  535. /********************************************************************************************************
  536. **         函数名称:                        void Write_byte()
  537. **        功能描述:                        转换组态王发送的字节到dat区
  538. **        创 建 者:                        李文杰
  539. **        创建时间:                        2017-11-28 3:48
  540. **        版    本:                        v1.0.0
  541. *********************************************************************************************************/
  542. void Sendkingviow()
  543. {                    switch(ReceiveLen)
  544.                                            {
  545.                                                    /*组态王读数据单片机回传*/
  546.                                  case 14:   
  547.                                                                                   Information_processing();                                                                     
  548.                                                                     ;break;
  549.                                                    /*组态王写字节数据单片机回传40        30        31        23        23        30        31        0d不正确回传40        30        31        2A        2A        30        31        0d*/
  550.                                             case 16:   
  551.                                                                     write_inform('#');
  552.                                                                                 writeMCU();
  553.                                                                    ;break;
  554.                                                         /*组态王写双字节数据单片机回传*/
  555.                                                         case 18:   
  556.                                                                     write_inform('#');
  557.                                                                    ;break;
  558.                                                         /*组态王写四字节数据单片机回传*/
  559.                                                         case 22:   
  560.                                                                     write_inform('#');
  561.                                                                    ;break;
  562.                                                         default://write_inform('*');
  563.                                                                     write_inform('*');
  564.                                                                             break;       
  565.                                            }
  566. }
  567. /*float C4toD(char * c)
  568. {
  569.         BYTE     Hd[30], Jiema[30];
  570.         float   DTc[30];
  571.         float  Decimal = 0;
  572.         float   returnflo = 0;
  573.         BOOL     ShuFU = FALSE, JieFU = FALSE;
  574.         memset(Hd, 0, sizeof(Hd));
  575.         memset(Jiema, 0, sizeof(Jiema));
  576.         memset(DTc, 0, sizeof(DTc));
  577.         if((c[7] > 0x40) && (c[7] < 0x47))
  578.                 Hd[7] = ((c[7]  - 0x37) & 0x0f);
  579.         else if((c[7] > 0x60) && (c[7] < 0x67))
  580.                 Hd[7] = ((c[7]  - 0x57) & 0x0f);
  581.         else
  582.                 Hd[7] = ((c[7]  - 0x30) & 0x0f);

  583.         if((c[6] > 0x40) && (c[6] < 0x47))
  584.                 Hd[6] = ((c[6]  - 0x37) & 0x0f);
  585.         else if((c[6] > 0x60) && (c[6] < 0x67))
  586.                 Hd[6] = ((c[6]  - 0x57) & 0x0f);
  587.         else
  588.                 Hd[6] = ((c[6]  - 0x30) & 0x0f);

  589.         DTc[2] = (float)(((float)(Hd[6] * 16.0) + (float)(Hd[7])) / 256.0);

  590.         if((c[5] > 0x40) && (c[5] < 0x47))
  591.                 Hd[5] = ((c[5]  - 0x37) & 0x0f);
  592.         else if((c[5] > 0x60) && (c[5] < 0x67))
  593.                 Hd[5] = ((c[5]  - 0x57) & 0x0f);
  594.         else
  595.                 Hd[5] = ((c[5]  - 0x30) & 0x0f);

  596.         if((c[4] > 0x40) && (c[4] < 0x47))
  597.                 Hd[4] = ((c[4]  - 0x37) & 0x0f);
  598.         else if((c[4] > 0x60) && (c[4] < 0x67))
  599.                 Hd[4] = ((c[4]  - 0x57) & 0x0f);
  600.         else
  601.                 Hd[4] = ((c[4]  - 0x30) & 0x0f);

  602.         DTc[1] = (float)((((float)(Hd[4] * 16.0) + (float)Hd[5]) + DTc[2]) / 256.0);

  603.         if((c[3] > 0x40) && (c[3] < 0x47))
  604.                 Hd[3] = ((c[3]  - 0x37) & 0x0f);
  605.         else if((c[3] > 0x60) && (c[3] < 0x67))
  606.                 Hd[3] = ((c[3]  - 0x57) & 0x0f);
  607.         else
  608.                 Hd[3] = ((c[3]  - 0x30) & 0x0f);

  609.         if((c[2] > 0x40) && (c[2] < 0x47))
  610.                 Hd[2] = ((c[2]  - 0x37) & 0x0f);
  611.         else if((c[2] > 0x60) && (c[2] < 0x67))
  612.                 Hd[2] = ((c[2]  - 0x57) & 0x0f);
  613.         else
  614.                 Hd[2] = ((c[2]  - 0x30) & 0x0f);

  615.         Decimal = (float)(((float)(Hd[2] * 16) + (float)(Hd[3]) + DTc[1])/ 256.0);

  616.         if((c[1] > 0x40) && (c[1] < 0x47))
  617.                 Jiema[1] = ((c[1]  - 0x37) & 0x0f);
  618.         else if((c[1] > 0x60) && (c[1] < 0x67))
  619.                 Jiema[1] = ((c[1]  - 0x57) & 0x0f);       
  620.         else
  621.                 Jiema[1] = ((c[1]  - 0x30) & 0x0f);

  622.         if((c[0] > 0x40) && (c[0] < 0x47))
  623.                 Jiema[0] = ((c[0]  - 0x37) & 0x0f);
  624.         else if((c[0] > 0x60) && (c[0] < 0x67))
  625.                 Jiema[0] = ((c[0]  - 0x57) & 0x0f);
  626.         else
  627.                 Jiema[0] = ((c[0]  - 0x30) & 0x0f);


  628.         ShuFU = ((Jiema[0] & 0x08) >> 3) > 0;
  629.         JieFU = ((Jiema[0] & 0x04) >> 2) > 0;

  630.         Jiema[2] = (Jiema[0] & 0x03) * 16 + Jiema[1];
  631.        
  632.         if(JieFU)
  633.                 returnflo = (float)pow(2, (-1) * Jiema[2]) * Decimal;
  634.         else
  635.                 returnflo = (float)pow(2, Jiema[2]) * Decimal;

  636.         if(ShuFU)
  637.                 returnflo = (-1) * returnflo;

  638.         return returnflo;
  639. }  *******************************************/
  640. /********************************************************************************************************
  641. **         函数名称:                        serial_init()
  642. **        功能描述:                        串口1初始化函数
  643. **        创 建 者:                        李文杰
  644. **        创建时间:                        2017-11-28 3:48
  645. **        版    本:                        v1.0.0
  646. *********************************************************************************************************/
  647. void serial_init()
  648. {
  649. /*****************AT89C52单片机定时器1做波特率发生器***************************/
  650. /*
  651.     SCON=0x50;
  652.     TMOD=0X20;
  653.     TH1=0xfd;
  654.     TL1=0xfd;
  655.     TR1=1;           */
  656. /*****************STC15F2K60S2定时器1做波特率发生器***************************/
  657. /*        PCON &= 0x7F;                //波特率不倍速
  658.         SCON = 0x50;                //8位数据,可变波特率
  659.         AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
  660.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  661.         TMOD &= 0x0F;                //清除定时器1模式位
  662.         TMOD |= 0x21;                //设定定时器1为8位自动重装方式
  663. #if (CH1==   9600)
  664.         TL1 = 0xdc;                //设定定时初值
  665.         TH1 = 0xdc;                //设定定时器重装值 0xdc
  666. #elif (CH1==   19200)
  667.         TL1 = 0xEE;                //设定定时初值
  668.         TH1 = 0xEE;                //设定定时器重装值
  669. #endif
  670.         ET1 = 0;                //禁止定时器1中断
  671.         TR1 = 1;                //启动定时器1
  672. /*****************STC15F2K60S2定时器2做波特率发生器**************************/
  673.     T2L = (65536 - (MAIN_Fosc/4/BAUD));   //设置波特率重装值
  674.     T2H = (65536 - (MAIN_Fosc/4/BAUD))>>8;
  675.     AUXR = 0x14;                //T2为1T模式, 并启动定时器2
  676.     AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器         
  677. #if (PARITYBIT   == NONE_PARITY)
  678.     SCON = 0X50;                //8位可变波特率
  679. #elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
  680.     SCON = 0XDA;                //9位可变波特率,校验位初始为1
  681. #elif (PARITYBIT == SPACE_PARITY)
  682.     SCON = 0XD2;                //9位可变波特率,校验位初始为0
  683. #endif         
  684.     ES = 1;                     //使能串口1中断
  685.     EA = 1;                                                //使能总中断

  686. }
  687. /********************************************************************************************************
  688. **         函数名称:                        void        main()
  689. **        功能描述:                        主函数
  690. **        创 建 者:                        李文杰
  691. **        创建时间:                        2017-11-28 3:48
  692. **        版    本:                        v1.0.0
  693. *********************************************************************************************************/
  694. void main (void)//主函数
  695. { TH0=T1MS>>8;                                                  //1MS
  696.   TL0=T1MS;
  697.   ET0=1;
  698.   TR0=1;
  699. ……………………

  700. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
组态王单片机通讯1.0.rar (2.47 MB, 下载次数: 156)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏6 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:243220 发表于 2018-11-7 10:22 来自手机 | 只看该作者
楼主,试过你的,stc89c52
回复

使用道具 举报

板凳
ID:149389 发表于 2019-9-9 20:52 来自手机 | 只看该作者
很好的参考资料
回复

使用道具 举报

地板
ID:95120 发表于 2020-1-31 11:00 | 只看该作者
请问组态王怎样向单片机发送读取指令呢?不用系统自动发送的。例如我想通过一个按钮实现向单片机发送读取X6的指令?
回复

使用道具 举报

5#
ID:283207 发表于 2020-2-1 16:24 | 只看该作者
谢楼主分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表