威纶通官方论坛

求助 连接 Arduino 与威伦通触摸屏

[复制链接]
发表于 2015-6-9 18:02:44 | 显示全部楼层 |阅读模式
本帖最后由 leexianfeng 于 2015-6-10 20:57 编辑

// serialTestv2.ino
// 与HMI连接时要使用Modbus Ascii模式,如果是Rtu模式不能处理那种字符串,应该是程序使用的是char字符的缘故吧
#define LED 13

#define PD0 2
#define PD1 3
#define PD2 4
#define PD3 5
#define PD4 6
#define PD5 7
#define PD6 8
#define PD7 9
#define PA0 A0
#define PA1 A1
#define PA2 A2
#define PA3 A3
#define PA4 A4
#define PA5 A5

#define uchar unsigned char                           //8位
#define ulint unsigned long                           //32位
#define uint unsigned int                           //16位

char a[30];
char b[30];
uchar Send_Data[30];                           //发送数据数组
uchar count=0,time=0;                                   //count为收到数据的次数,time应用于发送03代码时,中间的字数量是多少个数值
//uchar Receive_Data[30];                   //接收数据数组
int Receive_Data[30];
uint begin_address=0,address_leg=0;   //数值字开始位,数值字长度
uint disp[8]={0,0,0,0,0,0,0,0}; //字接收显示数组,用于存储6x1-6x8的十六位接收数据

/*********************tft显示屏 define************************/
#include <UTFT.h>
extern uint8_t SevenSegNumFont[];
extern uint8_t SmallFont[];
extern uint8_t BigFont[];

UTFT myGLCD(CTE32HR,38,39,40,41);

/*********************tft显示屏 define end************************/

void setup()
{
        pinMode(LED,OUTPUT);//设置数字端口13为输出
    pinMode(PD0,OUTPUT);//设置数字端口2为输出
    pinMode(PD1,OUTPUT);//设置数字端口3为输出
    pinMode(PD2,OUTPUT);//设置数字端口4为输出
    pinMode(PD3,OUTPUT);//设置数字端口5为输出
    pinMode(PD4,OUTPUT);//设置数字端口6为输出
    pinMode(PD5,OUTPUT);//设置数字端口7为输出
    pinMode(PD6,OUTPUT);//设置数字端口8为输出
    pinMode(PD7,OUTPUT);//设置数字端口9为输出

        Serial.begin(9600);           //设置串口波特率
        delay(1000);
/*********************tft显示屏 initial************************/
        myGLCD.InitLCD(); //PORTRAIT 数值模式,LANDSCAPE 水平模式
        myGLCD.clrScr();
        myGLCD.setFont(BigFont);
        myGLCD.print("Welcome XFgzs", CENTER, 25);
/*********************tft显示屏 initial end************************/
}

void loop()
{
        int bufferBytes = Serial.available();
        itostr(a,bufferBytes);
        String data="";       
        String Senddata="";
        String dataA;
        String dataB;
    String data2="";
//初始化数组Receive_Data[30]
    for(int i=0; i<30; i++){
            Receive_Data[30]=0;
    }       

        if(Serial.available()>0 & Serial.available()<120)  { // //每次从weinview HMI中获得的字符数位34
                //Serial.println(bufferBytes); //输出输入数据长度 指令格式5A 01 01 01 22,后两位位换行回车符
                myGLCD.clrScr();
                //Serial.print("input data=");
                myGLCD.setFont(BigFont);
                for(int i=0;i<bufferBytes;i++){  //将指令按照字节单位循环读取并赋值给字符数组Receive_Data
                       
                        Receive_Data = Serial.read();
                        //Serial.print(Receive_Data); //测试用 将从机接收到的字符数组打印到显示屏上
                        data+=Receive_Data;
                        data+=' ';
                        delay(2);

                }
 楼主| 发表于 2015-6-10 20:58:04 | 显示全部楼层
/*********************执行通讯协议解析************************/        
        command();
/*********************执行通讯协议解析 end************************/   

/*********************tft显示屏 显示************************/
               
            myGLCD.setColor(0, 255, 0);
            myGLCD.setBackColor(0, 0, 0);
            myGLCD.setFont(SevenSegNumFont);
            myGLCD.print("0123456789", CENTER, 20,0); //Print函数参数,显示字符串,位置xy,角度
/*********************tft显示屏 换行显示 使用ASC编码每行显示5个字符************************/            
            if(bufferBytes>5){
                    //Serial.println(data);
                    dataA=data.substring(0,15);
                    //Serial.println(dataA);
                    dataB=data.substring(15,30);
                    //Serial.println(dataB);
                myGLCD.print(dataA, 0, 80);
                myGLCD.print(dataB, 0, 140);
            }
            else {
                    myGLCD.print(data, 0, 80,0);
            }
/*********************tft显示屏 换行显示 end************************/               
            
            
/*********************tft显示屏 换行显示 使用ASC编码每行显示10个字符************************/            
            myGLCD.setFont(BigFont);
        for(int i=0;i<7;i++){  //将指令按照字节单位循环读取并赋值给字符数组Receive_Data
                        Senddata+=Send_Data[i];
                        Senddata+=' ';
                        delay(2);

                }

            if(bufferBytes>12){
                    myGLCD.print(Senddata.substring(0,30), 0, 210);
                    myGLCD.print(Senddata.substring(30,60), 0, 230);
            }
            else {
                    myGLCD.print(Senddata, 0, 210);
            }
/*********************tft显示屏 换行显示  end************************/       
            myGLCD.print("TotalNum=", 0, 260);
            myGLCD.print(a, 150, 260);

            for(int j=0; j<2; j++){      //提取串口每个位得字
                data2+=Receive_Data[j];
                data2+=' ';
            }
            myGLCD.print(data2, 0, 280,0);
            
/*********************tft显示屏 显示 end************************/
    }

    while(Serial.read() >= 0) { //用空操作来清除缓存区中的所有数据  

    }
    delay(200);
}

char* itostr(char *str,int i)
{
        sprintf(str,"%d",i);//%x 显示成16进制 %d十进制  %o八进制
        return str;
}

void command(void)
{
//缺少对收到指令的校验,通过对指令的校验,可以识别出不符合指令格式的输入指令,减少bug
        uint crc_end,legg;
        switch (Receive_Data[1]) {
            case 0x01:
                //int echo1[7] = {0x01,0x01,0x02,0x00,0x00,0xB9,0xFC};
                // 位状态读取指令
                      Send_Data[0]=Receive_Data[0];                                          //站号
                        Send_Data[1]=Receive_Data[1];                                          //功能码
                        Send_Data[2]=0x02;                                                          //功能码0x02代表位状态显示元件
                        Send_Data[3]=check_Bitout(0);                                                  //低位状态,即LED开关情况
                        Send_Data[4]=check_Bitout(0);                                                  //高位状态
                        Send_Data[5]=0xB9;                                          //校验低位 模运算,求的是余数
                        Send_Data[6]=0xFC;                                          //校验高位 除运算,求的是商
                        send_word(Send_Data,7);
                       
              break;
            case 0x03:
                // 字状态读取指令
                                begin_address=Receive_Data[2]<<8|Receive_Data[3];
                                address_leg=Receive_Data[4]<<8 | Receive_Data[5];         //总寄存器长度
                                //hi_type=0;
                                Send_Data[0]=0x0C;//Receive_Data[0];                                        //站号
                                Send_Data[1]=0x01;//Receive_Data[1];                                        //功能码
                                legg=(uint)address_leg*2;                                        //字节数
                                Send_Data[2]=0x02;//address_leg*2;                                        //字节数
                                for(time=0;time<legg;time++)                                //发送相应字节
                                {
                                        if(!(time%2))                                                        //字高位为0
                                        Send_Data[time+3] =0x00;//disp[time/2+begin_address]/256;                //字高字节
                                        else
                                        Send_Data[time+3] =0x00;//disp[time/2+begin_address]%256;                //字低字节
                                }
                                //crc_end=crc16(Send_buf,legg+3);                                //校验
                                Send_Data[legg+3]=0x94;//crc_end%256;                                //校验低位
                                Send_Data[legg+4]=0x3D;//crc_end/256;                                //校验高位
                                send_word(Send_Data,legg+5);                                        //返回屏
              break;             
            case 0x05:
                    begin_address=Receive_Data[3];
                        if(Receive_Data[4]==0xff){                                          //当为强制打开时,可以通过配置Receive_Data[2],增加到16个继电器位控制
                                switch(begin_address){                                         //对应的地址
                                        case 0x00: digitalWrite(PD0, HIGH); break;        //相应的LED点亮,记录下相应的P0位状态
                                        case 0x01: digitalWrite(PD1, HIGH); break;
                                        case 0x02: digitalWrite(PD2, HIGH); break;
                                        case 0x03: digitalWrite(PD3, HIGH); break;
                                        case 0x04: digitalWrite(PD4, HIGH); break;
                                        case 0x05: digitalWrite(PD5, HIGH); break;
                                        case 0x06: digitalWrite(PD6, HIGH); break;
                                        case 0x07: digitalWrite(PD7, HIGH); break;
                                }                                         
                        }
                        else                                                                                  //当强制为OFF时
                        {
                        //        flag_led=0;
                                switch(begin_address){
                                        case 0x00: digitalWrite(PD0, LOW); break;        //相应的LED熄灭,记录下相应的P0位状态
                                        case 0x01: digitalWrite(PD1, LOW); break;
                                        case 0x02: digitalWrite(PD2, LOW); break;
                                        case 0x03: digitalWrite(PD3, LOW); break;
                                        case 0x04: digitalWrite(PD4, LOW); break;
                                        case 0x05: digitalWrite(PD5, LOW); break;
                                        case 0x06: digitalWrite(PD6, LOW); break;
                                        case 0x07: digitalWrite(PD7, LOW); break;
                                }
                        }                                          
                        Send_Data[0]=Receive_Data[0];                                        //站号
                        Send_Data[1]=Receive_Data[1];                                        //功能码
                        Send_Data[2]=Receive_Data[2];                                        //起始高位
                        Send_Data[3]=Receive_Data[3];                                        //起始低位
                        Send_Data[4]=Receive_Data[4];                                        //返回状态
                        Send_Data[5]=Receive_Data[5];                                        //返回状态
                        //crc_end=crc16(Send_buf,6);                                        //校验
                        Send_Data[6]=Receive_Data[6];//crc_end%256;                                        //校验低位
                        Send_Data[7]=Receive_Data[7];//crc_end/256;                                        //校验高位
                        send_word(Send_Data,8);                                                 //发送返回屏
              break;
            case 0x06:
              // do something
          digitalWrite(PD0, LOW);
          digitalWrite(PD7, LOW);
              break;
            default:
              // do something
              Serial.print("no OUTPUT");
        }

}
//////////数码管显示函数,最多显示五位数,数值仅限于0-9,该函数根据实际情况选择使用////////////////
void Display(uint Num)           
{
        uint i;
        for (i=0;i<5; i++)
        {
                //P2 = 0;                       //清除显示,防止数字重影
                //P0 = DuanMa[Num%10];           //显示最低一位数
                delay(10);
                //P2 = 0x80>>i;                         //显示第一位数时点亮第一个数码管,第二位时点亮第二个数码管,以此类推。
                Num = Num/10;                         //将变量除以10处理将显示下一位数       
                   delay(1);
        }
}

/**************************数码管显示相关,DuanMa是显示0-9*****************************/
uchar DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9


/**********************检查位状态函数,并返回int数值类型***********************/
/*************************hl表示查询低位1或者高位2**默认返回0******************/

int check_Bitout(int hl)
{
        char hi_type,low_type;
    switch (hl) {
        case 1:
          // do something
                  low_type=digitalRead(PD0);
                low_type=low_type | digitalRead(PD1)<<1;
                low_type=low_type | digitalRead(PD2)<<2;
                low_type=low_type | digitalRead(PD3)<<3;
                low_type=low_type | digitalRead(PD4)<<4;
                low_type=low_type | digitalRead(PD5)<<5;
                low_type=low_type | digitalRead(PD6)<<6;
                low_type=low_type | digitalRead(PD7)<<7;
                return low_type;     
          break;
        case 2:
          // do something
                hi_type=digitalRead(PC0);
                hi_type=hi_type | digitalRead(PC1)<<1;
                hi_type=hi_type | digitalRead(PC2)<<2;
                hi_type=hi_type | digitalRead(PC3)<<3;
                hi_type=hi_type | digitalRead(PC4)<<4;
                hi_type=hi_type | digitalRead(PC5)<<5;
                hi_type=hi_type | digitalRead(PC6)<<6;
                hi_type=hi_type | digitalRead(PC7)<<7;
                return hi_type;
          break;
        default:
          // do something
          return 0;
    }
   
}
/**********************发送函数***********************/
/***********发送字符串或者一连串的字节数据************/
/****mydata表示要发送的字符串数组,num表示数组长度****/

void send_word(uchar *mydata,uchar num)
{                                                                                
        int i;
        for(i=0;i<num;i++)
        {
                Serial.write(*(mydata+i));
        }
        //count=0;
}
 楼主| 发表于 2015-6-10 21:09:40 | 显示全部楼层
现在可以通过arduino返回数值给HMI,上述将通讯里的crc验证取消了,通过HMI输入指令也是如此,因此只需要前几位正确就能操作位。

HMI        发    01  01  00  00  00  10  3D  C6  (位读取)
单片机接收后发回数据  01 01 02 00 00 B9 FC  无灯亮
                                01 01 02 01 00 B8 6C   1灯亮
                                01 01 02 02 00 B8 9C   2灯亮
                                01 01 02 04 00 BB 3C   3灯亮
                                 01 01 02 82 00 D9 5C  2、8灯亮
愿资料说是01  03  00  00  00  08  44  0C  (字读取)实测位01 03 00 00 00 06 C5 C8
单片机发回 0C 01 02 00 00 94 3D 跟代码不吻合,不知道是什么情况

HMI 位0x 1 发送给单片机位操作码05指令   01 05 00 00 FF 00 8C 3A  FF代表开,其他任意值代表关,因为没有校验位所以可以直接操作单片机,但是返回值不正确,所以再下一次循环,位得操作状态会复位,有待进一步研究
 楼主| 发表于 2015-6-10 21:10:01 | 显示全部楼层
现在可以通过arduino返回数值给HMI,上述将通讯里的crc验证取消了,通过HMI输入指令也是如此,因此只需要前几位正确就能操作位。

HMI        发    01  01  00  00  00  10  3D  C6  (位读取)
单片机接收后发回数据  01 01 02 00 00 B9 FC  无灯亮
                                01 01 02 01 00 B8 6C   1灯亮
                                01 01 02 02 00 B8 9C   2灯亮
                                01 01 02 04 00 BB 3C   3灯亮
                                 01 01 02 82 00 D9 5C  2、8灯亮
愿资料说是01  03  00  00  00  08  44  0C  (字读取)实测位01 03 00 00 00 06 C5 C8
单片机发回 0C 01 02 00 00 94 3D 跟代码不吻合,不知道是什么情况

HMI 位0x 1 发送给单片机位操作码05指令   01 05 00 00 FF 00 8C 3A  FF代表开,其他任意值代表关,因为没有校验位所以可以直接操作单片机,但是返回值不正确,所以再下一次循环,位得操作状态会复位,有待进一步研究
 楼主| 发表于 2015-6-11 09:41:09 | 显示全部楼层
现在已经解决crc校验码得问题,预知详情请到http://qxw1194290187.my3w.com/forums/2.aspx查看细节
发表于 2015-7-29 10:36:55 | 显示全部楼层
leexianfeng 发表于 2015-6-10 20:58
/*********************执行通讯协议解析************************/        
        command();
/****** ...

楼主,我使用了ITDB屏,可是写在  if   (comdata.length() >0)中的  myGLCD.print(humidity, 350, 130);语句根本不执行,也就是说在屏幕上不显示,我看到你的显示代码是写在串口接收里面的,不知道你的能显示吗?你用的IDE是哪个版本的,我猜想是不是因为我IDE的版本太低的原因。。。。
发表于 2015-9-15 17:37:39 | 显示全部楼层
有没有Ardunio 与威纶TK6070IH 的通讯实例呀?附件 哥们。
发表于 2015-9-16 16:13:03 | 显示全部楼层
leexianfeng 发表于 2015-6-10 20:58
/*********************执行通讯协议解析************************/        
        command();
/****** ...

有没#include <UTFT.h> 呀?能否提供这个文件呢?
发表于 2015-10-13 17:59:52 | 显示全部楼层
leexianfeng 发表于 2015-6-10 20:58
/*********************执行通讯协议解析************************/        
        command();
/****** ...

  hi_type = hi_type | digitalRead(PC7) << 7; 什么意思哦,我在编译的是提示如下:
Arduino:1.6.5 (Windows 7), 板:"Arduino Uno"

serialT.ino: In function 'char check_Bitout(int)':
serialT:298: error: 'PC7' was not declared in this scope
'PC7' was not declared in this scope

  报告将会包含更多的信息
  "在编译时,输出详细信息"
  在 文件>首选项 中启用
您需要登录后才可以发帖 登录 | 注册

本版积分规则

回复帖子

Archiver|小黑屋|威纶通官网 ( 粤ICP备06054553号 )

GMT+8, 2024-5-19 05:33

Powered by Discuz! X3.4

© 2001-2023 Comsenz Inc.

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