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.

[参考译文] CCS/EK-TM4C129EXL:UART 数据丢失

Guru**** 2482225 points
Other Parts Discussed in Thread: EK-TM4C129EXL, TM4C129ENCPDT

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/723446/ccs-ek-tm4c129exl-uart-data-loss

器件型号:EK-TM4C129EXL
主题中讨论的其他器件: TM4C129ENCPDT

工具/软件:Code Composer Studio

您好!

我将 EK-TM4C129EXL 评估套件与 CCS 7.0配合使用

我需要将 一个段落(字符数组)从我的 PC 传输到控制器、反之亦然。 为此、我计划使用 UART 通信。

为了开始 UART 通信、我检查了 UART_echo 示例。 UART 中断处理程序中的代码如下所示:  

while (ROM_UARTCharsAvail (UART0_BASE))


//
//从 UART 读取下一个字符并将其写回 UART。
//
ROM_UARTCharPutNonBlocking (UART0_BASE、ROM_UARTCharGetNonBlocking (UART0_BASE));

/*注释  

//
//闪烁 LED 以显示字符传输正在发生。
//
GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0、GPIO_PIN_0);

//
//延迟1毫秒。 每个 SysCtlDelay 大约为3个时钟。
//
SysCtlDelay (g_ui32SysClock /(1000 * 3));

//
//关闭 LED
//
GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0、0);

*

首先、当我发送一个段落时、只有16到18个字符回显 并打印 在控制台屏幕上。

然后、我删除了 LED 闪烁逻辑、它在收到每个字符时通过注释进行闪烁。 现在、无论段落大小如何、整个段落都会得到回显和打印。 非常完美。

问题是、如果我再次尝试将传入字符存储 在 char 数组中、则只存储16 - 18个字符、并且非常不可靠。 我在 while 循环中使用以下代码将传入的数据存储在缓冲区中。

buf[i++]= ROM_UARTCharGetNonBlocking (UART0_BASE);

我需要收集数据并在主函数中进行处理。  

有些人建议进行 缓冲操作。 我甚至使用 UARTgets ()函数尝试过它。 我做不到。

缓冲 UART 操作的编程示例或 UARTgets ()函数的示例将大有帮助。 或者、我是否可以在不执行缓冲操作的情况下实现它?

注意:该段落将从我的 PC 发送到一个部分。  

感谢你能抽出时间。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    即使缓冲区中没有字符、"UARTCharGetNonBlocking"函数也始终立即返回。 如果可以在该函数中等待接收字符、则可以改用"UARTCharGet"。 否则、您可以检查函数 UARTCharGetNonBlocking 是否返回-1。 这意味着接收缓冲器为空。 另一种方法是调用 UARTCharsAvail(),并且仅在 UARTCharsAvail()返回"true"时调用 UARTCharGetNonBlocking()。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Bob。

    示例程序使用 UARTCharsAvail()函数作为 while 循环条件来获取一组传入的字符,并在它们出现时打印它们。 如下图所示、打印字符效果非常好。

    但在相同的条件下、如果我尝试将这些字符存储在缓冲器中、则仅存储16个字符。

    我将尝试使用 UARTCharGE()函数。

    在之间、TM4C129ENCPDT 数据表中提到 UART 接收 FIFO 只有16 x 12位深。 因此、在单个 UART 中断发生时接收一组字符(段落)肯定需要 UART 的缓冲操作、即使用 UARTgets 函数并维护内部缓冲区。

    遗憾的是、CCS 中没有缓冲 UART 操作示例或使用 UARTgets 函数的示例。 UART 缓冲操作中是否有任何示例?

    感谢你能抽出时间。

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

    我创建并附加了一个在缓冲模式下使用 UART 标准 IO 例程的项目。 我实际上遇到了一个问题。 UARTWrite 函数未按应有的方式终止 NULL 字符。 因此、此项目包含"uartstdio.c"的修改版本。 我将在下一个版本中记录该错误以进行修复。 使用"File"->"Import"并从附加的.zip 文件导入此项目。

    /cfs-file/__key/communityserver-discussions-components-files/908/EK_2D00_Buffered_5F00_uart_5F00_echo.zip

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

    感谢 Bob。

    我将尝试使用该代码。

    之间、根据您的代码、UARTgets 函数位于无限 while 循环内。 我尝试过类似的东西。

    我有一个要求、即主函数中将有一个无限 while 循环。

    只有当 UART 接收中断发生时、控制才能进入 UART 中断子例程

    传入的字符流 必须存储在缓冲区中。

    此外 、在 UART 中断函数内、我在 char 数组队列中对缓冲区数据进行排队、并返回到 main 中的无限 while 循环。

    在无限 while 循环中、我检查 char 数组队列中的数据。 如果队列中存在数据、我将对数据进行去队列处理。 否则、控制将在无限 while 环路中连续循环。

    当我在 UART 中断子例程中使用 UARTgets 函数时、我面临 UART 数据丢失不可靠的数据接收。

    是否有其他符合我要求的方法?

    再次感谢您的参与。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在缓冲模式下使用 UART 标准 IO 时,中断函数 UARTStdioIntHandler()负责接收字符并将其放入循环缓冲区。 这是一个不同于我在示例中创建的"UARTBuffer"的缓冲区。 此"内部"静态循环缓冲器的大小由"uartstdio.h"文件中的"UART_RX_buffer_size"定义。

    现在在 main()循环中,您需要从内部循环缓冲区中获取数据并对其进行处理。 问题是如何确定何时有一整套数据供处理。 如果传入字符串为 NULL 或以返回分隔、它们将存储为循环缓冲区中的 NULL 终止字符串。 对函数 UARTPeek (0)的调用可以确定是否已完全接收到以 null 结尾的字符串。 如果是、函数将返回该字符串中的字符数数量。 否则、该函数返回-1。 然后,可以使用 UARTgets ()从循环缓冲区中抓取字符串。

    如果您想在接收到一定数量的字符后处理传入数据,请使用函数 UARTRxBytesAvail()来查找已接收的字节数。 当该值是所需的字节数时,用 UARTgets ()来抓取它们,除非字符数组中包含 NULL 字符。 然后使用循环和 UARTgetc()。

    根据可用 RAM 设置内部循环缓冲区的大小、接收到的字符串的大小以及在您可以返回并处理下一个字符串之前可以接收的字符数。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您快速回复 Bob。

    首先回答您的问题、

    您如何确定您何时拥有一整套数据进行处理?

    我将通过 UART 以1秒或2秒或0.5秒等不规则间隔获取数据

    我将得到一个字符串行,格式为 ">abcdefghijklmnopqrstuvwxyz<"。 字符串的长度不是恒定的。 它每次都会变化。

    我已经查看 了 UARTStdioIntHandler()。 正如您所说的、它有一个循环缓冲器 g_pCUARTRxBuffer。 通过 UART 接收的每次数据都被附加到该缓冲区中、而不是被替换。

    我是否应该在获取数据并在单独的字符队列数组中对其进行排队之后每次清除缓冲区?

    清除循环缓冲区是否会影响某个位置?

    其次、您使用 UARTPeek 后跟 UARTgets 的想法似乎完全符合我的要求。

    我之前已经阅读过这些内容。 但是、由于缺少使用这些函数的示例程序、我跳过了这些示例程序。

    我不知道在哪里使用这两个函数(在主函数中或在 UART 中断函数中)、也不知道如何正确地构建这两个函数以实现可靠的数据接收。

    由于我的传入数据流以">"开始、以"<"结束、 因此 Shali 使用以下逻辑。

    MAIN ()

    while (1)

    if (UARTPeek ('<')!=-1)

    {UARTgets (buf、UARTPeek (' <'));    }  // I plan to use the length from the return value of UARTPeek('<')

    是否需要在 UART stdio 中断处理程序中使用 UARTPeek ('<')?

    谢谢、Bob。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这听起来像是一个很好的计划。 您无需重置循环缓冲区。 UARTgets ()函数向前移动"tail"指针、使循环缓冲区上的该部分再次可用。 唯一的问题是、您能够以最快的速度处理字符串、这样"头部"指针就不会超过"尾"指针。 缓冲区的大小应是可能的最长字符串的两倍。 目前、如果循环缓冲区已满、中断处理程序只丢弃传入的字符。 您可以通过在现有的"if (!RX_buffer_full)"中添加"else"语句来修改函数 UARTStdioIntHandler()、以设置一些全局易失性标志、从而让您现在发生溢出错误。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在主循环中使用 UARTPeek ('<')、而不是在中断处理程序中使用。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Bob。

    我尝试在 main 函数内使用 UARTRpeek、它工作正常。 不过 、其理念类似于轮询方法。 它通过 UART 持续检查数据、如果存在数据、它会检查 UARTREK 函数中给出的终止字符。 如下所示:

    MAIN ()

    while (1)

    if (UARTPeek ('<')!=-1)
     {
     UARTges_new (buf、(UARTPeek ('<')+1));
     memset (buf、0、sizeof (buf));
     }

    因此、我尝试在 UART stdio 中断处理程序中立即使用 UARTpeek 函数 、在获取数据并将其存储在循环缓冲区中之后。  在 UART stdio 中断处理程序中、将有一个 while 循环、如下所示。 在 while 循环结束时、我包含了 UARTpeek、后跟 UARTgets 函数。

     while (map_UARTCharsAvail (g_ui32Base))

    {…

    if (UARTPeek ('<')!=-1)
     {
     UARTges_new (buf、(UARTPeek ('<')+1));
     memset (buf、0、sizeof (buf));
     }

    但这种方法再次导致 UART 数据丢失、而且非常不可靠。 找不到原因?

    其次、

    UART peek 函数 通过计算 终止字符的第一次出现来查找长度、而 UARTgets 函数使用该长度读取数据。

    例如:如果我的传入数据流为">abcdef<",则 UARTets 函数将数据存储为">abcdef"。

    但是、如果我 的传入字符串具有多个终端字符、情况会怎样。 如 <efghij<klmnop<"

    在这种情况下,我第一次进入 UART peek 和第二次进入 UART peek 时会得到两组数据,如">abcdef。

    但迭代会在两次之后停止。 无论字符串的大小如何、 只会发生两次迭代、并丢弃剩余的迭代。

    您能解释 一下这种奇怪的行为吗?

    感谢你能抽出时间。

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

    如果我可以-相关评论如下:

    • 供应商的"Bob"已经超越了" - "供应商援助规范!"    我们非常希望我们的海报能够识别和欣赏这种情况-并且(经常)表示感谢。
    • 海报(最新)操作改进:
      • "终止字符"证明"唯一"是"正常"的、因此其"目镜到达会停止该过程!   (即终止!)
      • 当此类唯一性"无法保证"时、"典型" 要求"此类"终止字符"的"背靠背到达"、以影响"终止"。
      • 这是通过'Alerting' (尚未记录或打印)实现的、'First Terminating char's Arrival'
      • 然后、"写入/打印"该字符-前提是它不 是"立即重复"
      • 或影响'Termination'-何时终止字符。  连续接收

    如果不注意到 Bob 有(到目前为止)"义务海报的(明显)非 MCU 问题!"     供应商的"Bob"是一 种非常有限且高度受重视的论坛资源之一!    

    基本代码程序不属于本论坛的"以"为中心"性质-并且"不符合论坛的最佳利益!"   此处考虑影响-如果"任何/大多数"论坛参与者-提出"持续的 (而不是)基本编程问题"序列。    (任何)时间(然后)是否会保留-以解决基于(适当) MCU 的问题?

    还有(其他)论坛 (和/或学习资源)侧重于此类规范指导一般"问题解决"-这些论坛应收到(认真)海报"注意事项"。

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

    感谢您的指导。

    对于由此给您带来的不便、我深表歉意。

    正如您所说的、Bob 已经为我提供了代码示例、让我产生怀疑。 这对满足我的要求更有帮助。  

    我想用最后一个问题来结束这个主题。

    我完全明白了您的观点、以后不会再重复这一点。

    再次感谢您...

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

    我的朋友-这里没有人(至少是我所有的人)要求你道歉!   然而、"发出警报!"对于论坛来说是否恰当且有益?

    您显然"渴望学习"、并且取得了很好的进展、并且提交"最后一个问题"(相信我在这里的十年多)的可能性非常小!

    我公司的投资者始终强调、"识别弱点"证明"效率低下且不当"、但却未能"提供卓越的替代方案!"   而且-根据他们的指导(实际上是规则)、我认为我"很好地遵守了"。

    在您的兴奋之处-您"没有提及"我提供的编程帮助-尝试"解决"-这是(著名的)最后一个问题。   您是否可以提供(部分)反馈?

    祝您在"加速学习"和"启动您的钩子"中顺利进入(库存更充足)流中...