搜索
bottom↓
回复: 3

开源PLC学习笔记17(开源PLC与组态软件通讯MODBUS)——2013_12_11

[复制链接]

出0入0汤圆

发表于 2013-12-11 14:34:38 | 显示全部楼层 |阅读模式
从freemodbus的阴影中逃了出来,现在需要把modbus加入到开源PLC中了。

首先,利用笔记13中的方法,逐步添加。但是因为STC12系列无法通过PROTEUS仿真,不过找到了内部含有EEPROM并且可以PROTEUS仿真的51,
《单片机C语言程序设计实训100例——基于8051+Proteus仿真(第2版)》25 单片机内置EEPROM读写测试仿真

这样就可以仿真了,然后把笔记15中的代码加入,过程比想象地要简单很多。



输入的命令是03040415
复习一下,
03040415 会被分解成 0403 和 1504
0403:第一个0是散转函数的下标,表示LD命令,403表示X3,是第4个开关;
1504:第一个1是散转函数的下标,表示OUT命令,504表示Y3,是第5个LED;
即 LD X3
    OUT Y4

然后,先利用组态王
设置按照http://www.chinabaike.com/z/gyzd/877961.html




这样组态王的开关就可以控制X3,从而间接控制Y4。

sbit LED0 = P0^0; // 对应线圈0
sbit LED1 = P0^1; // 对应线圈1
sbit LED2 = P0^2; // 对应线圈2
sbit LED3 = P0^3; // 对应线圈3
sbit LED4 = P0^4; // 对应线圈4
sbit LED5 = P0^5; // 对应线圈5
sbit LED6 = P0^6; // 对应线圈6
sbit LED7 = P0^7; // 对应线圈7

sbit KEY0 = P1^0;
sbit KEY1 = P1^1;
sbit KEY2 = P1^2;
sbit KEY3 = P1^3;
sbit KEY4 = P1^4;
sbit KEY5 = P1^5;
sbit KEY6 = P1^6;
sbit KEY7 = P1^7;

并且在设置线圈函数中,主要对KEY进行操作
//设定线圈状态 返回0表示成功
INT16U setCoilVal(INT16U addr, INT16U tempData)
{
        INT16U result = 0;
        INT16U tempAddr;

        tempAddr = addr & 0xfff;

        switch(tempAddr)                // & 0xff
        {
                case 0:
                                if (tempData)
                                        KEY0 = 1;
                                else
                                        KEY0 = 0;
                                break;
                case 1:
                                if (tempData)
                                        KEY1 = 1;
                                else
                                        KEY1 = 0;
                                break;
                case 2:
                                if (tempData)
                                        KEY2 = 1;
                                else
                                        KEY2 = 0;
                                break;
                case 3:
                                if (tempData)
                                        KEY3 = 1;
                                else
                                        KEY3 = 0;
                                break;
                case 4:
                                if (tempData)
                                        KEY4 = 1;
                                else
                                        KEY4 = 0;
                                break;
                case 5:
                                if (tempData)
                                        KEY5 = 1;
                                else
                                        KEY5 = 0;
                                break;
                case 6:
                                if (tempData)
                                        KEY6 = 1;
                                else
                                        KEY6 = 0;
                                break;
                case 7:
                                if (tempData)
                                        KEY7 = 1;
                                else
                                        KEY7 = 0;
                                break;
                case 10:
                                break;
                case 11:
                                break;
                case 12:
                                break;
                case 13:
                                break;
                case 14:
                                break;
                case 15:
                                break;
                case 16:
                                break;
                case 17:
                                break;

                default:
                                break;
        }

        return result;
}


进行仿真,


从中可以看出,组态王设置线圈状态是没有问题的,但是查询线圈状态,组态王发出的命令总是01 01 01 00 。。。。不是LED所对应的地址,目前还不知道如何解决。

另外,为了简洁和集中重点,命令输入通讯还没加入。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2013-12-11 20:19:14 | 显示全部楼层


添加通讯,只添加写命令
void FX1NProcessing(void)
{

        unsigned char i;
        unsigned char WriteLen=0;
         unsigned int  WriteAddr=0;

        if(UDRFlag)                                // 有数据来
        {
                UDRFlag=0;
                if(Buffer[0]==ENQ)        // 发送请求                                        ==== 1. 3. 5. 7. 10. 12. 14.(14开始下发数据)
                {
                        UartSendByte(ACK);
                }
                else if(STXETX)        // 可识别的                          
                {
                        if(E11)
                        {
                                //        计算得到写入字节数:
                                for(i=8;i<10;i++)Buffer=ascto0F(Buffer);
                                Buffer[8]<<=4;
                                WriteLen=(Buffer[8]+Buffer[9]);
                                //        计算得到写入地址:
                                for(i=4;i<8;i++)Buffer=ascto0F(Buffer);
                                WriteAddr =Buffer[4]<<12;
                                WriteAddr+=Buffer[5]<<8;
                                WriteAddr+=Buffer[6]<<4;
                                WriteAddr+=Buffer[7];
//                                        if(WriteAddr==0x8000)ErasurePLC(ErasureCODE);        //        擦除PLC程序区
                                WriteFlash(WriteAddr,(unsigned char *)(Buffer+10),(unsigned char)WriteLen);        //        写 flash
                                step=WriteLen;
                                UartSendByte(ACK);
                                }                        
                        
                }
                UartReceiveCounter=0;
                 REN=1;
        }
}
省去了和检验,
因为采用串口助手,写入命令02 45 31 31 30 30 30 30 30 34 30 32 30 34 30 32 31 35 03 33 33,最后两个随意
表示STX E 1 1 0 0 0 0 0 4 0 2 0 4 0 2 1 5 ETX 3 3
即在0000地址写入 LD X2
                           OUT Y2


主函数也更改为
#include "system.h"
unsigned char command[]={'0','3','0','4','0','4','1','5'};

void main(void)
{
          SYSTEM_DISABLE_INTERRUPT();
        UartInit();
         TimerInit();
        SYSTEM_ENABLE_INTERRUPT();

        WriteFlash(IAP_ADDRESS,(unsigned char*)(command),4);
        step=4;
     while (1)
    {  
              FX1NProcessing();
         //更新IO端口,必须
                RefreshIO();              
     //PLC执行去找二当家的,当老大就是好
                main_PLC();                                                
                timerProc();                        
                checkComm0Modbus();//检测modbus帧
         }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-5-22 09:44:09 | 显示全部楼层
mark下!【开源PLC与组态软件通讯MODBUS)】

出0入0汤圆

发表于 2014-5-22 10:10:01 | 显示全部楼层
不是很明白组态,,,收藏先
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-2 22:45

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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