精华内容
下载资源
问答
  • 串口通讯超时的设置与含义(COMMTIMEOUTS)
    千次阅读
    2017-09-18 15:42:23
    COMMTIMEOUTS:COMMTIMEOUTS主要用于串口超时参数设置。COMMTIMEOUTS结构如下: 

    typedef struct _COMMTIMEOUTS { 
    DWORD ReadIntervalTimeout; 
    DWORD ReadTotalTimeoutMultiplier; 
    DWORD ReadTotalTimeoutConstant; 
    DWORD WriteTotalTimeoutMultiplier; 
    DWORD WriteTotalTimeoutConstant; 
    } COMMTIMEOUTS,*LPCOMMTIMEOUTS; 

     

    间隔超时=ReadIntervalTimeout
    总超时   =   ReadTotalTimeoutMultiplier   * 字节数   +   ReadTotalTimeoutConstant 

     

    串口读取事件分为两个阶段(我以Win32 API函数ReadFile读取串口过程来说明一下)
    第一个阶段是:串口执行到ReadFile()函数时,串口还没有开始传输数据,所以串口缓冲区的第一个字节是没有装数据的,这时候总超时起作用,如果在总超时时间内没有进行串口数据的传输,ReadFile()函数就返回,当然 没有读取到任何数据。而且,间隔超时并没有起作用。
    第二阶段:假设总超时为20秒,程序运行到ReadFile(),总超时开始从0 计时,如果在计时到达10秒时,串口开始了数据的传输,那么从接收的第一个字节开始,间隔超时就开始计时,假如间隔超时为1ms,那么在读取完第一个字节后,串口开始等待1ms,如果1ms之内接收到了第二个字节,就读取第二个字节,间隔超时重置为0并计时,等待第三个字节的到来,如果第三个字节到来的时间超过了1ms,那么ReadFile()函数立即返回,这时候总超时计时是没到20秒的。如果在20秒总计时时间结束之前,所有的数据都遵守数据间隔为1ms的约定并陆陆续续的到达串口缓冲区,那么就成功进行了一次串口传输和读取;如果20秒总计时时间到,串口还陆陆续续的有数据到达,即使遵守字节间隔为1ms的约定,ReadFile()函数也会立即返回,这时候总超时就起作用了。
    总结起来,总超时在两种情况下起作用
    第一:串口没进行数据传输,等待总超时时间那么长ReadFile()才返回。非正常数据传输
    第二:数据太长,总超时设置太短,数据还没读取完就返回了。读取的数据是不全的
    间隔超时触发是有条件的
    第一:在总超时时间内。
    第二:串口进行了数据的传输。
    成功的进行一次串口数据的传输和读取,只有总超时和间隔超时相互参与配合才能完成

    更多相关内容
  • C#下串口通讯超时优化类

    千次阅读 2017-10-18 18:12:27
    一直以来就想实现一个功能,串口通讯实现数据下发之后有可能需要很长时间才能返回数据或者需要好几包才能下发下来!这个时候就应该有一个等待的机制,数据下发之后两个数据需要设置,第一个就是等待的步长值,第二个...

    转载连接: http://blog.csdn.net/energeticsunxiaocong/article/details/40737627


    一直以来就想实现一个功能,串口通讯实现数据下发之后有可能需要很长时间才能返回数据或者需要好几包才能下发下来!这个时候就应该有一个等待的机制,数据下发之后两个数据需要设置,第一个就是等待的步长值,第二个就是超时时间。这个数据完整性的判断肯定是要自己去写程序判断一下,包括数据的长度啊等等规则。数据下发之后每隔单位时间就要去判断一下当前返回的数据是否已经符合了完整性的判断,若是已经符合返回true --完成。

    如果返回false --则继续等待。直到超时时间到了之后进行超时提示!


    看似简单的一个操作,真正写起来才知道没有那么简单。我是前后反复写了好几天然后经过不断的完善才做成现在这个样子,确实也是不容易,现在拿出来和大家分享,有觉得不合适或者不好的地方欢迎给我留言!


    [csharp]  view plain  copy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5. using System.IO.Ports;  
    6. using System.Threading;  
    7.   
    8. namespace 串口测试  
    9. {  
    10.     public class WaitRec  
    11.     {  
    12.         /// <summary>  
    13.         /// 发送的内容  
    14.         /// </summary>  
    15.         public string strSend;  
    16.   
    17.         /// <summary>  
    18.         /// 发送一次等待的秒数  
    19.         /// </summary>  
    20.         public int second;  
    21.   
    22.         /// <summary>  
    23.         /// 超时时间  
    24.         /// </summary>  
    25.         public int time_To_Timeout;  
    26.   
    27.         /// <summary>  
    28.         /// 声明  
    29.         /// </summary>  
    30.         /// <param name="strSend">发送的数据</param>  
    31.         /// <param name="second">发送之后进行判断的时间间隔</param>  
    32.         /// <param name="time_To_Timeout">发送数据之后的超时时间</param>  
    33.         public WaitRec(string strSend, int second, int time_To_Timeout)  
    34.         {  
    35.             this.strSend = strSend;  
    36.             this.second = second;  
    37.             this.time_To_Timeout = time_To_Timeout;  
    38.         }  
    39.     }  
    40.     public class SerialPortHelper  
    41.     {  
    42.         //串口类  
    43.         private SerialPort sp;  
    44.         //处理接收信息的方法  
    45.         public Action<string> action;  
    46.         public Action<string> TimeOutAction;  //超时之后执行的操作  
    47.         #region 构造参数  
    48.         /// <summary>  
    49.         /// 初始化信息  
    50.         /// </summary>  
    51.         /// <param name="com">端口号,COM1</param>  
    52.         /// <param name="btl">波特率,9600</param>  
    53.         /// <param name="sjw">数据位,8</param>  
    54.         /// <param name="tzw">停止位,StopBits.One</param>  
    55.         /// <param name="xyw">校验位,Parity.None</param>  
    56.         /// <param name="func">处理接收数据的方法</param>  
    57.         public SerialPortHelper(string com, int btl, int sjw, StopBits tzw, Parity xyw, Action<string> action, Action<string> TimeOutAction)  
    58.         {  
    59.             sp = new SerialPort();  
    60.             sp.PortName = com;  
    61.             sp.BaudRate = btl;  
    62.             sp.DataBits = sjw;  
    63.             sp.StopBits = tzw;  
    64.             sp.Parity = xyw;  
    65.             sp.DataReceived += serialPort1_DataReceived;  
    66.             this.action = action;  
    67.             this.TimeOutAction = TimeOutAction;  
    68.             sp.Open();  
    69.         }  
    70.         #endregion  
    71.         /// <summary>  
    72.         /// 将string转换到Byte[]  
    73.         /// </summary>  
    74.         /// <param name="Str_Datasource"></param>  
    75.         /// <returns></returns>  
    76.         public byte[] StringToBytes(string Str_Datasource)  
    77.         {  
    78.             Str_Datasource = Str_Datasource.Replace(" """);  
    79.             byte[] BytesResult = new byte[Str_Datasource.Length / 2];  
    80.             for (int i = 0; i < Str_Datasource.Length / 2; i++)  
    81.             {  
    82.                 BytesResult[i] = (byte)Convert.ToInt32(Str_Datasource.Substring(i * 2, 2), 16);  
    83.             }  
    84.             return BytesResult;  
    85.         }  
    86.         /// <summary>  
    87.         /// 下发数据  
    88.         /// </summary>  
    89.         /// <param name="Str_Source"></param>  
    90.         public void SendData(string Str_Source)  
    91.         {  
    92.             byte[] BytescmdTosend = StringToBytes(Str_Source);  
    93.             sp.Write(BytescmdTosend, 0, BytescmdTosend.Length);  
    94.         }  
    95.         private string strTemp = ""//这是一个用来标识状态的字符 接收数据之后这个就自动更改成为“接收”  
    96.         /// <summary>  
    97.         /// 下发数据  
    98.         /// </summary>  
    99.         /// <param name="str">需要下发的数据</param>  
    100.         /// <param name="second">系统每隔单位时间去判断的时间间隔</param>  
    101.         /// <param name="time_To_Timeout">每次接收数据设置的超时时间</param>  
    102.         public void SendData(string str, int second, int time_To_Timeout)  
    103.         {  
    104.             strTemp = ""//接收到的数据 每次发送之前需要手工清零一下  
    105.             byte[] BytescmdTosend = StringToBytes(str);  
    106.             sp.Write(BytescmdTosend, 0, BytescmdTosend.Length);  
    107.             WaitRec wr = new WaitRec(str, second, time_To_Timeout);  
    108.             ParameterizedThreadStart ParStart = new ParameterizedThreadStart(WaitRec);  
    109.             Thread myThread = new Thread(ParStart);  
    110.             myThread.IsBackground = true;  
    111.             myThread.Start(wr);  
    112.         }  
    113.         /// <summary>  
    114.         /// 字符串的取和计算  
    115.         /// </summary>  
    116.         /// <param name="Str_Source"></param>  
    117.         /// <returns></returns>  
    118.         public string FunctionGetSum(string Str_Source)  
    119.         {  
    120.             string Str_Sum = string.Empty;  
    121.             int Int_Sum = 0;  
    122.             for (int i = 0; i < Str_Source.Length; i += 2)  
    123.             {  
    124.                 Int_Sum += Convert.ToInt32(Str_Source.Substring(i, 2), 16);  
    125.             }  
    126.             Int_Sum = Int_Sum % 0x100;  
    127.             Str_Sum = Convert.ToString(Int_Sum, 16);  
    128.             return Str_Sum;  
    129.         }  
    130.         /// <summary>  
    131.         /// 判断格式是否正确  
    132.         /// </summary>  
    133.         /// <param name="Str_Source"></param>  
    134.         /// <returns></returns>  
    135.         public bool FunctionGetCmdCorrect(string Str_Source)  
    136.         {  
    137.             bool b_Correct = false;  
    138.             //姑且设置两个条件若是最后是0x16 而且符合376.1规约的校验位规则 则姑且认为是正确的数据  
    139.             //首先剔除所有空格  
    140.             Str_Source = Str_Source.Replace(" """);  
    141.             //判断最后一位是否是0x16  
    142.             if (Str_Source != "")  
    143.             {  
    144.                 if (Str_Source.Substring(Str_Source.Length - 2, 2) == "16")  
    145.                 {  
    146.                     //如果符合这一步再进行下边的操作 下边进行判断是否位数是偶数  
    147.                     if (Str_Source.Length % 2 == 0)  
    148.                     {  
    149.                         //位数肯定是可以被整除的  
    150.                         string Str_Part = Str_Source.Substring(12, Str_Source.Length - 12 - 4);//需要进行校验位计算的字符串  
    151.                         if (FunctionGetSum(Str_Part).ToUpper() == Str_Source.Substring(Str_Source.Length - 4, 2).ToUpper())  
    152.                         {  
    153.                             //这个地方忘了区分大小写了 失误失误  
    154.                             //如果需要进行校验位计算的数据和计算出来的校验位一致才证明是正确的 试试吧  
    155.                             b_Correct = true;  
    156.                         }  
    157.                     }  
    158.                 }  
    159.             }  
    160.             return b_Correct;  
    161.         }  
    162.         /// <summary>  
    163.         /// 是一个循环,如果没有接受到需要的数据继续等待直到等到超时时间为止  
    164.         /// </summary>  
    165.         /// <param name="obj"></param>  
    166.         private void WaitRec(object obj)  
    167.         {  
    168.             WaitRec wr = (WaitRec)obj;  
    169.             bool b = false//这个布尔型的标识主要用来标识是否已经接收到返回值  
    170.             int Int_SpendAlready = 0; //当前已经消耗的时间  
    171.             for (int i = 0; i < wr.time_To_Timeout / wr.second; i++)  
    172.             {  
    173.                 if (FunctionGetCmdCorrect(strTemp) == true)  
    174.                 {  
    175.                     b = true;  
    176.                     break;  
    177.                 }  
    178.                 else  
    179.                 {  
    180.                     //返回的数据strTemp到目前为止还没有符合376.1规则的要求  
    181.                     for (int j = 0; j < wr.second; j++)  
    182.                     {  
    183.                         Thread.Sleep(1000);  
    184.                         Int_SpendAlready++;  
    185.                         //这里的意思是在前台的UI上边展示每次的超时时间和已经消耗的时间  
    186.                         //Application.OpenForms["Frm_JZQMYPLGX"].Controls.Find("Lbl_Wait", true)[0].Text = "当前耗时:" + Int_SpendAlready + "秒 " + "\r\n超时时间:" + wr.time_To_Timeout + "秒";  
    187.                         if (FunctionGetCmdCorrect(strTemp) == true)  
    188.                         {  
    189.                             //自己定义个函数用来判断返回的数据是否符合要求  
    190.                             b = true;  
    191.                             break;  
    192.                         }  
    193.                         else  
    194.                         {  
    195.                             b = false;  
    196.                             continue;  
    197.                         }  
    198.                     }  
    199.                 }  
    200.             }  
    201.             #region 执行完操作之后的程序  
    202.             if (b == true)  
    203.             {  
    204.                 action(strTemp);  
    205.             }  
    206.             else  
    207.             {  
    208.                 sp.Close();  
    209.                 TimeOutAction("操作时间" + wr.time_To_Timeout + "秒已到,请检查报文!");  
    210.             }  
    211.             #endregion  
    212.         }  
    213.         public void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)  
    214.         {  
    215.             try  
    216.             {  
    217.                 string currentline = ""; ;  
    218.                 byte[] lAryBytes = new byte[sp.ReadBufferSize];//这就是接收到的数据二进制文件  
    219.                 int lIntLen = sp.Read(lAryBytes, 0, lAryBytes.Length);  
    220.                 if (lIntLen > 0)  
    221.                 {  
    222.                     byte[] lAryData = new byte[lIntLen];  
    223.                     for (int i = 0; i < lIntLen; i++)  
    224.                     {  
    225.                         lAryData[i] = lAryBytes[i];  
    226.                     }  
    227.                     currentline = ByteToString(lAryData);//转化为16进制数显示  
    228.                     //strTemp += currentline; //2014年10月21日我把程序修改了一下改成直接返回接收到的数据  
    229.                     //这个地方需要修改一下 如果当前接收到的数据已经符合了376.1规约的要求,则进行提示  
    230.                     //action(currentline);//这里是把接收到的数据反应到前台  
    231.                     //2014年10月27日修改程序如果当前接收到的数据已经可以满足要求则推送到前天,若是不能满足要求则继续等待  
    232.                     if (FunctionGetCmdCorrect(currentline) == true)  
    233.                     {  
    234.                         strTemp += currentline;  
    235.                     }  
    236.                     else  
    237.                     {  
    238.                         //如果没有满足规约要求则进行等待  
    239.                         strTemp += currentline;  
    240.                     }  
    241.                 }  
    242.             }  
    243.             catch (Exception ex)  
    244.             {  
    245.                 //MessageBox.Show(, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Information);  
    246.                 Console.WriteLine(ex.Message.ToString() + "请检查指令流!");  
    247.             }  
    248.         }  
    249.         public void Close()  
    250.         {  
    251.             sp.Close();  
    252.         }  
    253.         ///  <summary>    
    254.         /// 字符数组转字符串16进制    
    255.         ///  </summary>    
    256.         ///  <param name="InBytes"> 二进制字节 </param>    
    257.         ///  <returns>类似"01 02 0F" </returns>    
    258.         public string ByteToString(byte[] InBytes)  
    259.         {  
    260.             string StringOut = "";  
    261.             foreach (byte InByte in InBytes)  
    262.             {  
    263.                 StringOut = StringOut + String.Format("{0:X2}", InByte) + " ";  
    264.             }  
    265.             return StringOut.Trim();  
    266.         }  
    267.         ///  <summary>    
    268.         /// strhex 转字节数组    
    269.         ///  </summary>    
    270.         ///  <param name="InString">类似"01 02 0F" 用空格分开的  </param>    
    271.         ///  <returns> </returns>    
    272.         public byte[] StringToByte(string InString)  
    273.         {  
    274.             string[] ByteStrings;  
    275.             ByteStrings = InString.Split(" ".ToCharArray());  
    276.             byte[] ByteOut;  
    277.             ByteOut = new byte[ByteStrings.Length];  
    278.             for (int i = 0; i <= ByteStrings.Length - 1; i++)  
    279.             {  
    280.                 ByteOut[i] = byte.Parse(ByteStrings[i], System.Globalization.NumberStyles.HexNumber);  
    281.             }  
    282.             return ByteOut;  
    283.         }  
    284.         ///  <summary>    
    285.         ///  strhex转字节数组    
    286.         ///  </summary>    
    287.         ///  <param name="InString">类似"01 02 0F" 中间无空格 </param>    
    288.         ///  <returns> </returns>    
    289.         public byte[] StringToByte_2(string InString)  
    290.         {  
    291.             byte[] ByteOut;  
    292.             InString = InString.Replace(" """);  
    293.             try  
    294.             {  
    295.                 string[] ByteStrings = new string[InString.Length / 2];  
    296.                 int j = 0;  
    297.                 for (int i = 0; i < ByteStrings.Length; i++)  
    298.                 {  
    299.                     ByteStrings[i] = InString.Substring(j, 2);  
    300.                     j += 2;  
    301.                 }  
    302.                 ByteOut = new byte[ByteStrings.Length];  
    303.                 for (int i = 0; i <= ByteStrings.Length - 1; i++)  
    304.                 {  
    305.                     ByteOut[i] = byte.Parse(ByteStrings[i], System.Globalization.NumberStyles.HexNumber);  
    306.                 }  
    307.             }  
    308.             catch (Exception ex)  
    309.             {  
    310.                 throw new Exception(ex.Message);  
    311.             }  
    312.             return ByteOut;  
    313.         }  
    314.         ///  <summary>    
    315.         /// 字符串 转16进制字符串    
    316.         ///  </summary>    
    317.         ///  <param name="InString">unico </param>    
    318.         ///  <returns>类似“01 0f” </returns>    
    319.         public string Str_To_0X(string InString)  
    320.         {  
    321.             return ByteToString(UnicodeEncoding.Default.GetBytes(InString));  
    322.         }  
    323.     }  
    324. }  


    [csharp]  view plain  copy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.ComponentModel;  
    4. using System.Data;  
    5. using System.Drawing;  
    6. using System.Linq;  
    7. using System.Text;  
    8. using System.Windows.Forms;  
    9. using System.IO.Ports;  
    10. using System.Threading;  
    11.   
    12. namespace 串口测试  
    13. {  
    14.     public partial class FrmMain : Form  
    15.     {  
    16.         public FrmMain()  
    17.         {  
    18.             InitializeComponent();  
    19.         }  
    20.         /*程序开发说明: 
    21.          * 编写日期:2014年10月17日 
    22.          * 开发人员:孙小聪 
    23.          * 开发目的:我想自己优化一个类实现一种什么效果呢就是我下发一个数据之后 三个参数: 
    24.          * 1.步长值 
    25.          * 2.超时时间 
    26.          * 3.通讯规约 
    27.          * 数据下发之后 每隔单位时间去判断一下当前接收到的数据,然后按照指定的规约类型去判断当前返回的数据是否正确符合规约要求。 
    28.          * 若是符合规约要求返回一个True 不需要继续等待 
    29.          * 若是返回数据不符合要求继续等待。 
    30.          * 继续等待到超时时间退出进行提示 
    31.          * 若是没有超过超时时间继续等待到超时时间为止。听着很简单的一个功能真是实现的时候就会发现不是那么简单,我把这个类完善一下!  
    32.          * 今天下午的主要功能就是完成了。这个情况还是很复杂的,我现在手头这个程序就是用来判断是否有返回值,但是我们真正使用的情况是 
    33.          * 首先不一定一帧数据就能返回回来。而且返回来之后我们要判断完整性 
    34.          */  
    35.         #region 初始化端口  
    36.         private void InitCOM()   
    37.         {  
    38.             cmbCOM.Items.Clear();  
    39.             string[] strArr = SerialPort.GetPortNames();  
    40.             foreach (string one in strArr)  
    41.             {  
    42.                 cmbCOM.Items.Add(one);  
    43.             }  
    44.             //cmbCOM.SelectedIndex = strArr.Length > 0 ? 0 : -1;  
    45.             cmbCOM.SelectedIndex = 1;  
    46.         }  
    47.         #endregion  
    48.         //接口类  
    49.         SerialPortHelper sp;  
    50.         /// <summary>  
    51.         /// 初始化信息  
    52.         /// </summary>  
    53.         /// <param name="sender"></param>  
    54.         /// <param name="e"></param>  
    55.         private void Form1_Load(object sender, EventArgs e)  
    56.         {  
    57.             Control.CheckForIllegalCrossThreadCalls = false;  //允许控件跨线程调用 当然这是不推荐的,后期使用中还是应该使用委托  
    58.             InitCOM();  
    59.             cmbBTL.SelectedIndex = 4;  
    60.             cmbSJW.SelectedIndex = 3;  
    61.             cmbTZW.SelectedIndex = 0;  
    62.             cmbXYW.SelectedIndex = 2;  
    63.         }  
    64.         #region 清空文本  
    65.         private void btnClearSend_Click(object sender, EventArgs e)  
    66.         {  
    67.             txtSend.Text = "";  
    68.         }  
    69.         private void btnClearRec_Click(object sender, EventArgs e)  
    70.         {  
    71.             txtReceive.Text = "";  
    72.         }  
    73.         #endregion  
    74.         #region 打开关闭串口  
    75.         private void btnState_Click(object sender, EventArgs e)  
    76.         {  
    77.             if (btnState.Text == "打开串口")  
    78.             {  
    79.                 Parity py= cmbXYW.Text=="None"?Parity.None:  
    80.                     cmbXYW.Text=="Odd"?Parity.Odd:cmbXYW.Text=="Even"?Parity.Even:  
    81.                     cmbXYW.Text=="Mark"?Parity.Mark:Parity.Space;  
    82.                 sp = new SerialPortHelper(cmbCOM.Text,int.Parse(cmbBTL.Text),  
    83.                     int.Parse(cmbSJW.Text),cmbTZW.Text=="1"?StopBits.One:cmbTZW.Text=="1.5"?StopBits.OnePointFive:StopBits.Two,  
    84.                     py, ReceMeg, FunctionTimeOutAction);  
    85.                 btnState.Text = "关闭串口";  
    86.             }  
    87.             else   
    88.             {  
    89.                 sp.Close();  
    90.                 sp = null;  
    91.                 btnState.Text = "打开串口";  
    92.             }  
    93.         }  
    94.         /// <summary>  
    95.         /// 超时之后执行的操作  
    96.         /// </summary>  
    97.         /// <param name="str"></param>  
    98.         public void FunctionTimeOutAction(string str)  
    99.         {  
    100.             MessageBox.Show("数据接收超时!请准备重新发送","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);  
    101.             return;  
    102.         }  
    103.         #endregion  
    104.         /// <summary>  
    105.         /// 接收的数据  
    106.         /// </summary>  
    107.         /// <param name="str"></param>  
    108.         public void ReceMeg(string str)   
    109.         {  
    110.             txtReceive.Text += str;  
    111.         }  
    112.         private void btnSend_Click(object sender, EventArgs e)  
    113.         {  
    114.             if (this.btnState.Text == "打开串口")  
    115.             {  
    116.                 //这个时候不能用  
    117.                 MessageBox.Show("发送数据之前请先打开串口!""提示", MessageBoxButtons.OK, MessageBoxIcon.Information);  
    118.                 return;  
    119.             }  
    120.             else  
    121.             {  
    122.                 sp.SendData(this.txtSend.Text.Trim(),1,10);  
    123.             }  
    124.         }  
    125.     }  
    126. }  

    展开全文
  • 自己写的串口通讯帮助类,实现应答机制,通讯中发送一条指令会等待应答,同步异步都有
  • STM32 串口DMA超时

    2021-12-28 14:52:04
    本文用来记录学习中的问题,不涉及其他 //主函数 int main(void) { ......... __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//开启空闲中断服务 HAL_UART_Receive_DMA(&huart1,rebuff,100);...//错误处理回调函数

    本文用来记录学习中的问题,不涉及其他

    //主函数
    int main(void)
    {
    	.........
      	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);//开启空闲中断服务
      	HAL_UART_Receive_DMA(&huart1,rebuff,100);//开启接收
      	while (1)
      	{
    		..........
      	}
    }
    
    //中断服务
    void USART1_IRQHandler(void)
    {
    	if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET) //空闲中断判断   __HAL_UART_GET_FLAG获取指定中断
    	{
    		uint8_t len=0;//定义长度
    		__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除空间中断
    		//之后这里可以多次判断以便排除干扰
    		HAL_UART_DMAStop(&huart1);//停止DMA
    		len=100-__HAL_DMA_GET_COUNTER(huart1.hdmarx);//获取已接收长度
    		{//括号内可以到处理函数中
    			xxxx(len);//处理函数
    			HAL_UART_Receive_DMA(&huart1,rebuff,100);//重新开启接收
    		}	
    	}
      HAL_UART_IRQHandler(&huart1);
    }
    

    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);//发送完成回调函数
    void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);//发送完成过半 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//接收完成回调函数 void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//接收完成过半 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);//错误处理回调函数

    展开全文
  • C# 带超时处理串口通讯模型

    千次阅读 2018-07-13 17:22:56
    串口发送与接收数据的模型,带超时功能,示意图如下:其中,额外等待是可有可无的。代码如下(已精简,只剩最主要的)。其中串口类的名字是Global.spusing System; using System.Collections.Generic; using System....

    串口发送与接收数据的模型,带超时功能,示意图如下:


    其中,额外等待是可有可无的。

    代码如下(已精简,只剩最主要的)。其中串口类的名字是Global.sp

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Threading;
    using System.Diagnostics;
    
    namespace Test01
    {
        public partial class FormMain : Form
        {
    
            static System.Timers.Timer timerTOA; //timerTimeOut A 总体观察(暂无数据时)
           
            byte[] buff; //临时数组,存放每次的返回结果
            
            int delayTime; //允许的超时次数
    
            int offset; //当前偏移量
            int bytesNum; //本次读取到的数量
          
            public FormMain()
            {
                InitializeComponent();
    
                initData();
                bindEvent();
                send();
            }
    
            public void initData()
            {
                timerTOA = new System.Timers.Timer();
                timerTOA.Interval = 100; //100ms超时      
                timerTOA.AutoReset = false;
                timerTOA.Enabled = false;
    
                buff = new byte[1500];
                offset = 0;
                bytesNum = 0;
                delayTime = 0;
            }
    
            public void bindEvent()
            {
                timerTOA.Elapsed += new System.Timers.ElapsedEventHandler(end100ms);
                Global.sp.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(spDataReceived);
            }
    
            //串口发送
            private void send()
            {
                byte[] order = "xxxxx";
                sendOrder(order); //sendOrder不再展开
            }
    
            /// <summary>
            /// timerTOA的100ms结束时触发的方法
            /// </summary>
            private void end100ms(Object sender, EventArgs e)
            {
                bytesNum = Global.sp.BytesToRead;
    
                if (bytesNum == 0 && delayTime <= 10) //再给10次机会
                {
                    delayTime++;
                    timerTOA.Start();
                }
                else
                {
                    try
                    {
                        if (Global.sp.BytesToRead > 0)
                        {
                            Global.sp.Read(buff, 0, Global.sp.BytesToRead);
                        }
                    } 
                    catch (Exception ex)
                    {
                        //错误处理...
                    }
                   
                    this.BeginInvoke(new EventHandler(analyze));
                } 
    
            }
    
            /// <summary>
            /// 串口收到下位机返回的数据时触发的方法
            /// </summary>
            public void spDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
                timerTOA.Stop();
                timerTOA.Start();
            }
    
            /// <summary>
            /// 针对本次数据进行分析处理
            /// </summary>
            public void analyze(object sender, EventArgs e)
            {
                //处理数据...
    			//...
                
    			//处理完毕,开始下一次循环(如果需要的话)
    			reset();
    			//继续...
    			//send()
            }
    
            /// <summary>
            /// 重置一些内容
            /// </summary>
            public void reset()
            {
                buff = new byte[1500];
                offset = 0;
                bytesNum = 0;
                delayTime = 0;
            }
        }
    }
    

    展开全文
  • 关于串口C#接受数据,Serialport类里面发布了SerialDataReceivedEventHandler这个委托,并建立了SerialPort.DataReceived事件,我们可以在窗口主程序中进行事件绑定,绑定到我们对数据的函数。可以简单理解为串口一...
  • 幸好Linux的串口自己就带有超时机制。Linux下使用termios.h中的的接口进行串口设置。使用termios.h的接口进行超时设置,主要是配置 VTIME 和 VMIN 两个字段。其中VTIME指定了等待的时间(timeout=VTIME*100ms),VMIN...
  • 系列文章目录 ...1.在#3章基础上,中断定时+超时接收 2.增加CRC校验方式及接收应答处理 提示:以下是本篇文章正文内容,下面案例可供参考 一、场景 示例: 主机下发命令,从机解析并应答,CRC校验 二、编程
  • 接收到一帧数据(1Byte)后,串口中断服务函数将定时器T0计数清0(类似喂狗),并创建一个计数标志 一帧数据(1Byte)长度约为1.04ms[9600bps,1,0,1]。当串口中断数据接收完毕后,短时间无有效数据接收并进入中断...
  • 单片机串口超时接收机制

    千次阅读 2019-03-06 14:25:17
    在使用单片机的时候串口是与外界通讯最常用的一种...在处理接收的时候超时处理是一种常见的方法。 参考代码如下: //串口0 中断函数 void UART0_Isr() interrupt 4 using 1 { if (TI) { busy0 = 0; TI = 0; ...
  • 串口通信之超时

    2021-03-01 08:30:55
    超时分串口超时串口超时,主要是读超时,即ReadTimeout与Read方法之间的超时。下面谈谈他们之间的意义和实现。Read方法是阻塞的,它一直在读串口接收缓冲区中的数据,如果接收缓冲区有数据,Read方法则返回一...
  • Android串口通讯, 支持发送数据回调, 支持并发处理, 自定义协议, CRC校验, 自动粘包, 自动去除冗余的干扰数据 是 项目的二次封装 支持多线程并发的同时多种设备协议 引入 Step 1. Add the JitPack repository to ...
  • 完善的微服务基础设施 Service Mesh通过将微服务通信下沉到基础设施层,屏蔽了微服务处理各种通信问题的复杂度,可以看成是微服务之间的抽象协议层,抽象层面可以看成是TCP/IP协议栈的一部分。对于微服务的开发者来...
  • android串口通讯

    千次阅读 2018-07-20 17:44:24
    在google的demo中,只是使用的c语音去打开串口,操作串口读取数据还是使用java 的IO流进行读取,IO流在read的时候是没有超时处理的,所有会造成串口卡住。 最新从新用jni使用c重新写了串口调用,因为是用c取里的...
  • linux 串口通讯

    2021-05-13 03:40:23
    配置串口POSIX终端接口POSIXPOSIX是Portable Operating System Interface(可移植操作系统界面)的缩写,而X则表明其对Unix API的传承。WindowsNT和现代UNIX都支持POSIX接口。很多系统都支持POSIX终端(串口)接口。程序...
  • C++之串口通讯

    千次阅读 2020-05-30 23:00:58
    串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现...
  • C++ 串口通讯

    2021-06-02 16:39:53
    MAP() // CSerialPortTestDlg 消息处理程序 BOOL CSerialPortTestDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT...
  • 华大HC32F460之串口超时中断使用

    千次阅读 2021-10-29 18:44:15
    2)串口接收使用DMA方案,再使用定时器超时来断帧,这样使用一般情况下没有问题,但是 如果作为从机的时候,如果要求ACK在特别短的时间里(比如20ms以内)去响应,就会有一定的风险存在; 3)串口接收使用DMA方案...
  • modbus串口通讯C#

    千次阅读 2019-03-12 15:17:00
    题目: modbus串口通讯 主要内容如下: 1、实现使用modbus通讯规约的测试软件; 2、具有通信超时功能; 3、分主站从站,并能编辑报文、生成报文等; 4、计算发送报文次数,接收报文次数,失败通信次数; 5、对接收的...
  • 1,前言开发环境:在 Visual Studio 2017,.NET Core 2.x串口通讯用于设备之间,传递数据,物联网设备中广泛使用串口方式连接通讯,物联网通讯协议...
  • 文章目录01、串口通讯02、 CreateFile API03、串口通讯Demo 01、串口通讯 在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信。串口通信方便易行,应用广泛。 RS232通信协议是目前最...
  • QT串口延时接收数据

    千次阅读 2020-07-21 09:25:37
    处理思路:创建两个槽函数(SLOT),当串口有数据应答时系统会给一个 readyRead()信号,用槽函数接收一个信号,并处理。在进入到这个槽函数后设置一个定时,当定时走完会有一个timeout()信号,用另一个槽函数处理...
  • 系列文章目录-串口通讯 /C51串口通讯调试目录:/ 第5章:#C51串口通讯5-#一串数据#中断定时+超时接收+接收应答+CRC校验 第4章:#C51串口通讯4-#一串数据#中断即时解析用户自定义协议(握手接收应答) 第3章:#C51串口...
  • 项目开发中,在安装linux系统的ARM9板上,需要实时检测USB口与Windows...串口通讯中断端口地址也不会消失,因此,只有通过在一定时间内检测端口的读写状态来判断串口通讯是够正常,如超时则认为连接断开。首先,打...
  • 在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。如果在指定的时间内没有读出或写入指定数量的字符,那么ReadFile或WriteFile的操作就会结束。要查询当前的超时设置应调用GetCommTimeouts函数,该函数会...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,560
精华内容 1,824
关键字:

串口通讯超时处理