This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C129ENCPDT:UART 接口在实际数据包的开头接收第一个字节#39;0&#39

Guru**** 1794070 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/572226/tm4c129encpdt-uart-interface-receiving-first-byte-0-at-the-beginning-for-actual-data-packet

器件型号:TM4C129ENCPDT

如果错误、请忽略、是否有人会帮助我解决使用 UART 接收数据、 通过 UART1发送命令(波特率115200)以及接收响应的问题。 命令 SEND 和来自另一个系统的响应数据是正确的(使用 com 端口分析响应),但在将数据字节接收到阵列时,第一个字节将作为零接收。 一些帮助是非常有利的。 下面是相同的代码。

谢谢  

UART1_Send ((uint8_t *) Receiver_Command、5);                        //发送命令  
///----------------------------------------------
DELAY_Milli_Sec (6);//接收接收接收器响应的延迟6ms //等待收集数据和其他器件响应的时间  

____________________________________________________________________________________________________________________________________________________________

void delay_Milli_Sec (uint32_t delay_value)

uint32_t Timer_Count;

Timer_Count =(120000 * DELAY_VALUE);//以毫秒为单位计算值

ROM_IntEnable (INT_TIMER3A);
ROM_TimerIntEnable (TIMER3_base、TIMER_TINA_TIMEOUT);
ROM_TimerLoadSet (TIMER3_base、INT_TIMER3A、Timer_Count);
ROM_TimerEnable (TIMER3_base、TIMER_A);
while (DelaySet_Flag = 0)

//等待延迟

DelaySet_FLAG = 0;
ROM_TimerIntDisable (TIMER3_base、TIMER_A);//禁用 Timer3中断
ROM_TimerDisable (TIMER3_base、TIMER_A);//禁用 Timer3

____________________________________________________________________________________________________________________________________________________________

无效
UART1_IntHandler (空)

Interrupt_Flag =(Interrupt_Flag | uart1_interrupt);//全局变量
Receive_Wait_Flag =(Receive_Wait_Flag | uart1_interrupt);//全局变量>> uart1中断>>接收等待标志置1
静态 uint32_t ui32Status;//局部变量>>中断状态
静态 uint8_t uart1_data;
静态 uint32_t Max_Byte=34;//最初设置为34字节
静态 uint32_t CURRENT_Char = 0;//数组中的第一个数据位置
ui32Status = ROM_UARTIntStatus (UART1_base、true);//获取中断状态。
ROM_UARTIntClear (UART1_base、ui32Status);//清除已发出的中断。
while (ROM_UARTCharsAvail (UART1_base))//循环、此时接收 FIFO 中有字符。

uart1_data = ROM_UARTCharGetNonBlocking (UART1_base);//从 UART1读取下一个字符

if (Current_If_If <Max_byte)

uart1_data_packet[curry_Char++]= uart1_data;//将每个字节读取到 uart1_data_packet 数组

if ((uart1_data_packet[0]= 0xf0)&&(uart1_data_packet[1]= 0xf0)//检查 Receiver_Command 消息 ID 以设置响应数据的字节计数

max_Byte=34;//根据命令消息 ID 更新计数值
if (Current_Char==33)

CURRENT_CHAR = 0;//将数组清除为0位置
Receive_Wait_Flag &= 0xFD;


否则、如果((uart1_data_packet[0]= 0xAA)&&(uart1_data_packet[1]= 0x79))

max_Byte=4;//根据命令消息 ID 更新计数值
if (Current_Char==3)

CURRENT_CHAR = 0;//将数组清除为0位置
Receive_Wait_Flag &= 0xFD;


其他

CURRENT_CHAR=0;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    库里安

    您正在使用 ROM_UARTCharGetNonBlocking (UART1_BASE)读取 FIFO。 尽管您确实等待中断进入例程、但可能是由于不同的原因发生了中断、此时 FIFO 中没有任何内容。
    一些建议:
    -缩短 IRS:尝试在 IRS 内简单启用某种标志,并在外部处理命令。
    -在 IRS (IRS)内部、在每个代码块之前检查中断的原因。
    谢谢
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    收到命令/字符串后、将其复制到另一个缓冲区、以便在主代码中进行评估。 不要使用中断接收缓冲区。

    否则、在您检查缓冲区内容时、您将通过 UART 中断例程覆盖缓冲区内容。 其影响将介于"奇怪"和"严重破坏"之间。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢 Bruno 和 F.m,

    我对 ISR 进行了如下修改、即使结果相同。  

    ____________________________________________________________________________________________

    无效

    UART1_IntHandler (空)
    {  
    Interrupt_Flag =(Interrupt_Flag | uart1_interrupt);//全局变量  
    静态 uint32_t ui32Status;//局部变量>>中断状态  
    静态 uint8_t uart1_data;

    静态 uint8_t CURRENT_Char = 0;  

    ui32Status = ROM_UARTIntStatus (UART1_base、true);//获取中断状态。
    ROM_UARTIntClear (UART1_base、ui32Status);//清除已发出的中断。  
    while (ROM_UARTCharsAvail (UART1_base))//循环、此时接收 FIFO 中有字符。

    uart1_data = ROM_UARTCharGetNonBlocking (UART1_base);//从 UART1读取下一个字符  
    uart1_data_packet[curry_Char++]= uart1_data;

    ____________________________________________________________________________________________

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    请告诉我们您是如何配置 UART 中断的。 通常、在 UART 中断中、您必须检查发生的具体中断类型-接收中断或发送中断类型或其他类型中断、并在中断例程中采用相应的路径。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这里还有其他一些没有报告的东西、也没有执行(IMHO)。

    [报价]我正在通过 UART1 (波特率115200)发送命令并接收响应。[/报价]

    这些命令的外观如何,即它们的长度如何,起始字符和终止字符的外观如何?

    在(最后一个) UART 接收处理程序代码中、您无条件地将接收到的字节写入接收缓冲区、并使索引递增。 这不是很好的防御性编码。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢 f.m、这就是答案。

    预期的字节为4字节或34字节数据包。
    以下代码可解决此问题。 我衷心感谢 Bruno、f.m、Petrei 和 TI 团队。
    ____________________________________________________________________________________________
    无效
    UART1_IntHandler (空)

    Interrupt_Flag =(Interrupt_Flag | uart1_interrupt);//全局变量
    静态 uint32_t ui32Status;//局部变量>>中断状态
    如果((Current_Char == 34)||(Current_Char == 4))

    CURRENT_CHAR = 0;//数组中的第一个数据位置

    ui32Status = ROM_UARTIntStatus (UART1_base、true);//获取中断状态。
    ROM_UARTIntClear (UART1_BASE、ui32Status);//清除已发出的中断。
    while (ROM_UARTCharsAvail (UART1_base))//循环、此时接收 FIFO 中有字符。

    uart1_DATA_packet[CURRENT_CHAR++]=ROM_UARTCharGetNonBlocking (UART1_base);//从 UART1读取下一个字符


    ____________________________________________________________________________________________
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="KurianThomas"]... 以下代码可解决此问题。

    实际上、我认为不是。

    [引用 user="KurianThomas"]if (Current_Char = 34)||(Current_Char = 4)

    CURRENT_CHAR = 0;//数组中的第一个数据位置
    }[/报价]

    这会将索引重置为第5个字符之后的数组开头(在假定的结束字符之后)、从而有效清理最后接收到的命令。 这是问题的第一个,不是吗?

    如果您的命令始终为4字节或34字节、则永远不会以这种方式收到34字节命令。

    我看不到您是如何将收到的命令传递给主代码的。 直接处理由异步事件(中断)修改的数据(数组)肯定会失败。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    库里安

    这可能听起来很累、但请稍等片刻:

    完全分隔您的代码:

    1) 1)一个部分负责接收来自 UART 端口的任何内容(在生命周期的后期、您将希望它通过任何类型的串行 COMM 层接收任何内容、但这是一个更复杂的情况)。 该部分将接收到的字节存储到循环缓冲区中、并将最后一个填充位置递增。

    2) 2)一个不同的段对缓冲区的内容进行解析、并确定是否接收到一些有效的命令或消息。

    硬编码解决方案、如"期望固定消息长度"、"期望特定字节序列"、而是在您的协议级别(在解析器内部)实施、而不是在通信级别实施。

    保持持久、毫不犹豫地回声!

    布鲁诺

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用用户="Bruno Saraiva"]

    这可能听起来很累、但请稍等片刻:

    (笑声)

    保持持久、毫不犹豫地回声!

    [/报价]

    您可以在您的老板的雷达下面免费查看代码... ;-)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢、我就是这样。 我有一组定义的通信协议和一个由计时器控制的硬实时系统。

    希望您已经注意到在前一个案例中、"Current_Char"是静态的。  

    请在下面找到工作代码:

    //
    //
    // UART1中断处理程序。
    //
    //
    无效
    UART1_IntHandler (空)

    Interrupt_Flag =(Interrupt_Flag | uart1_interrupt);//全局变量
    静态 uint32_t ui32Status;//局部变量>>中断状态
    如果((Current_Char == 34)||(Current_Char == 4))

    CURRENT_CHAR = 0;//数组中的第一个数据位置

    ui32Status = ROM_UARTIntStatus (UART1_base、true);//获取中断状态。
    ROM_UARTIntClear (UART1_base、ui32Status);//清除已发出的中断。
    while (ROM_UARTCharsAvail (UART1_base))//循环、此时接收 FIFO 中有字符。

    uart1_DATA_packet[CURRENT_CHAR++]= ROM_UARTCharGetNonBlocking (UART1_base);//从 UART1读取下一个字符

    ____________________________________________________________________________________________

    IF (Interrupt_Flag 和 uart1_interrupt)

    INTERRUPT_Flag &= 0xFD;//清除 UART1中断标志
    ///----------------------------------------------
    //
    //在发送命令后收集接收器响应状态
    //
    接收器状态响应.Header1 = uart1_DATA_packet[0];
    接收器状态响应.Header2 = uart1_data_packet[1];
    接收器状态响应代码= uart1_data_packet[2];
    接收器状态响应。模拟增益磅= uart1_data_packet[3];
    接收器状态响应。模拟增益 HB = uart1_DATA_PACKE[4];
    接收器状态响应时间磅= uart1_data_packet[5];
    RECEIVER_Status_RESPONSE.TIME_HB = uart1_DATA_PACKE[6];
    接收器状态响应状态= uart1_data_packet[7];
    接收器状态响应。Angle _X_LB = uart1_DATA_PACKE[8];
    RECEIVER_Status_RESPONSE.Angle_X_HB = uart1_DATA_PACKE[9];
    接收器状态响应。角度 Y 磅= uart1_data_packet[10];
    RECEIVER_Status_RESPONSE.Angle_Y_HB = uart1_DATA_PACKE[11];
    RECEIVER_Status_RESPONSE.Quad_A_LB = uart1_DATA_PACKE[12];
    接收器状态响应。Quad_A_MidB = uart1_data_packet[13];
    接收器状态响应1 = uart1_data_packet[14];
    接收器状态响应保留2 = uart1_data_packet[15];
    接收器状态响应。Quad_B_LB = uart1_DATA_PACKE[16];
    接收器状态响应。Quad_B_MidB = uart1_data_packet[17];
    接收器状态响应保留3 = uart1_data_packet[18];
    接收器状态响应保留4 = uart1_data_packet[19];
    RECEIVER_Status_RESPONSE.Quad_C_LB = uart1_DATA_PACKET[20];
    接收器状态响应。Quad_C_MidB = uart1_data_packet[21];
    接收器状态响应.Temp_lb = uart1_data_packet[22];
    RECEIVER_Status_RESPONSE.Temp_HB = uart1_DATA_PACKE[23];
    接收器状态响应。Quad_D_LB = uart1_DATA_PACKE[24];
    接收器状态响应。Quad_D_MidB = uart1_DATA_PACKE[25];
    接收器状态响应 HV_LB = uart1_DATA_PACKE[26];
    接收器状态响应 HV_HB = uart1_DATA_PACKE[27];
    接收器状态响应。Switch_1_2_positions = uart1_data_packet[28];
    接收器状态响应。Switch_3_4_POSITIONS = uart1_data_packet[29];
    接收器状态响应。Switch_5_Position = uart1_data_packet[30];
    接收器状态响应校验和= uart1_data_packet[31];
    接收器状态响应页脚1 = uart1_data_packet[32];
    接收器状态响应页脚2 = uart1_data_packet[33];

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    不知怎么说、我期待的是这样的东西。

    [引用 user="KurianThomas">希望您注意到在前一个案例中、"curry_Char"是静态的。  [/报价]

    它与索引无关、而与数据(数组)本身有关。 当您处理上一个数据包时,如果新数据包到达,会发生什么情况? 我怀疑这种情况会经常发生、因为另一个错误:

    [引用 user="KurianThomas"] if (current_Char == 34)||(...

    我将使用以下方法:

    • 使用大于最大预期数据包的缓冲区(我将使用40字节、大小可被4除)
    • 检查起始字符(Header1)、如果检测到索引、则将其重置为零(并照常存储该字符)
    • 检查终止字符(脚注2)、如果找到、则复制缓冲区+设置主代码的标志
    • 存储所有其他字符(并使索引计数器递增)
    • 检查缓冲区溢出(索引)、并重置为零-这应该会自动丢弃损坏的数据包

    但是、如前所述、使用来自主代码和中断代码的相同数据数组将最终在您的脸上熔断。 请使用副本。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常感谢、这种方法非常可靠、乐观
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    "乐观"在这里是一个很好的标签。
    您应始终假设字符可能会丢失、数据包会损坏。 并以稳健的方式进行处理、从而在不进行干预/复位的情况下恢复通信(所谓的"雨天场景")。