找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5009|回復(fù): 3
收起左側(cè)

51采集PCF8591數(shù)據(jù)通過ESP8266上傳C#上位機(jī)

[復(fù)制鏈接]
ID:226961 發(fā)表于 2017-8-25 12:39 | 顯示全部樓層 |閱讀模式
效果
      
如果想用手機(jī)做可以參考這篇文章,自己的協(xié)議規(guī)定在文章中
android 之TCP客戶端編程
---恢復(fù)內(nèi)容開始---
請問一下博客為什么又不能直接復(fù)制粘貼圖片了呢............

先看8266的配置,8266我是用的Lua語言寫的,,因為方便快捷....這次寫的當(dāng)然比以前完善......
關(guān)于WIFI模塊可以看這幾篇
ESP8266使用詳解NodeMCU初探ESP8266刷AT固件與nodemcu固件(一)Lua腳本語言入門(二)Lua腳本語言入門(三)Lua腳本語言入門(四)Lua腳本語言入門(五)Lua腳本語言入門ESP8266使用詳解--基于Lua腳本語言最后加上一篇有人的WIFI模塊,有人的做的也不錯,當(dāng)初項目就是用的有人的
有人WIFI模塊使用詳解自己的ESP8266是建立服務(wù)器
我的init.lua

lighton=0pin = 4gpio.mode(pin,gpio.OUTPUT)tmr.alarm(0,500,1,function()  if lighton==0 then      lighton=1      gpio.write(pin,1)  else      lighton=0       gpio.write(pin,0)  endend)tmr.alarm(1, 3000, 0, function()      print("dofile wifi.lua...")      dofile("wifi.lua")end)
初始化呢,和我以前的一個地方不一樣
tmr.alarm(1, 3000, 0, function()
      print("dofile wifi.lua...")
      dofile("wifi.lua")

我讓模塊3s以后再去加載的wifi.lua
說一下原因,,,因為我在wifi.lua里面設(shè)置的串口的數(shù)據(jù)直接發(fā)送到網(wǎng)口,,如果沒有這個延時加載,一下子就執(zhí)行了串口的數(shù)據(jù)直接發(fā)送到網(wǎng)口
那么下次想通過串口向模塊發(fā)指令或者重新寫入LUA程序就會出現(xiàn)問題,因為直接執(zhí)行了串口的數(shù)據(jù)直接發(fā)送到網(wǎng)口,,有了這個延時我可以在復(fù)位的3s之前去操作模塊了
再看一下wifi.lua

ConnectCnt = 0wifi.setmode(wifi.STATIONAP)cfg={}cfg.ssid="HiWifi8266"--模塊的WIFI信號名字cfg.pwd="11223344"--密碼wifi.ap.config(cfg)--寫入配置wifi.sta.config("qqqqq","11223344")--模塊連接的路由器名稱和密碼wifi.sta.connect()tmr.alarm(2, 3000, 1, function()--3s檢測一次是否連接上路由器     if wifi.sta.getip() ~= nil then         tmr.stop(2)         print("Connected, IP is "..wifi.sta.getip())--打印分得的IP     endend)srv=net.createServer(net.TCP,28800)--創(chuàng)建TCP服務(wù) tmr.alarm(3, 1000, 1, function()--1s進(jìn)入一次看是否需要建立新的監(jiān)聽     if ConnectCnt == 0 then           srv:listen(8080,function(conn0)            print("Connect0")            ConnectCnt = 1                   if connect1 ~= nil then             connect1:close()          end            connect0 = conn0           conn0:on("receive",function(conn0,payload)            print(payload)            end)         end)    end        if ConnectCnt == 1 then        srv:listen(8080,function(conn1)             print("Connect1")             ConnectCnt = 2          if connect2 ~= nil then             connect2:close()          end            connect1 = conn1            conn1:on("receive",function(conn1,payload)                 print(payload)                 end)             end)       end                  if ConnectCnt == 2 then        srv:listen(8080,function(conn2)             print("Connect2")              ConnectCnt = 3          if connect3 ~= nil then             connect3:close()          end            connect2 = conn2            conn2:on("receive",function(conn2,payload)                 print(payload)                 end)             end)       end             if ConnectCnt == 3 then        srv:listen(8080,function(conn3)             print("Connect3")             ConnectCnt = 0          if connect0 ~= nil then             connect0:close()          end            connect3 = conn3            conn3:on("receive",function(conn3,payload)                 print(payload)                 end)             end)       endend)uart.setup(0,9600,8,0,1,0) uart.on("data",       function(data)       if connect0 ~= nil then         connect0:send(data)      end      if connect1 ~= nil then         connect1:send(data)      end       if connect2 ~= nil then          connect2:send(data)      end       if connect3 ~= nil then          connect3:send(data)      end          end, 0)
這次的建立服務(wù)可以連接3個客戶端,也不知道到底能連接多少個,,,沒測試,,就先寫了3個
注意看一下哈,我是這樣設(shè)置的
if ConnectCnt == 0 then           srv:listen(8080,function(conn0)            print("Connect0")            ConnectCnt = 1                   if connect1 ~= nil then             connect1:close()          end            connect0 = conn0           conn0:on("receive",function(conn0,payload)            print(payload)            end)         end)    end
conn0連接就把conn1關(guān)掉,
conn1連接就把conn2關(guān)掉,
conn2連接就把conn3關(guān)掉,
conn03接就把conn0關(guān)掉,
所以呢現(xiàn)在做的最多可以3個客戶端連接,,,,改天試一試能不能做到65535個連接......看看最多能連接多少個
最后的串口發(fā)送就不用說了,,,只是在原先的基礎(chǔ)上先判斷了是不是 nil 然后再發(fā)送
那就測試一下
連接模塊的無線

其實也可以不用連接模塊的無線,,因為模塊連接路由器了,所以電腦或者手機(jī)連接路由器后可以連接模塊連接路由器后分得的IP來測試
就用這四個來測試,用串口助手看信息,,對了模塊默認(rèn)內(nèi)部IP:192.168.4.1


然后我挨個點(diǎn)擊連接

現(xiàn)在連接了三個

現(xiàn)在發(fā)送數(shù)據(jù)

好再連接一個

再看一下發(fā)送數(shù)據(jù)

wifi模塊算是做好了
對了可以連接路由器測試

只不過IP地址是剛才模塊連接路由器后分得的IP
連接路由器的好處是可以做到遠(yuǎn)程控制
android客服端+eps8266+單片機(jī)+路由器之遠(yuǎn)程控制系統(tǒng)現(xiàn)在做上位機(jī)部分
整體規(guī)劃成這樣

先寫個函數(shù)獲取本機(jī)的IP地址,然后填寫到IP地址框

/// <獲取本機(jī) IP 地址>        ///         /// </summary>        /// <returns></returns>        private void getIPAddress()        {            IPAddress[] hostipspool = Dns.GetHostAddresses("");            comboBoxIPAdress.Items.Clear();            foreach (IPAddress ipa in hostipspool)            {                if (ipa.AddressFamily == AddressFamily.InterNetwork)                {                    comboBoxIPAdress.Items.Add(ipa.ToString());                    comboBoxIPAdress.SelectedIndex = comboBoxIPAdress.Items.Count > 0 ? 0 : -1;                }            }        }
程序加載的時候就搜索一下

private void Form1_Load(object sender, EventArgs e)        {            getIPAddress();        }
然后在點(diǎn)擊下拉框IP地址的下拉框的時候再搜索一下

/// <點(diǎn)擊IP下拉框>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void comboBoxIPAdress_DropDown(object sender, EventArgs e)        {            getIPAddress();        }
啟動一下看效果

這兩個IP是這兩個的

現(xiàn)在寫點(diǎn)擊按鈕連接函數(shù)
先定義一個連接線程,一個保存IP地址的變量,一個保存端口號的變量,一個連接斷開的標(biāo)志變量,還有TcpClient

public partial class Form1 : Form    {        private Thread ConnectThread;//連接線程        private IPAddress ipAddress;//ip地址        int Port = 0;//端口號        Boolean ConnectFlage = false;//連接標(biāo)志        private TcpClient myTcpClient = null;// TcpClient        public Form1()        {            InitializeComponent();        }

然后寫個連接函數(shù)

/// <連接線程方法>        ///         /// </summary>        private void ConnectMethod()        {            myTcpClient = new TcpClient();                      //實例化myTcpClient            try            {                myTcpClient.Connect(ipAddress, Port);//連接服務(wù)器                buttonConnect.Invoke(buttonConnectDelegate, "斷開");                ConnectFlage = true;            }            catch (Exception)            {                //異常處理函數(shù)                ConnectFlage = false;                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { myTcpClient.Close(); }                catch { }            }        }


然后在點(diǎn)擊事件中獲取IP和端口號,然后啟動連接任務(wù)

/// <連接點(diǎn)擊事件>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void buttonConnect_Click(object sender, EventArgs e)        {            if (ConnectFlage == false)            {                if (string.IsNullOrEmpty(comboBoxIPAdress.Text) == false)                {                    ipAddress = IPAddress.Parse(comboBoxIPAdress.Text);//獲取IP地址                    Port = Convert.ToInt32(textBoxPort.Text);          //獲取端口號                    ConnectThread = new Thread(ConnectMethod);                    ConnectThread.Start();                }                else                {                    MessageBox.Show("請檢查IP地址!", "提示");                }            }            else            {                //斷開處理函數(shù)                ConnectFlage = false;                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { myTcpClient.Close(); }                catch { }            }        }

對了寫個按鈕的回調(diào)來顯示按鈕的連接和斷開

Boolean ConnectFlage = false;//連接標(biāo)志        private TcpClient myTcpClient = null;// TcpClient        private delegate void ButtonConnectDelegate(string str);//定義連接按鈕回調(diào)        ButtonConnectDelegate buttonConnectDelegate;        public Form1()        {            InitializeComponent();        }        private void Form1_Load(object sender, EventArgs e)        {            buttonConnectDelegate = new ButtonConnectDelegate(buttonConnectMethod);//實例化            getIPAddress();        }

回調(diào)函數(shù)
/// <打開按鈕回調(diào)函數(shù)>        ///         /// </summary>        private void buttonConnectMethod(string str)        {            buttonConnect.Text = str;        }

現(xiàn)在可以測試一下連接模塊


對了這個現(xiàn)在模塊好像是很長時間不和模塊通信,模塊就自動斷開了服務(wù),,,,好像為了低功耗嗎....最后看一下怎么喚醒他,我現(xiàn)在是復(fù)位了一下

現(xiàn)在做一個函數(shù)來接收數(shù)據(jù),然后把接收的數(shù)據(jù)顯示到數(shù)據(jù)接收的顯示框,數(shù)據(jù)框的回調(diào)函數(shù)也是必不可少的,還有定義一個接收任務(wù)
關(guān)于回調(diào)可以看一下
C#委托+回調(diào)詳解先定義一個networkstrem用來接收和發(fā)送網(wǎng)絡(luò)數(shù)據(jù)流
其實C#的和JAVA的很類似
可以看一下
android 之TCP客戶端編程
看一下現(xiàn)在的工程
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;using System.Windows.Forms;namespace TCPClient{    public partial class Form1 : Form    {        private Thread ConnectThread;//連接線程        private IPAddress ipAddress;//ip地址        int Port = 0;//端口號        Boolean ConnectFlage = false;//連接標(biāo)志        private TcpClient myTcpClient = null;// TcpClient                private delegate void ButtonConnectDelegate(string str);//定義連接按鈕回調(diào)        ButtonConnectDelegate buttonConnectDelegate;        private delegate void ShowReMsgTcpDelegate(byte[] by);//定義顯示TCP接收消息回調(diào)        private ShowReMsgTcpDelegate showReMsgTcpDelegate;        private NetworkStream networkstrem = null;//網(wǎng)絡(luò)數(shù)據(jù)流        private Thread ReceiveThread;//接收消息線程        public Form1()        {            InitializeComponent();        }        private void Form1_Load(object sender, EventArgs e)        {            buttonConnectDelegate = new ButtonConnectDelegate(buttonConnectMethod);//實例化            showReMsgTcpDelegate = new ShowReMsgTcpDelegate(ShowReMsgTcpMethod);//實例化顯示回調(diào)            getIPAddress();        }        /// <獲取本機(jī) IP 地址>        ///         /// </summary>        /// <returns></returns>        private void getIPAddress()        {            IPAddress[] hostipspool = Dns.GetHostAddresses("");            comboBoxIPAdress.Items.Clear();            foreach (IPAddress ipa in hostipspool)            {                if (ipa.AddressFamily == AddressFamily.InterNetwork)                {                    comboBoxIPAdress.Items.Add(ipa.ToString());                    comboBoxIPAdress.SelectedIndex = comboBoxIPAdress.Items.Count > 0 ? 0 : -1;                }            }        }        /// <點(diǎn)擊IP下拉框>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void comboBoxIPAdress_DropDown(object sender, EventArgs e)        {            getIPAddress();        }        /// <連接點(diǎn)擊事件>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void buttonConnect_Click(object sender, EventArgs e)        {            if (ConnectFlage == false)            {                if (string.IsNullOrEmpty(comboBoxIPAdress.Text) == false)                {                    ipAddress = IPAddress.Parse(comboBoxIPAdress.Text);//獲取IP地址                    Port = Convert.ToInt32(textBoxPort.Text);          //獲取端口號                    ConnectThread = new Thread(ConnectMethod);                    ConnectThread.Start();                }                else                {                    MessageBox.Show("請檢查IP地址!", "提示");                }            }            else            {                //斷開處理函數(shù)                ConnectFlage = false;                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { ReceiveThread.Abort(); }                catch { }                try { networkstrem.Dispose(); }                catch { }                try { myTcpClient.Close(); }                catch { }            }        }        /// <連接線程方法>        ///         /// </summary>        private void ConnectMethod()        {            myTcpClient = new TcpClient();                      //實例化myTcpClient            try            {                myTcpClient.Connect(ipAddress, Port);//連接服務(wù)器                networkstrem = myTcpClient.GetStream();//獲取數(shù)據(jù)流                ReceiveThread = new Thread(ReceiveDataMethod);//啟動接收數(shù)據(jù)任務(wù)                ReceiveThread.Start();                buttonConnect.Invoke(buttonConnectDelegate, "斷開");                ConnectFlage = true;            }            catch (Exception)            {                //異常處理函數(shù)                ConnectFlage = false;                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { ReceiveThread.Abort(); }//銷毀任務(wù)                catch { }                try { networkstrem.Dispose(); }//釋放資源                catch { }                try { myTcpClient.Close(); }//關(guān)閉TCP                catch { }            }        }        /// <打開按鈕回調(diào)函數(shù)>        ///         /// </summary>        private void buttonConnectMethod(string str)        {            buttonConnect.Text = str;        }        /// <顯示串口接收到的信息--回調(diào)函數(shù)>        ///         /// </summary>        private void ShowReMsgTcpMethod(byte[] by)        {            string getMsg = string.Empty;            if (checkBoxHexShow.Checked)//16進(jìn)制顯示            {                getMsg = byteToHexStr(by); //用到函數(shù)byteToHexStr--字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串             }            else            {                getMsg = new ASCIIEncoding().GetString(by);            }            textBoxDataRes.AppendText(getMsg);        }        /// <字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串>        ///         /// </summary>        /// <param name="bytes"></param>        /// <returns></returns>        public static string byteToHexStr(byte[] bytes)        {            string returnStr = "";            try            {                if (bytes != null)                {                    for (int i = 0; i < bytes.Length; i++)                    {                        returnStr += bytes.ToString("X2");                    }                }                return returnStr;            }            catch (Exception)            {                return returnStr;            }        }        /// <接收消息線程>        ///         /// </summary>        private void ReceiveDataMethod()        {            int RecvCnt = 0;            byte[] recvBytes = new byte[1024];            while (true)            {                try                {                    if ((myTcpClient.Client.Poll(20, SelectMode.SelectRead)) && (myTcpClient.Client.Available == 0))                    {                        myTcpClient.Close();//引發(fā)異常                    }                    RecvCnt = networkstrem.Read(recvBytes, 0, recvBytes.Length);                    byte[] receive = new byte[RecvCnt];//設(shè)置緩沖區(qū)  RecvCnt  個字節(jié)                    for (int i = 0; i < receive.Length; i++)                    {                        receive = recvBytes;                    }                    textBoxDataRes.Invoke(showReMsgTcpDelegate, receive);                }                catch (Exception)                {                    //異常處理函數(shù)                    ConnectFlage = false;                    buttonConnect.Invoke(buttonConnectDelegate, "連接");                    try { ReceiveThread.Abort(); }//銷毀任務(wù)                    catch { }                    try { networkstrem.Dispose(); }//釋放資源                    catch { }                    try { myTcpClient.Close(); }//關(guān)閉TCP                    catch { }                }            }        }    }}


看一下顯示回調(diào)函數(shù)
/// <顯示串口接收到的信息--回調(diào)函數(shù)>        ///         /// </summary>        private void ShowReMsgTcpMethod(byte[] by)        {            string getMsg = string.Empty;            if (checkBoxHexShow.Checked)//16進(jìn)制顯示            {                getMsg = byteToHexStr(by); //用到函數(shù)byteToHexStr--字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串             }            else            {                getMsg = new ASCIIEncoding().GetString(by);            }            textBoxDataRes.AppendText(getMsg);        }
這個函數(shù) byteToHexStr(by); //用到函數(shù)byteToHexStr--字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串
/// <字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串>        ///         /// </summary>        /// <param name="bytes"></param>        /// <returns></returns>        public static string byteToHexStr(byte[] bytes)        {            string returnStr = "";            try            {                if (bytes != null)                {                    for (int i = 0; i < bytes.Length; i++)                    {                        returnStr += bytes.ToString("X2");                    }                }                return returnStr;            }            catch (Exception)            {                return returnStr;            }        }

那么接收數(shù)據(jù)的函數(shù)

/// <接收消息線程>        ///         /// </summary>        private void ReceiveDataMethod()        {            int RecvCnt = 0;            byte[] recvBytes = new byte[1024];            while (true)            {                try                {                    if ((myTcpClient.Client.Poll(20, SelectMode.SelectRead)) && (myTcpClient.Client.Available == 0))                    {                        myTcpClient.Close();//引發(fā)異常                    }                    RecvCnt = networkstrem.Read(recvBytes, 0, recvBytes.Length);                    byte[] receive = new byte[RecvCnt];//設(shè)置緩沖區(qū)  RecvCnt  個字節(jié)                    for (int i = 0; i < receive.Length; i++)                    {                        receive = recvBytes;                    }                    textBoxDataRes.Invoke(showReMsgTcpDelegate, receive);                }                catch (Exception)                {                    //異常處理函數(shù)                    ConnectFlage = false;                    buttonConnect.Invoke(buttonConnectDelegate, "連接");                    try { ReceiveThread.Abort(); }//銷毀任務(wù)                    catch { }                    try { networkstrem.Dispose(); }//釋放資源                    catch { }                    try { myTcpClient.Close(); }//關(guān)閉TCP                    catch { }                }            }        }

里面的這里是判斷TCP是不是斷開了連接,,如果斷開了執(zhí)行myTcpClient.Close()就會引發(fā)異常
if ((myTcpClient.Client.Poll(20, SelectMode.SelectRead)) && (myTcpClient.Client.Available == 0))
  {
        myTcpClient.Close();//引發(fā)異常
  }


現(xiàn)在連接模塊然后用串口助手發(fā)數(shù)據(jù)

已經(jīng)能接收到數(shù)據(jù)了,現(xiàn)在呢,做發(fā)送數(shù)據(jù)

/// <發(fā)送按鈕點(diǎn)擊事件>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void buttonSend_Click(object sender, EventArgs e)        {            if (!checkBoxHexSend.Checked)//字符發(fā)送            {                byte[] sendbyte = Encoding.Default.GetBytes(textBoxSend.Text);                try { networkstrem.Write(sendbyte, 0, sendbyte.Length); }                catch (Exception) { MessageBox.Show("請檢查連接", "提示!"); }            }            else//16形式進(jìn)制發(fā)送            {                byte[] sendbyte = strToToHexByte(textBoxSend.Text);//字符串轉(zhuǎn)16進(jìn)制格式,不夠自動前面補(bǔ)零                try { networkstrem.Write(sendbyte, 0, sendbyte.Length); }                catch (Exception) { MessageBox.Show("請檢查連接", "提示!"); }            }        }

/// <字符串轉(zhuǎn)16進(jìn)制格式,不夠自動前面補(bǔ)零>        ///         /// </summary>        /// <param name="hexString"></param>        /// <returns></returns>        private static byte[] strToToHexByte(String hexString)        {            int i;            bool Flag = false;            hexString = hexString.Replace(" ", "");//清除空格            if ((hexString.Length % 2) != 0)            {                Flag = true;            }            if (Flag == true)            {                byte[] returnBytes = new byte[(hexString.Length + 1) / 2];                try                {                    for (i = 0; i < (hexString.Length - 1) / 2; i++)                    {                        returnBytes = Convert.ToByte(hexString.Substring(i * 2, 2), 16);                    }                    returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);                }                catch                {                    for (i = 0; i < returnBytes.Length; i++)                    {                        returnBytes = 0;                    }                    MessageBox.Show("超過16進(jìn)制范圍A-F,已初始化為0", "提示");                }                return returnBytes;            }            else            {                byte[] returnBytes = new byte[(hexString.Length) / 2];                try                {                    for (i = 0; i < returnBytes.Length; i++)                    {                        returnBytes = Convert.ToByte(hexString.Substring(i * 2, 2), 16);                    }                }                catch                {                    for (i = 0; i < returnBytes.Length; i++)                    {                        returnBytes = 0;                    }                    MessageBox.Show("超過16進(jìn)制范圍A-F,已初始化為0", "提示");                }                return returnBytes;            }        }



現(xiàn)在測試一下發(fā)送數(shù)據(jù)



對了

當(dāng)點(diǎn)擊這兩個的時候,對應(yīng)數(shù)據(jù)框里面的內(nèi)容應(yīng)該相應(yīng)的變化
直接在點(diǎn)擊函數(shù)里面設(shè)置

/// <發(fā)送Hex和字符串選擇>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void checkBoxHexSend_CheckedChanged(object sender, EventArgs e)        {            if (checkBoxHexSend.Checked)            {                try                {                    byte[] by = StringToByte(textBoxSend.Text);                    textBoxSend.Clear();                    textBoxSend.BeginInvoke(showSeMsgTcpDelegate, by);                }                catch (Exception)                {                    //MessageBox.Show(ex.ToString());                }            }            else            {                try                {                    byte[] by = strToToHexByte(textBoxSend.Text);                    textBoxSend.Clear();                    textBoxSend.BeginInvoke(showSeMsgTcpDelegate, by);                }                catch (Exception)                {                    //MessageBox.Show(ex.ToString());                }            }        }        /// <接收Hex和字符串選擇>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void checkBoxHexShow_CheckedChanged(object sender, EventArgs e)        {            if (checkBoxHexShow.Checked)            {                try                {                    byte[] by = StringToByte(textBoxDataRes.Text);                    textBoxDataRes.BeginInvoke(showReMsgTcpDelegate, by);                }                catch (Exception)                {                    //MessageBox.Show(ex.ToString());                }            }            else            {                try                {                    byte[] by = strToToHexByte(textBoxDataRes.Text);                    textBoxDataRes.Clear();                    textBoxDataRes.BeginInvoke(showReMsgTcpDelegate, by);                }                catch (Exception)                {                    //MessageBox.Show(ex.ToString());                }            }        }
其實在優(yōu)化應(yīng)是用回調(diào)來做,,,,等做下一個畫波形圖的時候在說,現(xiàn)在做界面看不出來卡頓
現(xiàn)在呢做的差不多了,,規(guī)定一下協(xié)議

上位機(jī)發(fā)送0xaa,0x55,0x01,CRC//讀取采集的電壓數(shù)據(jù)單片機(jī)返回0xaa,0x55,0x01,采集電壓數(shù)據(jù)AD0(4字節(jié)Float型),AD1,AD2,AD3,CRC//單片機(jī)返回//上位機(jī)發(fā)送0xaa,0x55,0x02,設(shè)置的輸出電壓(單字節(jié)),CRC//設(shè)置輸出的電壓
就寫一個任務(wù),,方便點(diǎn)用定時器吧,,然后如果判斷連接上服務(wù)器了每隔100ms發(fā)送一次采集數(shù)據(jù)的命令


/// <定時發(fā)送事件>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void timer1_Tick(object sender, EventArgs e)        {            byte[] sendbyte = new byte[3];            sendbyte[0] = 0xaa;            sendbyte[1] = 0x55;            sendbyte[2] = 0x01;            SerialSend(sendbyte);        }

/// <網(wǎng)絡(luò)發(fā)送數(shù)據(jù)函數(shù)>        ///         /// </summary>        /// <param name="sendbyte"></param>        private void SerialSend(byte[] byt)        {            int crc = 0;            byte[] sendbyte = new byte[byt.Length + 2];            for (int i = 0; i < byt.Length; i++)            {                sendbyte = byt;            }            crc = crc16_modbus(byt, byt.Length);//計算CRC            byte[] Crcbyte = System.BitConverter.GetBytes(crc);//得到CRC            sendbyte[sendbyte.Length - 2] = Crcbyte[0];            sendbyte[sendbyte.Length - 1] = Crcbyte[1];            try             {                 networkstrem.Write(sendbyte, 0, sendbyte.Length);             }            catch (Exception)             {                //異常處理函數(shù)                ConnectFlage = false;                timer1.Stop();//停止定時器                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { ReceiveThread.Abort(); }//銷毀任務(wù)                catch { }                try { networkstrem.Dispose(); }//釋放資源                catch { }                try { myTcpClient.Close(); }//關(guān)閉TCP                catch { }                                MessageBox.Show("請檢查連接", "提示!");             }        }

定時器呢在這里面啟動

/// <打開按鈕回調(diào)函數(shù)>        ///         /// </summary>        private void buttonConnectMethod(string str)        {            if (str == "斷開")            {                timer1.Enabled = true;                timer1.Start();//啟動定時器            }            else            {                timer1.Enabled = false;                timer1.Stop();//停止定時器            }            buttonConnect.Text = str;        }

現(xiàn)在的代碼
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;using System.Windows.Forms;namespace TCPClient{    public partial class Form1 : Form    {        private Thread ConnectThread;//連接線程        private IPAddress ipAddress;//ip地址        int Port = 0;//端口號        Boolean ConnectFlage = false;//連接標(biāo)志        private TcpClient myTcpClient = null;// TcpClient                private delegate void ButtonConnectDelegate(string str);//定義連接按鈕回調(diào)        ButtonConnectDelegate buttonConnectDelegate;        private delegate void ShowReMsgTcpDelegate(byte[] by);//定義顯示TCP接收消息回調(diào)        private ShowReMsgTcpDelegate showReMsgTcpDelegate;        private NetworkStream networkstrem = null;//網(wǎng)絡(luò)數(shù)據(jù)流        private Thread ReceiveThread;//接收消息線程        private Thread ShowDataThread;//顯示任務(wù),點(diǎn)擊Hex顯示時        private delegate void ShowSeMsgTcpDelegate(byte[] by);//定義顯示TCP發(fā)送消息回調(diào)        private ShowSeMsgTcpDelegate showSeMsgTcpDelegate;        public Form1()        {            InitializeComponent();        }        private void Form1_Load(object sender, EventArgs e)        {            timer1.Stop();//啟動定時器            buttonConnectDelegate = new ButtonConnectDelegate(buttonConnectMethod);//實例化            showReMsgTcpDelegate = new ShowReMsgTcpDelegate(ShowReMsgTcpMethod);//實例化顯示回調(diào)            showSeMsgTcpDelegate = new ShowSeMsgTcpDelegate(showSeMsgTcpMethod);//實例化發(fā)送回調(diào)            getIPAddress();        }        /// <獲取本機(jī) IP 地址>        ///         /// </summary>        /// <returns></returns>        private void getIPAddress()        {            IPAddress[] hostipspool = Dns.GetHostAddresses("");            comboBoxIPAdress.Items.Clear();            foreach (IPAddress ipa in hostipspool)            {                if (ipa.AddressFamily == AddressFamily.InterNetwork)                {                    comboBoxIPAdress.Items.Add(ipa.ToString());                    comboBoxIPAdress.SelectedIndex = comboBoxIPAdress.Items.Count > 0 ? 0 : -1;                }            }        }        /// <點(diǎn)擊IP下拉框>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void comboBoxIPAdress_DropDown(object sender, EventArgs e)        {            getIPAddress();        }        /// <連接點(diǎn)擊事件>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void buttonConnect_Click(object sender, EventArgs e)        {            if (ConnectFlage == false)            {                if (string.IsNullOrEmpty(comboBoxIPAdress.Text) == false)                {                    ipAddress = IPAddress.Parse(comboBoxIPAdress.Text);//獲取IP地址                    Port = Convert.ToInt32(textBoxPort.Text);          //獲取端口號                    ConnectThread = new Thread(ConnectMethod);                    ConnectThread.Start();                }                else                {                    MessageBox.Show("請檢查IP地址!", "提示");                }            }            else            {                //斷開處理函數(shù)                ConnectFlage = false;                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { ReceiveThread.Abort(); }                catch { }                try { networkstrem.Dispose(); }                catch { }                try { myTcpClient.Close(); }                catch { }            }        }        /// <連接線程方法>        ///         /// </summary>        private void ConnectMethod()        {            myTcpClient = new TcpClient();                      //實例化myTcpClient            try            {                myTcpClient.Connect(ipAddress, Port);//連接服務(wù)器                networkstrem = myTcpClient.GetStream();//獲取數(shù)據(jù)流                ReceiveThread = new Thread(ReceiveDataMethod);//啟動接收數(shù)據(jù)任務(wù)                ReceiveThread.Start();                               buttonConnect.Invoke(buttonConnectDelegate, "斷開");                ConnectFlage = true;            }            catch (Exception)            {                //異常處理函數(shù)                ConnectFlage = false;                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { ReceiveThread.Abort(); }//銷毀任務(wù)                catch { }                try { networkstrem.Dispose(); }//釋放資源                catch { }                try { myTcpClient.Close(); }//關(guān)閉TCP                catch { }            }        }        /// <打開按鈕回調(diào)函數(shù)>        ///         /// </summary>        private void buttonConnectMethod(string str)        {            if (str == "斷開")            {                timer1.Enabled = true;                timer1.Start();//啟動定時器            }            else            {                timer1.Enabled = false;                timer1.Stop();//停止定時器            }            buttonConnect.Text = str;        }        /// <顯示串口接收到的信息--回調(diào)函數(shù)>        ///         /// </summary>        private void ShowReMsgTcpMethod(byte[] by)        {            string getMsg = string.Empty;            if (checkBoxHexShow.Checked)//16進(jìn)制顯示            {                getMsg = byteToHexStr(by); //用到函數(shù)byteToHexStr--字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串             }            else            {                getMsg = new ASCIIEncoding().GetString(by);            }            textBoxDataRes.AppendText(getMsg);        }        private void showSeMsgTcpMethod(byte[] by)        {            string getMsg = string.Empty;            if (checkBoxHexSend.Checked)//16進(jìn)制顯示            {                getMsg = byteToHexStr(by); //用到函數(shù)byteToHexStr--字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串             }            else            {                getMsg = new ASCIIEncoding().GetString(by);            }            textBoxSend.AppendText(getMsg);        }        /// <字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串>        ///         /// </summary>        /// <param name="bytes"></param>        /// <returns></returns>        public static string byteToHexStr(byte[] bytes)        {            string returnStr = "";            try            {                if (bytes != null)                {                    for (int i = 0; i < bytes.Length; i++)                    {                        returnStr += bytes.ToString("X2");                    }                }                return returnStr;            }            catch (Exception)            {                return returnStr;            }        }        /// <接收消息線程>        ///         /// </summary>        private void ReceiveDataMethod()        {            int RecvCnt = 0;            byte[] recvBytes = new byte[1024];            while (true)            {                try                {                    if ((myTcpClient.Client.Poll(20, SelectMode.SelectRead)) && (myTcpClient.Client.Available == 0))                    {                        myTcpClient.Close();//引發(fā)異常                    }                    RecvCnt = networkstrem.Read(recvBytes, 0, recvBytes.Length);                    byte[] receive = new byte[RecvCnt];//設(shè)置緩沖區(qū)  RecvCnt  個字節(jié)                    for (int i = 0; i < receive.Length; i++)                    {                        receive = recvBytes;                    }                    textBoxDataRes.Invoke(showReMsgTcpDelegate, receive);                }                catch (Exception)                {                    //異常處理函數(shù)                    ConnectFlage = false;                    buttonConnect.Invoke(buttonConnectDelegate, "連接");                    try { ReceiveThread.Abort(); }//銷毀任務(wù)                    catch { }                    try { networkstrem.Dispose(); }//釋放資源                    catch { }                    try { myTcpClient.Close(); }//關(guān)閉TCP                    catch { }                }            }        }        /// <發(fā)送按鈕點(diǎn)擊事件>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void buttonSend_Click(object sender, EventArgs e)        {            if (!checkBoxHexSend.Checked)//字符發(fā)送            {                byte[] sendbyte = Encoding.Default.GetBytes(textBoxSend.Text);                try { networkstrem.Write(sendbyte, 0, sendbyte.Length); }                catch (Exception) { MessageBox.Show("請檢查連接", "提示!"); }            }            else//16形式進(jìn)制發(fā)送            {                byte[] sendbyte = strToToHexByte(textBoxSend.Text);//字符串轉(zhuǎn)16進(jìn)制格式,不夠自動前面補(bǔ)零                try { networkstrem.Write(sendbyte, 0, sendbyte.Length); }                catch (Exception) { MessageBox.Show("請檢查連接", "提示!"); }            }        }        /// <字符串轉(zhuǎn)16進(jìn)制格式,不夠自動前面補(bǔ)零>        ///         /// </summary>        /// <param name="hexString"></param>        /// <returns></returns>        private static byte[] strToToHexByte(String hexString)        {            int i;            bool Flag = false;            hexString = hexString.Replace(" ", "");//清除空格            if ((hexString.Length % 2) != 0)            {                Flag = true;            }            if (Flag == true)            {                byte[] returnBytes = new byte[(hexString.Length + 1) / 2];                try                {                    for (i = 0; i < (hexString.Length - 1) / 2; i++)                    {                        returnBytes = Convert.ToByte(hexString.Substring(i * 2, 2), 16);                    }                    returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);                }                catch                {                    for (i = 0; i < returnBytes.Length; i++)                    {                        returnBytes = 0;                    }                    MessageBox.Show("超過16進(jìn)制范圍A-F,已初始化為0", "提示");                }                return returnBytes;            }            else            {                byte[] returnBytes = new byte[(hexString.Length) / 2];                try                {                    for (i = 0; i < returnBytes.Length; i++)                    {                        returnBytes = Convert.ToByte(hexString.Substring(i * 2, 2), 16);                    }                }                catch                {                    for (i = 0; i < returnBytes.Length; i++)                    {                        returnBytes = 0;                    }                    MessageBox.Show("超過16進(jìn)制范圍A-F,已初始化為0", "提示");                }                return returnBytes;            }        }        /// <字符串轉(zhuǎn)換成字節(jié)數(shù)組>        ///         /// </summary>        /// <param name="stringToConvert"></param>        /// <returns></returns>        public static byte[] StringToByte(string stringToConvert)        {            return (new ASCIIEncoding()).GetBytes(stringToConvert);        }        /// <發(fā)送Hex和字符串選擇>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void checkBoxHexSend_CheckedChanged(object sender, EventArgs e)        {            if (checkBoxHexSend.Checked)            {                try                {                    byte[] by = StringToByte(textBoxSend.Text);                    textBoxSend.Clear();                    textBoxSend.BeginInvoke(showSeMsgTcpDelegate, by);                }                catch (Exception)                {                    //MessageBox.Show(ex.ToString());                }            }            else            {                try                {                    byte[] by = strToToHexByte(textBoxSend.Text);                    textBoxSend.Clear();                    textBoxSend.BeginInvoke(showSeMsgTcpDelegate, by);                }                catch (Exception)                {                    //MessageBox.Show(ex.ToString());                }            }        }        /// <接收Hex和字符串選擇>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void checkBoxHexShow_CheckedChanged(object sender, EventArgs e)        {            if (checkBoxHexShow.Checked)            {                try                {                    byte[] by = StringToByte(textBoxDataRes.Text);                    textBoxDataRes.BeginInvoke(showReMsgTcpDelegate, by);                }                catch (Exception)                {                    //MessageBox.Show(ex.ToString());                }            }            else            {                try                {                    byte[] by = strToToHexByte(textBoxDataRes.Text);                    textBoxDataRes.Clear();                    textBoxDataRes.BeginInvoke(showReMsgTcpDelegate, by);                }                catch (Exception)                {                    //MessageBox.Show(ex.ToString());                }            }        }        /// <清除接收>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void buttonClearRecv_Click(object sender, EventArgs e)        {            textBoxDataRes.Clear();        }        /// <清除發(fā)送>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void buttonClearSend_Click(object sender, EventArgs e)        {            textBoxSend.Clear();        }        /// <設(shè)置DA輸出>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void trackBarDAout_Scroll(object sender, EventArgs e)        {            textBoxDAout.Text = trackBarDAout.Value.ToString();        }        /// <CRC  效驗  >        ///         /// </summary>        /// <param name="modbusdata"></param>        /// <param name="length"></param>        /// <returns></returns>        private int crc16_modbus(byte[] modbusdata, int length)        {            int i, j;            int crc = 0xffff;            try            {                for (i = 0; i < length; i++)                {                    crc ^= modbusdata;                    for (j = 0; j < 8; j++)                    {                        if ((crc & 0x01) == 1)                        {                            crc = (crc >> 1) ^ 0xa001;                        }                        else                        {                            crc >>= 1;                        }                    }                }            }            catch (Exception)            {                throw;            }            return crc;        }        /*          modbusdata   要校驗的數(shù)據(jù)          length       數(shù)據(jù)長度          返回值 1 正確  0 錯誤        */        private int crc16_flage(byte[] modbusdata, int length)        {            int Receive_CRC = 0, calculation = 0;//接收到的CRC,計算的CRC            Receive_CRC = crc16_modbus(modbusdata, length);            calculation = modbusdata[length + 1];            calculation <<= 8;            calculation += modbusdata[length];            if (calculation != Receive_CRC)            {                return 0;            }            return 1;        }        /// <定時發(fā)送事件>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void timer1_Tick(object sender, EventArgs e)        {            byte[] sendbyte = new byte[3];            sendbyte[0] = 0xaa;            sendbyte[1] = 0x55;            sendbyte[2] = 0x01;            SerialSend(sendbyte);        }        /// <網(wǎng)絡(luò)發(fā)送數(shù)據(jù)函數(shù)>        ///         /// </summary>        /// <param name="sendbyte"></param>        private void SerialSend(byte[] byt)        {            int crc = 0;            byte[] sendbyte = new byte[byt.Length + 2];            for (int i = 0; i < byt.Length; i++)            {                sendbyte = byt;            }            crc = crc16_modbus(byt, byt.Length);//計算CRC            byte[] Crcbyte = System.BitConverter.GetBytes(crc);//得到CRC            sendbyte[sendbyte.Length - 2] = Crcbyte[0];            sendbyte[sendbyte.Length - 1] = Crcbyte[1];            try             {                 networkstrem.Write(sendbyte, 0, sendbyte.Length);             }            catch (Exception)             {                //異常處理函數(shù)                ConnectFlage = false;                timer1.Stop();//停止定時器                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { ReceiveThread.Abort(); }//銷毀任務(wù)                catch { }                try { networkstrem.Dispose(); }//釋放資源                catch { }                try { myTcpClient.Close(); }//關(guān)閉TCP                catch { }                                MessageBox.Show("請檢查連接", "提示!");             }        }    }}
View Code
測試一下

然后呢,設(shè)置一下這個好弄得

協(xié)議的規(guī)定
//上位機(jī)發(fā)送
0xaa,0x55,0x02,設(shè)置的輸出電壓(單字節(jié)),CRC//設(shè)置輸出的電壓

/// <設(shè)置DA輸出>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void trackBarDAout_Scroll(object sender, EventArgs e)        {            byte[] sendbyte = new byte[4];            sendbyte[0] = 0xaa;            sendbyte[1] = 0x55;            sendbyte[2] = 0x02;            sendbyte[3] = Convert.ToByte(trackBarDAout.Value);            SerialSend(sendbyte);            textBoxDAout.Text = trackBarDAout.Value.ToString();        }
只要滑動這個滑動條就把當(dāng)前滑動條的數(shù)據(jù)發(fā)給Wifi模塊
現(xiàn)在寫接收數(shù)據(jù)的函數(shù),然后顯示在相應(yīng)的位置


/// <顯示串口接收到的信息--回調(diào)函數(shù)>        ///         /// </summary>        private void ShowReMsgTcpMethod(byte[] by)        {            string getMsg = string.Empty;            if (checkBoxHexShow.Checked)//16進(jìn)制顯示            {                getMsg = byteToHexStr(by); //用到函數(shù)byteToHexStr--字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串             }            else            {                getMsg = new ASCIIEncoding().GetString(by);            }            if (by[0] == 0xaa && by[1] == 0x55)            {                if (crc16_flage(by, by.Length - 2) == 1)//CRC校驗正確                {                    if (by[2] == 0x01)                    {                        float f1 = BitConverter.ToSingle(by, 3);                        float f2 = BitConverter.ToSingle(by, 7);                        float f3 = BitConverter.ToSingle(by, 11);                        float f4 = BitConverter.ToSingle(by, 15);                        textBoxAD0.Text = f1.ToString();                        textBoxAD1.Text = f2.ToString();                        textBoxAD2.Text = f3.ToString();                        textBoxAD3.Text = f4.ToString();                    }                }            }            textBoxDataRes.AppendText(getMsg);        }

就加上這幾句
if (by[0] == 0xaa && by[1] == 0x55)            {                if (crc16_flage(by, by.Length - 2) == 1)//CRC校驗正確                {                    if (by[2] == 0x01)                    {                        float f1 = BitConverter.ToSingle(by, 3);                        float f2 = BitConverter.ToSingle(by, 7);                        float f3 = BitConverter.ToSingle(by, 11);                        float f4 = BitConverter.ToSingle(by, 15);                        textBoxAD0.Text = f1.ToString();                        textBoxAD1.Text = f2.ToString();                        textBoxAD2.Text = f3.ToString();                        textBoxAD3.Text = f4.ToString();                    }                }            }
關(guān)于FLoat的轉(zhuǎn)換,先給大家一篇文章
鏈接:http://pan.baidu.com/s/1ck2m7O%20密碼:rmsg
單片機(jī)程序中會做轉(zhuǎn)換介紹,其實就是用共用體,,上位機(jī)呢就是用那個方法解析
現(xiàn)在測試一下,把數(shù)據(jù)220.5發(fā)給上位機(jī)


好了上位機(jī)測試沒有問題了
我后來改了一些地方
協(xié)議變成了一條
0xaa,0x55,0x01,(設(shè)置的電壓值),CRC16校驗

/// <定時發(fā)送事件>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void timer1_Tick(object sender, EventArgs e)        {            byte[] sendbyte = new byte[4];            sendbyte[0] = 0xaa;            sendbyte[1] = 0x55;            sendbyte[2] = 0x01;            sendbyte[3] = trackBarValue[0];//滑動條的值            SerialSend(sendbyte);        }

滑動控件的事件

/// <設(shè)置DA輸出>        ///         /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void trackBarDAout_Scroll(object sender, EventArgs e)        {            trackBarValue[0] = Convert.ToByte(trackBarDAout.Value);            textBoxDAout.Text = trackBarDAout.Value.ToString();        }


這里面加了個try,,是因為不能保證數(shù)據(jù)傳輸?shù)臅r候沒有錯誤的時候
/// <顯示串口接收到的信息--回調(diào)函數(shù)>        ///         /// </summary>        private void ShowReMsgTcpMethod(byte[] by)        {            string getMsg = string.Empty;            try            {                if (checkBoxHexShow.Checked)//16進(jìn)制顯示                {                    getMsg = byteToHexStr(by); //用到函數(shù)byteToHexStr--字節(jié)數(shù)組轉(zhuǎn)16進(jìn)制字符串                 }                else                {                    getMsg = new ASCIIEncoding().GetString(by);                }                if (by[0] == 0xaa && by[1] == 0x55)                {                    if (crc16_flage(by, by.Length - 2) == 1)//CRC校驗正確                    {                        if (by[2] == 0x01)                        {                            float f1 = BitConverter.ToSingle(by, 3);                            float f2 = BitConverter.ToSingle(by, 7);                            float f3 = BitConverter.ToSingle(by, 11);                            float f4 = BitConverter.ToSingle(by, 15);                            textBoxAD0.Text = f1.ToString();                            textBoxAD1.Text = f2.ToString();                            textBoxAD2.Text = f3.ToString();                            textBoxAD3.Text = f4.ToString();                        }                    }                }            }            catch (Exception)            {            }                        textBoxDataRes.AppendText(getMsg);        }


現(xiàn)在做單片機(jī)的程序
程序呢說幾個地方

typedef union Resolverf//51是大端模式,32默認(rèn)小端模式{    float Data;    unsigned char  Data_Table[4];}ResolverfData;typedef union ResolverLong{    long Data;    unsigned char  Data_Table[4];}ResolverLongData;
最后做完了發(fā)現(xiàn)了一個問題,這個模塊刷入Lua語言后,把數(shù)據(jù)通過WIFI發(fā)給模塊,模塊內(nèi)部默認(rèn)的是遇到'\0'后認(rèn)為是一條數(shù)據(jù),,所以呢
當(dāng)發(fā)送的byte數(shù)組里面的值是0的時候數(shù)據(jù)就會出現(xiàn)問題,直接把0以前的數(shù)據(jù)發(fā)過去了.
所以自己做了下設(shè)置

/// <網(wǎng)絡(luò)發(fā)送數(shù)據(jù)函數(shù)>        ///         /// </summary>        /// <param name="sendbyte"></param>        private void SerialSend(byte[] byt)        {            int crc = 0;            byte[] sendbyte = new byte[byt.Length + 4];//加一個檢測數(shù)據(jù)的,CRC,最后結(jié)尾判斷CRC            byte[] Change0 = new byte[1];//檢測數(shù)據(jù)用            Change0[0] = 0xff;//初始化為FF,哪位數(shù)據(jù)為0就把相應(yīng)的數(shù)據(jù)位變?yōu)?,檢測的為變?yōu)?            for (int i = 0; i < byt.Length; i++)            {                sendbyte = byt;                if (sendbyte == 0x00)                {                    sendbyte = 0x01;                    switch(i)                    {                        case 0: Change0[0] &= 0xfe; break;                        case 1: Change0[0] &= 0xfd; break;                        case 2: Change0[0] &= 0xfb; break;                        case 3: Change0[0] &= 0xf7; break;                        case 4: Change0[0] &= 0xef; break;                        case 5: Change0[0] &= 0xdf; break;                        case 6: Change0[0] &= 0xbf; break;                    }                }            }            sendbyte[sendbyte.Length-4] = Change0[0];            crc = crc16_modbus(sendbyte, sendbyte.Length-3);//計算CRC            byte[] Crcbyte = System.BitConverter.GetBytes(crc);//得到CRC            sendbyte[sendbyte.Length - 3] = Crcbyte[0];            sendbyte[sendbyte.Length - 2] = Crcbyte[1];            sendbyte[sendbyte.Length - 1] = 0xff;            if (sendbyte[sendbyte.Length - 3] == 0x00)            {                sendbyte[sendbyte.Length - 3] = 0x01;                sendbyte[sendbyte.Length - 1] = 0xF0;            }            if (sendbyte[sendbyte.Length - 2] == 0x00)            {                sendbyte[sendbyte.Length - 2] = 0x01;                sendbyte[sendbyte.Length - 1] = 0x0F;            }            try             {                if (networkstrem.CanWrite)                {                    networkstrem.Write(sendbyte, 0, sendbyte.Length);                }            }            catch (Exception)             {                //異常處理函數(shù)                ConnectFlage = false;                timer1.Stop();//停止定時器                buttonConnect.Invoke(buttonConnectDelegate, "連接");                try { ReceiveThread.Abort(); }//銷毀任務(wù)                catch { }                try { networkstrem.Dispose(); }//釋放資源                catch { }                try { myTcpClient.Close(); }//關(guān)閉TCP                catch { }                                MessageBox.Show("請檢查連接", "提示!");             }        }
想法就是在數(shù)據(jù)的后面用一個字節(jié)來標(biāo)識前面的數(shù)據(jù)哪些是0,對了如果數(shù)據(jù)是0,就把數(shù)據(jù)改為1,
0xaa, 0x55, 0x01, DA值, 標(biāo)識前面哪些數(shù)據(jù)是0, CRC低位, CRC高位, 標(biāo)識CRC有沒有0

假如說 DA值是0,那么把數(shù)據(jù)變成0x01,然后標(biāo)識下
0xaa,0x55,0x01,0x01,0xf7,CRC低位,CRC高位,0xFF(假設(shè)校驗沒有0)

如果CRC低位也是0那么
0xaa,0x55,0x01,0x01,0xf7,CRC低位,CRC高位,0xF0

如果CRC高位也是0那么
0xaa,0x55,0x01,0x01,0xf7,CRC低位,CRC高位,0x0F
其實可以用字符串格式發(fā)送,就不用麻煩了


單片機(jī)解析
/*** @brief  數(shù)據(jù)發(fā)送方法* @param  * @param  None* @param  None* @retval None* @example **/void DataSendMethod(){  if(UsartFlage == 1)//接收到數(shù)據(jù)    {        if(UsartReceive[7] != 0xff)//CRC校驗有0數(shù)據(jù)        {           if(UsartReceive[7] == 0xf0)//看一下CRC低位是0還是高位是0            {UsartReceive[5] = 0;}            if(UsartReceive[7] == 0x0f)            {UsartReceive[6] = 0;}        }                if(crc16_flage(UsartReceive, UsartReadCntCopy-5))//校驗數(shù)據(jù)        {            if(UsartReceive[4]!=0xFF)//有0數(shù)據(jù)            {                switch(UsartReceive[4])//找到哪一位是0數(shù)據(jù),修改過來                {                    case 0xFE: UsartReceive[0] = 0; break;//0位                    case 0xFD: UsartReceive[1] = 0; break;//1位                    case 0xFB: UsartReceive[2] = 0; break;//2位                    case 0xF7: UsartReceive[3] = 0; break;//3位                    case 0xEF: UsartReceive[4] = 0; break;//4位                    case 0xDF: UsartReceive[5] = 0; break;//5位                    case 0xBF: UsartReceive[6] = 0; break;//6位                }            }            if(UsartReceive[0] == 0xaa && UsartReceive[1] == 0x55)            {                UsartFlage = 0;                                switch(UsartReceive[2])                {                    case 0x01:  SetDAValue(); SendADValue(); break;//設(shè)置輸出的電壓,發(fā)送采集的電壓                    default:  break;                }            }        }        else        {           UsartFlage = 0;        }    } }




一,關(guān)于大小端
關(guān)于大小端---數(shù)據(jù)的低位存在低地址,高位存在高地址就是小端模式
關(guān)于大小端---數(shù)據(jù)的低位存在高地址,高位存在低地址就是大端模式
傳輸float數(shù)據(jù)直接用共用體解決,可以看看上面的青智儀表的文章,,,這個用的挺多的,,幾乎所有設(shè)備的浮點(diǎn)型數(shù)據(jù)都是這樣存儲的,,,,,,

二,51單片機(jī)使用printf,,,我程序里能使用printf,,不過說一點(diǎn)注意的地方
如果51想用printf發(fā)送數(shù)據(jù),加上這個函數(shù),其實也可以不加,,,不過必須在初始化的時候TI必須一直為 1 但是這樣的話就會有問題,程序一直進(jìn)入串口中斷......會造成主程序卡卡卡卡.......

/* 用自帶的printf 發(fā)送數(shù)據(jù) */char putchar(char c)  {      UartSend(c);      return c;  }  
別忘了包含

#include "stdio.h"#include <stdarg.h>
可以看一下這篇文章
http://blog.csdn.net/googlemi/article/details/8996605
發(fā)送數(shù)據(jù)
printf("%d",(unsigned int)Value);注意Value如果是char 或者 unsigned char 這樣的時候要加強(qiáng)制轉(zhuǎn)換
可以看一下這篇
http://taihang604.blog.163.com/blog/static/20834216520125185579173/

三,關(guān)于51單片機(jī)里面的CRC16校驗
記住:操作的數(shù)據(jù),,定義的數(shù)據(jù)類型要定義成 unsigned char  或者 unsigned int 類型的,,否則會算錯的
/*** @brief  計算CRC* @param  *modbusdata:數(shù)據(jù)指針* @param  length:數(shù)據(jù)長度* @param  * @retval 計算的CRC值* @example **/unsigned int crc16_modbus(unsigned char *modbusdata, char length){    char i, j;    unsigned int crc = 0xffff;    for (i = 0; i < length; i++)    {        crc ^= modbusdata;        for (j = 0; j < 8; j++)        {                if ((crc & 0x01) == 1)                {                        crc = (crc >> 1) ^ 0xa001;                }                else                {                        crc >>= 1;                }        }    }        return crc;}/*** @brief  判斷數(shù)據(jù)的CRC校驗是否正確* @param  *modbusdata:數(shù)據(jù)指針* @param  length:數(shù)據(jù)長度* @param  * @retval 1 正確  0 錯誤* @example **/char crc16_flage(unsigned char *modbusdata, char length){    unsigned int Receive_CRC=0,calculation=0;//接收到的CRC,計算的CRC    int i = 0;        Receive_CRC = crc16_modbus(modbusdata, length);        calculation = modbusdata[length+1];    calculation <<= 8;    calculation += modbusdata[length];        if(calculation != Receive_CRC)    {        return 0;    }    return 1;}

四,51單片機(jī)的發(fā)送數(shù)據(jù)我是用中斷發(fā)送的
只需要把準(zhǔn)備好的數(shù)據(jù)調(diào)用這個函數(shù)

/*** @brief  串口發(fā)送函數(shù)中斷函數(shù)* @param  * @param  None* @param  None* @retval None* @example **/void UartSendTI(unsigned char *value,int DataLen) {    UsartSendData = value;    UsartSendDataCnt = DataLen;    TI = 1;}



/*** @brief  串口發(fā)送函數(shù)中斷函數(shù)* @param  * @param  None* @param  None* @retval None* @example **/void UartSendTI(unsigned char *value,int DataLen) {    UsartSendData = value;    UsartSendDataCnt = DataLen;    TI = 1;}void UARTInterrupt(void) interrupt 4{    if(RI)    {        RI=0;        UsartReceive[UsartReadCnt]=SBUF;//接收串口數(shù)據(jù)        UsartReadCnt++;        if(UsartReadCnt>8)//防止溢出        {            UsartReadCnt = 0;        }    }    if(TI)    {        TI = 0;        if(UsartSendDataCnt>0)        {          SBUF = *UsartSendData++;          UsartSendDataCnt--;        }        else        {          TI = 0;        }  }}


五,串口接收和以前一樣用的空閑檢測

void Timer0Interrupt(void) interrupt 1{    TH0 = (65536 - 1000)/256;    TL0 = (65536 - 1000)%256;        //TimeCnt ++;        if (UsartReadCnt != 0)//如果接收到數(shù)據(jù)了    {            if (UsartIdleCnt == UsartReadCnt)//1ms時間數(shù)據(jù)沒了變化            {                UsartReadCntCopy = UsartReadCnt;                UsartReadCnt = 0;//清零數(shù)據(jù)個數(shù)                UsartIdleCnt = 0;//清零                UsartFlage = 1;            }            else            {                UsartIdleCnt = UsartReadCnt;            }    }}


說一下IIC,,因為當(dāng)初一個學(xué)弟問過我,簡要說一下
IIC協(xié)議規(guī)定發(fā)送數(shù)據(jù)的時候要先發(fā)一個起始信號,,,也就是告訴對方我開始和你通信了

函數(shù)原型: void  Start_I2c();  功能:     啟動I2C總線,即發(fā)送I2C起始條件.  ********************************************************************/void Start_I2c(){  SDA=1;         /*發(fā)送起始條件的數(shù)據(jù)信號*/  _Nop();  SCL=1;  _Nop();        /*起始條件建立時間大于4.7us,延時*/  _Nop();  _Nop();  _Nop();  _Nop();      SDA=0;         /*發(fā)送起始信號*/  _Nop();        /* 起始條件鎖定時間大于4μs*/  _Nop();  _Nop();  _Nop();  _Nop();         SCL=0;       /*鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) */  _Nop();  _Nop();}

然后呢,發(fā)送器件的地址,,因為可能掛接了好幾個IIC設(shè)備,目的是找到我想與之通信的那個,
看一下發(fā)送數(shù)據(jù),,,SCL=0;注意IIC規(guī)定只有SCL=0;的時候SDA上的數(shù)據(jù)才允許改變.....
void  SendByte(unsigned char  c){ unsigned char  BitCnt; //SCL=0; 起始信號最后是SCL=0;所以不用寫了 for(BitCnt=0;BitCnt<8;BitCnt++)  /*要傳送的數(shù)據(jù)長度為8位*/    {     if((c<<BitCnt)&0x80)SDA=1;   /*判斷發(fā)送位*/       else  SDA=0;                     _Nop();     SCL=1;               /*置時鐘線為高,通知被控器開始接收數(shù)據(jù)位*/      _Nop();       _Nop();             /*保證時鐘高電平周期大于4μs*/      _Nop();      _Nop();      _Nop();              SCL=0;     }

發(fā)送數(shù)據(jù)的時候先發(fā)的高位,,SCL為低電平的時候SDA準(zhǔn)備數(shù)據(jù),,,然后SCL為高電平,數(shù)據(jù)就傳過去了(就是告訴對方你接收SDA上的電平數(shù)據(jù)哈),
接著

8位數(shù)據(jù)傳完之后,主機(jī)(單片機(jī))把SDA置為高電平,,,然后SCL置為高電平這個時候呢如果從機(jī)(PCF8591)確實接收完了8位數(shù)據(jù),就會把SDA拉低
這就是從機(jī)的應(yīng)答信號,說明數(shù)據(jù)傳輸成功,,,非應(yīng)答就是不用管它
void  SendByte(unsigned char  c){ unsigned char  BitCnt; //SCL=0; 起始信號最后是SCL=0;所以不用寫了 for(BitCnt=0;BitCnt<8;BitCnt++)  /*要傳送的數(shù)據(jù)長度為8位*/    {     if((c<<BitCnt)&0x80)SDA=1;   /*判斷發(fā)送位*/       else  SDA=0;                     _Nop();     SCL=1;               /*置時鐘線為高,通知被控器開始接收數(shù)據(jù)位*/      _Nop();       _Nop();             /*保證時鐘高電平周期大于4μs*/      _Nop();      _Nop();      _Nop();              SCL=0;     }        _Nop();    _Nop();    SDA=1;                /*8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位*/    _Nop();    _Nop();       SCL=1;    _Nop();    _Nop();    _Nop();    if(SDA==1)ack=0;            else ack=1;        /*判斷是否接收到應(yīng)答信號*/    SCL=0;    _Nop();    _Nop();}
接著就是發(fā)命令或者說數(shù)據(jù)了,,,,這個數(shù)據(jù)呢,就和芯片有關(guān)了,,看芯片資料才知道
源碼鏈接

鏈接:http://pan.baidu.com/s/1qX8gfA8%20密碼:8xiy
實物鏈接
https://item.taobao.com/item.htm?spm=686.1000925.0.0.4a155084sH7efy&id=557671967654
哎呀!為什么博客又不能直接復(fù)制粘貼圖片了呢........這樣的話每寫一篇文章就會很耽誤時間了.............
回復(fù)

使用道具 舉報

ID:79874 發(fā)表于 2019-12-26 04:24 來自手機(jī) | 顯示全部樓層
失鏈接,大佬再分享一下
回復(fù)

使用道具 舉報

ID:79874 發(fā)表于 2020-4-8 08:47 來自手機(jī) | 顯示全部樓層
失效分享一下
回復(fù)

使用道具 舉報

ID:318489 發(fā)表于 2021-3-10 14:48 | 顯示全部樓層
失效了,還能再分享一下嗎?
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表