http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 16145|回复: 10

[其他] 串口通信遇到的问题。

[复制链接]
发表于 2013-4-12 19:10:58 | 显示全部楼层 |阅读模式
1金钱
飞哥,我在编程实现Modbus控制协议。使用RTU方式传输。
我编程到能发送相应的代码给智能电表,不过电表没有反应,我看了一下,发送的格式和数据没有错误。
之后,我用网上有个样例程序发送,发送的格式和数据用串口监听程序是和我之前那个一样的但是样例程序却能得到返回。
我怀疑是我的DATARECEIVED有问题,然后换成样例程序上的,但还是没有得到回复,飞哥,这到底是为什么啊?。求指教。



1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
 楼主| 发表于 2013-4-12 21:26:44 | 显示全部楼层
飞哥,怎么解决啊,在做毕设,卡了好久了。
回复

使用道具 举报

发表于 2013-4-12 21:53:16 | 显示全部楼层
发一下代码看看吧,我得看看代码才知道是什么情况
回复

使用道具 举报

 楼主| 发表于 2013-4-12 21:59:25 | 显示全部楼层
压缩文件。这样行么?

modbus.rar

54.07 KB, 下载次数: 261, 下载积分: 金钱 -1

回复

使用道具 举报

发表于 2013-4-12 22:07:59 | 显示全部楼层
[code=csharp]using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Windows.Forms;

namespace modbus
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


       #region  端口初始化及数据初始化处理
        public SerialPort mySerialPort = new SerialPort();
        private string btn_sender = "";
        private const int read_num = 99;
        private const int read_num2 = 60;
        private Boolean received = false;

        private void Form1_Load(object sender, EventArgs e)
        {
                string[] ports = SerialPort.GetPortNames();
                Array.Sort(ports);
                comboPortName.Items.AddRange(ports);
                comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;
                comboBaurate.SelectedIndex = comboBaurate.Items.IndexOf("9600");
                comboParity.SelectedIndex = comboParity.Items.IndexOf("None");
                comboDatabits.SelectedIndex = comboDatabits.Items.IndexOf("8");
                comboStopBit.SelectedIndex = comboStopBit.Items.IndexOf("2");
                Txtaddr.SelectedText = "1";
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            String myParity;
            String myStopBits;

            myParity =comboParity.SelectedItem.ToString();
            myStopBits =comboStopBit.SelectedItem.ToString();


            //设置校验位
            switch (myParity)
            {
                case "None":
                    mySerialPort.Parity = Parity.None;
                    break;
                case "Even":
                    mySerialPort.Parity = Parity.Even;
                    break;
                case "Odd":
                    mySerialPort.Parity = Parity.Odd;
                    break;
                default:
                    mySerialPort.Parity = Parity.None;
                    break;
            }
            
            //设置数据位
            mySerialPort.DataBits = Convert.ToInt32(comboDatabits.SelectedItem);

            //设置停止位
            switch (myStopBits)
            {
                case "1":
                    mySerialPort.StopBits = StopBits.One;
                    break;
                case "2":
                    mySerialPort.StopBits = StopBits.Two;
                    break;
                default:
                    mySerialPort.StopBits = StopBits.One;
                    break;

            }
            //采用ASCII编码方式
            mySerialPort.Encoding=Encoding.ASCII;
            //接收到一个字符就触发接收事件
           mySerialPort.ReceivedBytesThreshold = 1;
            if (mySerialPort.IsOpen) //判断串口当前状态
            {

                try
                {
                   mySerialPort.Close();
                }
                catch (Exception err)
                {
                    Portstatus.Text = "串口 " + comboPortName.Text + "关闭失败,错误信息: " + err.Message;

                }
                Portstatus.Text = "串口" + comboPortName.Text + ",关闭成功。";

            }
            else
            {
                //设置好端口名和波特率
                mySerialPort.PortName = comboPortName.Text;
                mySerialPort.BaudRate = int.Parse(comboBaurate.Text);

                try
                {
                    mySerialPort.Open();
                }
                catch (Exception err)
                {
                    //打开失败,将错误信息给用户看,同时创建一个新的端口
                    Portstatus.Text = "串口" + comboPortName.Text + "打开失败,错误信息:" + err.Message;
                    mySerialPort = new SerialPort();
                }
                Portstatus.Text = "串口" + comboPortName.Text + ",打开成功。";
            }
            btnOpen.Text = mySerialPort.IsOpen ? "关闭串口" : "打开串口";
        }
        #endregion


       #region 数据接收处理
        private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] b = new byte[mySerialPort.BytesToRead];//定义byte数组,serialPort读取数据  
            this.mySerialPort.Read(b, 0, b.Length);
            string str = "";
            for (int i = 0; i < b.Length; i++)
            {
                str += string.Format("{0:X2} ", b);
            }

            switch (btn_sender)
            {

                case "读取":
                    txtRcv2.AppendText(str);
                    label06H.Text = "读取寄存器通讯正常";
                    break;
            }
  
               str = null;

              received = true;

        }
        #endregion

      
       #region 输入检测
        //用来检测输入的数据是否有效
        public static void formatstring(string strinput, int length, out string stroutput, out Boolean Valid)
        {
            stroutput = "";
            Valid = true;
            byte temp;
            if ((strinput.Length <= length) & (strinput.Length > 0))
            {
                for (int i = 0; i < strinput.Length; i++)
                {
                    try
                    {
                        //将指定基数的数字的字符串表示形式转换为等效的 8 位无符号整数。
                        temp = Convert.ToByte(strinput.ToString(), 16);
                    }

                    catch
                    {   
                        Valid = false;
                        stroutput = "";
                        break;
                    }

                    stroutput += strinput;
                }

                if (Valid & (strinput.Length < length))
                {     //判断字节长度,补零
                    for (int j = 0; j < length - strinput.Length; j++)
                    {
                        stroutput = "0" + stroutput;
                    }
                }
            }

            else
            {   //发生错误
                Valid = false;
                stroutput = "";
            }
        }

        #endregion


       #region 功能码03H,写寄存器
        private void Fsc03H(string Staddr, string value)
        {

            byte[] defByte = new byte[6];
            txtRcv2.Text = "";
            //设备地址检测
            string str1x_03 = Txtaddr.Text.ToString();
            string str1_03 = "";
            Boolean Macvalid1_03;
            formatstring(str1x_03, 2, out str1_03, out Macvalid1_03);
            if (!Macvalid1_03)
            {
                MessageBox.Show("设备地址数值不符合规范,最多输入2位十六进制数", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            byte[] numbyte1_03 = this.mysendb(str1_03);//先转换成数组类型然后赋值。
            defByte[0] = numbyte1_03[0];
            //功能码03H

            string fun_str1_03 = "03";
            byte[] fun_numbyte1_03 = this.mysendb(fun_str1_03);//打包方法,把字符串转换成Byte[]
            defByte[1] = fun_numbyte1_03[0];
                     
            //起始地址
            string str2x_03 = Staddr;
            string str2_03 = "";
            Boolean addrvalid2_03;
            formatstring(str2x_03, 4, out str2_03, out addrvalid2_03);
            if (!addrvalid2_03)
            {
                MessageBox.Show("寄存器地址数值不符合规范,最多输入4位十六进制数", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            byte[] numbyte2_03 = this.mysendb(str2_03);
            defByte[2] = numbyte2_03[0];
            defByte[3] = numbyte2_03[1];
            // 数据数量(长度)

            string str_num_03 = value;
            Boolean num_valid_03 = true;
            try
            {
                int num_03 = Convert.ToInt16(str_num_03);
                Boolean numvalid = (Convert.ToInt16(str_num_03) > read_num);
            }
            catch
            {
                num_valid_03 = false;

            }
            if (!num_valid_03)
            {
                MessageBox.Show("输入寄存器数量不符合规范,请重新输入", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if ((Convert .ToInt16(str_num_03)>read_num) | (Convert.ToInt16(str_num_03) == 0))
            {
                MessageBox.Show("输入寄存器数量过大或为0,请重新输入", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            string str_num2_03 = Convert.ToString(Convert.ToInt16(str_num_03), 16);
            string str3_03 = "";
            Boolean vlvalid=true;
            formatstring(str_num_03, 4, out str3_03, out vlvalid);
            if (vlvalid)
            {
                byte[] numbyte3_03 = this.mysendb(str3_03);
                defByte[4] = numbyte3_03[0];
                defByte[5] = numbyte3_03[1];
                //计算CRC
                byte crch = 0;
                byte crcl = 0;

                CalculateCRC(defByte, defByte.Length, out crch, out crcl);

                byte[] rebyte = new byte[defByte.Length + 2];
                for (int i = 0; i < defByte.Length; i++)
                {
                    rebyte = defByte;
                }

                rebyte[6] = crcl;
                rebyte[7] = crch;
                received = false;
                this.mySerialPort.Write(rebyte, 0, rebyte.Length);//发送
                timer1.Enabled = true;
                textBoxInformation.AppendText("读取成功\r\n");
                //显示发送内容
                txtsend.Text = "";
                string strsend = "";
                for (int i = 0; i < rebyte.Length; i++)
                {
                    strsend += string.Format("{0:X2} ", rebyte);
                }
                txtsend.Text = strsend;
                strsend = null;
            }
        }


        #endregion


       #region 将字符串打包、空格删除
        public byte[] mysendb(string s)
        {

            string temps=delspace(s);
            if (temps.Length % 2 != 0)
            {
                temps = "0" + temps;
            }
            byte[] tempb = new byte[50];
            int j = 0;

            for (int i = 0; i < temps.Length; i = i + 2, j++)
            {
                tempb[j] = Convert.ToByte(temps.Substring(i, 2), 16);
            }

            byte[] send = new byte[j];
            Array.Copy(tempb, send, j);
            return send;

        }

        //空格删除
        public string delspace(string putin)
        {
            string putout = "";
            for (int i = 0; i < putin.Length; i++)
            {
                if (putin != ' ')
                {
                    putout+= putin;
                }
            }
            return putout;
        }
        #endregion


       #region CRC
        public static void CalculateCRC(byte[] pByte, int nNumberOfBytes, out ushort pChecksum)
        {
            int nBit;
            ushort nShiftedBit;
            pChecksum = 0xFFFF;

            for (int nByte = 0; nByte < nNumberOfBytes; nByte++)
            {
                pChecksum ^= pByte[nByte];
                for (nBit = 0; nBit < 8; nBit++)
                {
                    if ((pChecksum & 0x1) == 1)
                    {
                        nShiftedBit = 1;
                    }
                    else
                    {
                        nShiftedBit = 0;
                    }
                    pChecksum >>= 1;
                    if (nShiftedBit != 0)
                    {
                        pChecksum ^= 0xA001;
                    }
                }
            }
        }

        public static void CalculateCRC(byte[] pByte, int nNumberOfBytes, out byte hi, out byte lo)
        {
            ushort sum;
            CalculateCRC(pByte, nNumberOfBytes, out sum);
            lo = (byte)(sum & 0xFF);
            hi = (byte)((sum & 0xFF00) >> 8);
        }
        #endregion
        private void btnread_Click(object sender, EventArgs e)
        {
            string a = Convert.ToString(5);
            string b = Convert.ToString(1);
            Fsc03H(a, b);
            btn_sender = ((Button)sender).Text.ToString();
        }

        private void timer1_Tick_1(object sender, EventArgs e)
        {
            if (!received)
            {
                switch (btn_sender)
                {
                    case "读取":
                        label03H.Text = "读取寄存器通讯超时,请检查设置";
                        break;
                }
            }
            //       textBoxInformation.AppendText("hah");
            timer1.Enabled = false;
        }
    }
    }
[/code]
代码我看没什么问题,你调试的时候返回的是什么,是无响应还是没有数据。
如果是没有数据,那应该是传的数据的问题,如果是接收时没有响应就应该是接收时的问题了
你调试看看是什么情况
回复

使用道具 举报

 楼主| 发表于 2013-4-12 22:13:31 | 显示全部楼层
我用串口监听程序是无返回也就是无响应,我天天抱着个电表研究,我也认为代码没什么问题。
不过,我用网上的DEMO测试,发的数据和我的是一样的(用串口监听程序看),不过他的就是有返回。
回复

使用道具 举报

发表于 2013-4-12 22:15:26 | 显示全部楼层
那你就安他的格式写啊,安他的方法写不行吗?把它的代码详细看一下,有时候一小的细节就是转机的最关键地方
要细看,说不定就是几个代码放的位置,或者是少一两行代码的事,
回复

使用道具 举报

发表于 2013-4-14 05:51:15 | 显示全部楼层
波特率是一样的吗?传输命令的编码一样么?命令是否出错了?
回复

使用道具 举报

 楼主| 发表于 2013-4-14 22:50:25 | 显示全部楼层
守望幸福 发表于 2013-4-14 05:51
波特率是一样的吗?传输命令的编码一样么?命令是否出错了?

你好,我的波特率,传输的命令,编码都是一样的。
回复

使用道具 举报

发表于 2013-4-17 19:46:35 | 显示全部楼层
不知道有没有经过单步调试,我这里没有硬件,调试了一下看看,串口若是打开失败,也会通知打开成功的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-11-22 08:27

© 2014-2021

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