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.

[参考译文] RTOS/TM4C123GE6PM:UART 多字节 RX 完成中断?

Guru**** 2390745 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/729050/rtos-tm4c123ge6pm-uart-multibyte-rx-completion-interrupt

器件型号:TM4C123GE6PM
主题中讨论的其他器件:TM4C123

工具/软件:TI-RTOS

是否有方法可以在 UART 字节字符串的末尾触发中断? 我有多个器件连接到 UART 端口、每个器件以"突发"方式传输数据、例如、来自 GPS 模块的 NMEA 字符串。

最好将 UART 数据处理延迟到在 UART 上接收到整个消息之后、而不是在每个字节之后、我必须停止以一次处理一个字节。

我认为、当新的起始位不在 X 时间内跟随停止位时、可能涉及超时? 我提出这一问题是因为现在确实有人完善了一种处理这种行为的方法、我想知道他人在做什么。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、TM4C123有一个16字节的接收 FIFO、并且您可以将一个中断编程为在1/8 (第2个字节)、1/4 (第4个字节)、1/2 (第8个字节)、3/4 (第12个字节)或7/8 (第14个字节) FIFO 满时发生。 然后还启用"接收超时"中断。 当 FIFO 不为空并且在32位周期内没有接收到更多数据时、就会产生超时中断。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    值得一提的是、我打开了 UART DMA 支持、但它对我来说非常透明、因此我不确定这会产生什么影响。

    我不会提前知道我需要多少字节、因此打开已使用的 FIFO 比例中断不会有什么帮助。 但是、接收超时听起来很有趣。 我相信我可能已经在用它了。 如果我错了、请更正我(请参阅随附的代码)。 我的超时值 RADIO_UART_READ_TIMEOUT = 250 (滴答声? y=milliseconds,N=?)。 但我将其用作一种非阻塞式 UART 读回。 我调用 read(),它要么立即用一个字节返回,要么超时并继续。

    我想能够调用 read(),它就在那里,并无限期地等待,直到它有1。) 开始接收数据和2.) 在之前未知的字节数之后、数据已停止到达。 我可以这么做吗?

    UART_PARAMS_INIT (&uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;//默认
    值 uartParams.readDataMode = UART_DATA_BINARTOND;
    uartParams.readReturnMode = UART_RETURN;//默认
    值 uartParams.readEcho = UART_250_OFF_READONO;UART_RETURN
    = UART_RETURN;//
    uartParams.波特 率= 9600;
    uartParams.stopbits = UART_STOP_One;
    UART = UART_OPEN (RADIO_UART、&uartParams);
    IF (UART = NULL){
    System_abort ("打开 UART 时出错");
    } 

    我当前等待一段时间,直到我知道设备已响应并使用输入缓冲区的长度调用 read()。 如果我之前调用 read(),它是否会等待,直到它除了任何额外数据到达的超时(即看到最后一个停止位,没有更多字节进入)之外,还开始接收数据?

    RET = UART_READ (UART、buf、len); 

    我想在数据到达时捕获完整的"突发"数据、但由于我不确定要接收多少"突发"数据、这一点变得更加复杂。  这是一项交易:

    1) 我要求对讲机提供有关网络中所有节点的信息

    2) 对于网络中的每个节点、我都会得到一个"突发"的数据。 我希望能够通过单个读取()调用来捕获每个"突发"。

    3) 我不确定有多少个节点,因此我无法调用 read(),如果没有更多节点进入,它将无限期挂起。

    考虑到我的设计问题、这是可能的、还是我需要更加关心一次一个字节地汇编传入的数据?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这实际上取决于您是使用 TI-RTOS UART 驱动程序、还是执行自己的操作。 如果每个 UART 仅与单个任务相关联、则可以自行执行中断服务例程、并让其查找 NMEA0183终止字符0x0A。 我从事了一个 NMEA0183集线器项目、该项目以三种不同的波特率收集并重新广播四种不同 UART 上的数据。 特定 UART 的中断例程只需从 UART 中抓取每个字符并将其放入循环缓冲区。 如果接收到的字符是'$'或'!'、它通过初始化指针来跟踪 NMEA0183字符串。 然后、当它接收到下一个0x0A 时、它会设置一个标志、指示已接收到完整的 NMEA 字符串。 整个中断例程相对较快、因为中断中没有对字符串进行处理。 我为接收的字符(8192)使用了一个大循环缓冲区、并为包含每个接收字符串的起始和长度的结构使用了一个较小的循环缓冲区。 可简化为两个静态80字符串。 (我相信 NMEA0183句子的最大长度为80个字符。) 当第一个语句收到有效语句时、您为该缓冲区设置一个标志、然后开始填写下一个语句。 同时、您有一个 RTOS 任务、用于查找该易失性静态标志、当它为 true 时、会处理该字符串。

    我将询问 TI-RTOS 专家是否有其他建议。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mark、您好!
    我认为 TI-RTOS UART 驱动程序处理读取超时中断的方式不是很好。 它启用它,但如果发生 UART_READ()调用方,它不会解除阻止。 我唯一可以建议的是增加 FIFO 中断阈值并使用 UART_Params 的 readTimeout、我看到您已经在执行此操作。
    此致、
    Janet
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我的测试显示,使用 uartParams.readTimeout 设置,Read()调用确实会返回,但它不是基于从最后一个接收到的字符的延迟,而是基于调用 read()的时间。 因此,在某些情况下,它会收集完整的猝发,但更经常会将它们剪切为多个 read()调用。 我想这是可以的。

    我假设我应该做的是创建自己的中断处理程序、在数据到达时处理数据、并将每个"突发"汇编到 FIFO 中的一个条目中。 任务完成后、他们可以将其从 FIFO 中弹出、然后继续愉快地执行任务。 器件进入此阶段后、将处理 TLV (类型长度值)二进制数据及校验和等 因此、我的中断处理程序需要先关闭起始字符并验证校验和、然后再将其放入 FIFO 中。 再说一次、这是可以的。

    是否有办法将 UART 设置为在中断处理程序中触发对接收到的字符的处理而无需调用 read()? 有没有这方面的例子?

    我希望能够随时访问 UART.WRITE (DATA)、但我希望通过中断处理程序完全驱动读取/接收部分。 让我的中断处理程序在完成任务时标记我的任务处理、否则不会打扰我。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Mark、您好!

    您可能可以从 UART Tiva 驱动程序开始、并对其进行修改以执行所需的操作。  如果您使用的是非 DMA UART 驱动程序,一旦您打开 UART,中断就会被启用,并且如果没有人调用 UART_read(),则接收到的数据会进入 Ring Buffer。  您可以让 UART 中断处理程序调用一个处理函数(该函数可在 UART_Params 的'custom'字段中传递给驱动程序)。  处理函数可以布置 Swi 或解除任务阻断以执行读取。
    我不确定 UARTTivaDMA 驱动程序是否可以用于此目的,因为它根据传递给 UART_Read()的字节数设置 DMA。

    此致、

    Janet

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    嗯。 我有另外两个 UART 在单独的器件上工作、我喜欢它们在 DMA 模式下工作。 我想全局启用/禁用 DMA 驱动程序、那么我应该全局禁用它吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Mark、您好!

    也许 DMA 模式仍可用于读取超时(我从未尝试过)。  在 ISR 中、如果您获得读取超时中断、则可以停止任何正在进行的 DMA 传输、调用处理函数、然后对 DMA 重新编程。

    此致、

    Janet

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

    我最终使用 driverlib/NVIC API 来设置我自己的中断处理程序。 我必须修改*。cmd 文件以添加链接器脚本的 VTABLE 条目:

    部分
    {
    .text:> FLASH
    .const:> FLASH
    .cinit:>闪存
    .pinit:> FLASH
    init_array:> FLASH
    
    .data :> SRAM
    .bss:> SRAM
    .sysmem:> SRAM
    .stack:> SRAM
    .vtable:> SRAM
    } 

    然后、我使用中断处理程序修改了我的源文件:

    void RadioRxCallback( void ){
    
    uint32_t ui32Status;
    int32_t rxChar;
    
    //获取当前中断标志
    ui32Status = UARTIntStatus (RADIO_UART_BASE、TRUE);//获取中断状态
    //复位中断标志
    UARTIntClear (RADIO_UART_BASE、ui32Status);//清除已发出的中断
    
    while (UARTCharsAvail (radio_UART_base))//循环(有字符时)
    {
    rxChar = UARTCharGetNonBlocking (radio_UART_base);
    /*此处的错误检查内容-请参阅 UARTCharGetNonBlocking ()和 tm4c123gh6pm.pdf -第906页(UARTDR 寄存器说明)*/
    }
    }
    

    然后我在任务中设置 UART

    //调用 NVIC API 命令来设置中断处理程序
    IntRegister (RADIO_UART_RX_INTERRUPT、RadioRxCallback);
    IntEnable (RADIO_UART_RX_INTERRUPT);
    IntMasterEnable();
    //设置引脚
    SysCtlPeripheralEnable (Periph_radio_UART);
    SysCtlPeripheralEnable (Periph_radio_UART_Pins);
    GPIOPinConfigure (PIN_RADIO_RX);
    GPIOPinConfigure (PIN_RADIO_TX);
    GPIOPinTypeUART (PORT_RADIO_UART、PIN_RADIO_RX | PIN_RADIO_TX);
    //设置波特率和特性
    UARTConfigSetExpClk (radio_UART_base、SysCtlClockGet ()、9600、
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);
    //启用仅启用 RX 和 RX 超时中断
    UARTIntEnable (RADIO_UART_BASE、UART_INT_RX | UART_INT_RT); 

    我想从这里我会很好。 它减轻了从任务内部持续调用 read()的需要。 我可以清除中断处理程序、以了解它对数据的动态反应。 感谢你的帮助。