using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace K60主控器硬件功能测试
{ 
    ///---------------------------------------------------------------------*
    /// <summary>                                                           *
    /// 类          :SCI:串口功能实现类                                     *
    /// 类   功   能:打开串口、关闭串口及串口的接收和发送功能                *
    /// 类中函数包含:                                                       *
    ///             (1)SCIInit:串口初始化                                   *
    ///             (2)SCISendData:发送数据                                 *
    ///             (3)SCIReceiveData:接收数据                              *
    ///             (4)SCIClose:关闭串口                                    *
    ///             (5)SetInterrupt: 设置串口接收中断条件                   *
    /// 说        明:本模块与具体的窗体界面无关                             *
    /// </summary>                                                          *
    /// <remarks></remarks>                                                 *
    /// --------------------------------------------------------------------*
    public partial class SCI
    {
        /// ----------------------------------------------------------------*
        /// <summary>                                                       *
        /// 函 数 名:SCIInit                                                *
        /// 功    能:初始化串口,并打开串口                                  *
        /// 参    数:Port:串口控件,串口类型                                 *
        ///          ComNum:串口号,字符串类型(例如COM1,COM2等)              *
        ///          Baud:波特率,整型(例如9600,19200,38400,115200等)        *
        /// 返    回:返回一个布尔值,当串口成功打开后,返回True               *
        ///          当串口打开异常时,返回False                             *
        /// 内部调用:无                                                     *
        /// </summary>                                                      *
        /// <param name="Port"></param>                                     *
        /// <param name="ComNum"></param>                                   *
        /// <param name="Baud"></param>                                     *
        /// <returns></returns>                                             *
        /// ----------------------------------------------------------------*
        public bool SCIInit(System.IO.Ports.SerialPort Port, 
                            string ComNum, Int32 Baud)
        {
            try
            {
                Port.Close();               //保证初始化之前是关闭的
                Port.PortName = ComNum;     //设置串口号
                Port.BaudRate = Baud;       //设置波特率
                Port.Parity = System.IO.Ports.Parity.None;//设置无奇偶校验
                Port.DataBits = 8;          //设置8比特数据位
                Port.StopBits = System.IO.Ports.StopBits.One;//设置1位停止位
                Port.ReadBufferSize = 4096; //接收缓冲区大小(字节) 
                Port.Open();                //打开串口
            }
            catch
            {
                //产生错误,返回false
                return false;
            }
            return true;
        }

        ///-----------------------------------------------------------------*
        /// <summary>                                                       *
        /// 函 数 名:SCISendData                                            *
        /// 功    能:串口发送数据                                           *
        /// 参    数:Port:串口控件,串口类型                                 *
        ///          SendArray:存放要发送的数据,字节数组                    *
        /// 返    回:返回一个布尔值,当发送成功后,返回True;否则返回False     *
        /// 内部调用:无                                                     *
        /// </summary>                                                      *
        /// <param name="Port"></param>                                     *
        /// <param name="SendArray"></param>                                *
        /// <returns></returns>                                             *
        ///-----------------------------------------------------------------*
        public bool SCISendData(System.IO.Ports.SerialPort Port, 
                                       ref byte[] SendArray)
        {
            try
            {
                Port.Write(SendArray, 0, SendArray.Length);//通过串口发送出去
                //for (int i = 0; i < SendArray.Length; i++)
                //{
                //    TbSCISend.Text += SendArray[i].ToString("X2")
                //                          + " ";
                //}
            }
            catch 
            {
                //产生错误,返回false
                return false;
            }
            return true;
        }

        ///-----------------------------------------------------------------*
        /// <summary>                                                       *
        /// 函 数 名:SCIReceiveData                                         *
        /// 功    能:接收数据                                               *
        /// 参    数:(1)Port:串口控件,串口类型                              *
        ///          (2)ReceiveArray:存放接受数据数组,字节数组              *
        /// 返    回:返回一个布尔值,当接收成功后,返回True,否则,返回False    *
        /// 函数调用:无                                                     *
        /// </summary>                                                      *
        /// <param name="Port"></param>                                     *
        /// <param name="ReceiveArray"></param>                             *
        /// <returns></returns>                                             *
        ///-----------------------------------------------------------------*
        public bool SCIReceiveData(System.IO.Ports.SerialPort Port,
                                    ref byte[] ReceiveArray)
        {

            int len, m, gpseudo;
            byte ch, pre = 0;
            byte i = 0;
            byte j = 0;
            len = Port.BytesToRead;//获得接收缓冲区中的字节数
            try
            {
                ReceiveArray = new byte[64];//与低端一致
                ch = (byte)Port.ReadByte();
                //从输入缓冲区中读取len个字节
                //并将其放入ReceiveArray中,并清除缓冲区
                //  Port.Read(ReceiveArray, 0, len);
                //去干扰
                while (ch != 0xAA)
                {
                    ch = (byte)Port.ReadByte();
                    i++;
                }

                m = 0;
                ReceiveArray[m] = ch;//帧头
                m++;
                i++;
                pre = ch;
                gpseudo = 0;//防止不同数据帧之间的干扰
                for (j = i; (ch != 0x55) || ((ch == 0x55) && (gpseudo % 2 == 1)); j++)    //中间的一个条件换一下，测试总是出现问题 (j < len-1)
                {
                    ch = (byte)Port.ReadByte();
                    if ((ch != 0x55) || ((ch == 0x55) && (gpseudo % 2 == 1)))
                    {
                        if ((j > 0) && (ch) == 0xA5)
                        {
                            if (pre != 0xA5)
                            {
                                gpseudo = 1;
                            }
                            else
                            {
                                gpseudo = gpseudo + 1;
                            }
                        }
                        else
                        {
                            gpseudo = 0;
                        }
                    }

                    if (gpseudo % 2 == 1)  //会把所有的全部删掉，如何让其只删掉一个?
                    {

                        j++;//策略不同了,又该回来了
                        pre = ch;
                        continue;//怎么能用break呢,哎,----------;一个关键词用错,浪费了大半天时间0503
                        //gDATE_frame[m]=0;//需要在此清零吗
                    }
                    ReceiveArray[m] = ch;
                    m++;
                    //j++;,for循环里已有了
                    pre = ch;

                }

                ReceiveArray[m++] = ch;

                //if (ReceiveArray[1] != m)//不等于的话，清空，丢掉本次所有数据，方便下次传输
                //{
                //    ReceiveArray = new byte[len];
                //}//0512晚上可能是這個問題

            }
            catch
            {
                //产生错误,返回false
                return false;
            }
            return true;

            //int len;

            //byte i=0;
            //byte data;
            //byte restric=100;

            //len =Port.BytesToRead;//获得接收缓冲区中的字节数
            //try
            //{
            //    ReceiveArray = new byte[100]; //与低端一致
            //    PublicVar.frameCount = 0;
            //    for (i = 0; (i < restric) && (i < len); i++)
            //    {
            //        data = (byte)Port.ReadByte();
            //        switch (PublicVar.frameCount)
            //        {
            //            case 0:    //第一个数据
            //                {
            //                    if (data == 0xBB)    //收到数据是帧头FrameHead
            //                    {
            //                        ReceiveArray[0] = data;
            //                        PublicVar.frameCount++;

            //                    }
            //                    break;
            //                }

            //            case 1:    //第二个数据，该数据是随后接收的数据个数
            //                {
            //                    ReceiveArray[1] = data;
            //                    restric = data;//限制字节读取
            //                    PublicVar.frameCount++;
            //                    break;
            //                }

            //            default:   //其他情况
                            
            //                    //第二位数据是有效数据长度,根据它接收余下的数据直到帧尾前一位
            //                    if (PublicVar.frameCount >= 2 && PublicVar.frameCount <= (ReceiveArray[1] - 2))  //0511:帧长指所有字段的字节个数      
            //                    {
            //                        ReceiveArray[PublicVar.frameCount] = data;
            //                        PublicVar.frameCount++;
            //                        break;
            //                    }
            //                    else if (PublicVar.frameCount >= (ReceiveArray[1] - 1))
            //                    //若是末尾数据则执行
            //                    //0511:帧长指所有字段的字节个数，可以是大于号吗，觉得长度可存在冗余，可适当修改其中逻辑
            //                    {
            //                        if (data == 0xCC)    //若是帧尾
            //                        {
            //                            ReceiveArray[PublicVar.frameCount] = data;   //将帧尾0xCC存入缓冲区
            //                            PublicVar.frameCount = 0;   //接收数据个数清0,可以开始重新组帧

            //                        }
            //                        else                //若不是帧尾
            //                        {
            //                            PublicVar.frameCount = 0;   //组帧失败，计数清0，准备重新组帧
            //                        }
            //                        break;
            //                    }
            //                    else
            //                    {
            //                        break;
            //                    }
                            
            //               // break;
            //        }   //switch_END
            //    }
                    
                

            //    ////while (data != 0xBB)
            //    ////{
            //    ////    data = (byte)Port.ReadByte();
            //    ////}
            //    //ReceiveArray[0] = data;
            //    //len=(byte)Port.ReadByte();//长度
            //    //ReceiveArray[1] = (byte)len;

            //    ////从输入缓冲区中读取len个字节
            //    ////并将其放入ReceiveArray中,并清除缓冲区
            //    //for (i = 2; i < len; i++)
            //    //{
            //    //    ReceiveArray[i] = (byte)Port.ReadByte();
            //    //}

            //    ////if (ReceiveArray[1] != len)//不等于的话，清空，丢掉本次所有数据，方便下次传输
            //    ////{
            //    ////    ReceiveArray = new byte[len];
            //    ////    return false;
            //    ////}
        
            //}
            // catch
            // {
            //    //产生错误,返回false
            //    return false;
            // }
            //return true;
        }

        ///-----------------------------------------------------------------*
        /// <summary>                                                       *
        /// 函 数 名:SCIClose                                               *
        /// 功    能:关闭串口                                               *
        /// 参    数:Port:串口控件,串口类型                                 *
        /// 返    回:返回一个布尔值,当串口成功关闭后,返回True,否则返回False *
        /// 内部调用:无                                                     *
        /// </summary>                                                      *
        /// <param name="Port"></param>                                     *
        /// <returns></returns>                                             *
        ///-----------------------------------------------------------------*
        public bool SCIClose(System.IO.Ports.SerialPort Port)
        {
            try
            {
               Port.DiscardInBuffer(); //丢弃接收缓冲区的数据
               Port.DiscardOutBuffer();//丢弃发送缓冲区的数据
               Port.Dispose();         //释放串行通信的所有资源
               Port.Close();           //关闭串口
            }
            catch
            {
                //产生错误,返回false
                return false;
            }
            return true;
        }

        ///-----------------------------------------------------------------*
        /// <summary>                                                       *
        /// 函 数 名:SetInterrupt                                           *
        /// 功    能:设置中断条件                                           *
        /// 参    数:(1)Port:串口控件                                       *
        ///          (2)a:触发接收中断的条件,整型                           *
        /// 返    回:无                                                     *
        /// 函数调用:无                                                     *
        /// </summary>                                                      *
        /// <param name="Port"></param>                                     *
        /// <param name="a"></param>                                        *
        ///-----------------------------------------------------------------*
        public void SetInterrupt(System.IO.Ports.SerialPort Port,int a)
        {
            //设置串口接收终端条件
            Port.ReceivedBytesThreshold = a;
        }
        ///-----------------------------------------------------------------*
        /// <summary>                                                       *
        /// 功    能:组帧                                                   *
        /// 函数调用:无                                                     *
        /// </summary>                                                      *
        /// <param name="Cmdtype">数据类型</param>                          *
        /// <param name="data">需要发送的数据      </param>                 *
        ///-----------------------------------------------------------------*
        public void ComponentSCI(int Cmdtype, byte[] data)
        {
            int i;
            int len = data.Length;

            PublicVar.g_SendByteArray = new byte[len + 4];//0～35下标
            byte type = (byte)Cmdtype;
            //byte lenth1 = (byte)((len+1) >> 8);
            //byte length2 = (byte)(len+1);

            byte temp1 = 0xAA;
            byte temp2 = 0x55;
            //temp1 = 0xaa;//System.Text.Encoding.Default.GetBytes("A");
            PublicVar.g_SendByteArray[0] = temp1;//加入帧头
            //temp2 = 0xbb;//System.Text.Encoding.Default.GetBytes("Z");
            PublicVar.g_SendByteArray[1] = (byte)(len + 4);//加入数据长度  ，该数据存在问题，在存在增加转义字符的情况下
            PublicVar.g_SendByteArray[2] = type;//加入功能标志
            for (i = 3; i < len + 3; i++)
                PublicVar.g_SendByteArray[i] = data[i - 3];//加入有效数据
           // PublicVar.g_SendByteArray[i++] = 0;//校验和
            PublicVar.g_SendByteArray[i] = temp2;//加入帧尾
            //动态分配len字节单元内容用来存放发送数据
            //发送全局变量g_SendByteArray中的数据,并返回结果

        }
    }
}