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.

[参考译文] TM4C129XNCZAD:如何设置发送缓冲区为空的中断

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1534215/tm4c129xnczad-how-to-set-up-interrupt-for-transmit-buffer-empty

器件型号:TM4C129XNCZAD

工具/软件:

我们的器件启用了 RS485 通信、并且运行正常、但我想切换为仅中断驱动的通信、这样处理器在等待传输字符时就不必坐着或循环。

以下代码用于启用其中一个串行端口:

ROM_IntEnable (INT_UART1);
ROM_UARTIntEnable (UART1_BASE、UART_INT_RX | UART_INT_RT);

我是否需要添加 UART_INT_TX、如下所示?

ROM_UARTIntEnable (UART1_BASE、UART_INT_RX | UART_INT_RT | UART_INT_TX);

我在示例代码中找到了以下命令:

MAP_UARTFIFOLEVELSet (g_ui32Base、UART_FIFO_TX1_8、UART_FIFO_RX1_8);

当发送缓冲区中还有一个字符时、这是否意味着会生成中断?

 我用于触发中断的是什么、告诉我现在是时候在发送缓冲区中添加更多字符了吗?

下面是我们中断处理程序中的第一行:

UARTHB_Status = ROM_UARTIntStatus (UART1_BASE、TRUE);//获取中断状态
ROM_UARTIntClear (UART1_BASE、UARTHB_Status);//清除置为有效的中断

这些语句是否会清除所有中断、或者我是否需要添加其他内容来清除发送中断?

这是我用于填充输出缓冲区的代码。  请随时发表评论。

for( i = 0 ; i < 300; i++)//填充 FIFO 缓冲区。 注意:在 v2.27 之前、绝不会启用 FIFO 缓冲区。

IF (MUST_RESEND_char_HB)
GLOBAL_CHAR_HB = CHARACTER_TO_RESENT_HB;
暴露
global_char_hb = get_from_output_buffer_hb ();
如果 (UARTCharPutNonBlocking (UartPort_HB、GLOBAL_char_HB)== false)//字符未进入 FIFO、则必须重试。 UART1_BASE

MUST_RESEND_CHAR_HB = true;
Character_TO_RESENT_HB = GLOBAL_char_HB;
休息;
}
暴露

MUST_RESEND_CHAR_HB = false;
}

IF (OUT_wrptr_HB = OUT_rdptr_HB)

HOST_1_HB_TRANSFER_FINISED = TRUE;
characters_to_send_hb = false;
休息;
}

}

非常感谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引述 userid=“345142" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1534215/tm4c129xnczad-how-to-set-up-interrupt-for-transmit-buffer-empty

    我是否需要添加 UART_INT_TX、如下所示?

    ROM_UARTIntEnable (UART1_BASE、UART_INT_RX | UART_INT_RT | UART_INT_TX);

    [/报价]

    您可以添加 UART_INT_TX 以首先准备 TXFIFO 中的数据。 然而,这并不是绝对必要的。 您还可以等待 RX 中断到达、在 RX ISR 中、将您的数据写入 TXFIFO。   我会建议你尝试两个,看看哪一个最适合你的应用.  

    [引述 userid=“345142" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1534215/tm4c129xnczad-how-to-set-up-interrupt-for-transmit-buffer-empty

    我在示例代码中找到了以下命令:

    MAP_UARTFIFOLEVELSet (g_ui32Base、UART_FIFO_TX1_8、UART_FIFO_RX1_8);

    当发送缓冲区中还有一个字符时、这是否意味着会生成中断?

    [/报价]

    TX 和 RX FIFO 中都有 16 个条目。  因此、对于 FIFO_TX1_8 和 FIFO_RX1_8 意味着当 FIFO 中还有 2 个条目时生成中断。  

    是 我用来触发中断的内容告诉我应该在发送缓冲区中添加更多字符吗?

    正确。 当 FIFO_TX1_8 中还有 2 个条目留在 TXFIFO 中时、它将中断应用程序、以便将更多数据放入 FIFO 中。  

    [引述 userid=“345142" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1534215/tm4c129xnczad-how-to-set-up-interrupt-for-transmit-buffer-empty

    下面是我们中断处理程序中的第一行:

    UARTHB_Status = ROM_UARTIntStatus (UART1_BASE、TRUE);//获取中断状态
    ROM_UARTIntClear (UART1_BASE、UARTHB_Status);//清除置为有效的中断

    这些语句是否会清除所有中断、或者我是否需要添加其他内容来清除发送中断?

    这是我用于填充输出缓冲区的代码。  请随时发表评论。

    [/报价]

    是的、您的代码将清除在 UARTHB_Status 中设置为记录的标志。

    [引述 userid=“345142" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1534215/tm4c129xnczad-how-to-set-up-interrupt-for-transmit-buffer-empty

    这是我用于填充输出缓冲区的代码。  请随时发表评论。

    for( i = 0 ; i < 300; i++)//填充 FIFO 缓冲区。 注意:在 v2.27 之前、绝不会启用 FIFO 缓冲区。

    IF (MUST_RESEND_char_HB)
    GLOBAL_CHAR_HB = CHARACTER_TO_RESENT_HB;
    暴露
    global_char_hb = get_from_output_buffer_hb ();
    如果 (UARTCharPutNonBlocking (UartPort_HB、GLOBAL_char_HB)== false)//字符未进入 FIFO、则必须重试。 UART1_BASE

    MUST_RESEND_CHAR_HB = true;
    Character_TO_RESENT_HB = GLOBAL_char_HB;
    休息;
    }
    暴露

    MUST_RESEND_CHAR_HB = false;
    }

    IF (OUT_wrptr_HB = OUT_rdptr_HB)

    HOST_1_HB_TRANSFER_FINISED = TRUE;
    characters_to_send_hb = false;
    休息;
    }

    }

    [/报价]

    真的看不到问题。  

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

    非常感谢、我现在可以使用它... 规则三角形电流。 第一个问题:

    您能解释一下以下内容吗? “您可以先添加 UART_INT_TX 以准备 TXFIFO 中的数据。

    现在、大部分时间继续让我的器件正常工作。   有时我会进行看门狗复位、因此我认为存在一个中断发生、而我没有处理。  有什么想法可能是什么?  我将尝试在此处包含所有相关代码。

    首先、启用发送中断。

    ROM_UARTIntEnable (UART1_BASE、UART_INT_RX | UART_INT_RT | UART_INT_TX);//在此处添加 UART_INT_TX 以启用发送中断

    配置:

    ROM_UARTConfigSetExpClk (UART1_BASE、ui32SysClock、9600、(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_ODD));//根据我们的 Modbus 规范、需要奇校验

    在中断处理程序中:

    UARTHB_Status = ROM_UARTIntStatus (UART1_BASE、TRUE);//这会返回所有中断处于活动状态的位映射值、以便将这些中断清除。
    ROM_UARTIntClear (UART1_BASE、UARTHB_Status);//清除先前读取中激活的所有中断。 (请查看 UARTIntEnable 的文档以查看这些位。)

    IF (UARTHB_Status &(UART_INT_RX | UART_INT_RT))

    while (ROM_UARTCharsAvail (UART1_BASE))

    Ch = UARTCharGetNonBlocking (UART1_BASE);//如果没有可用字符、会发生什么情况?
    put_in_input_buffer_hb ((char)ch );
    HB_SDR Time_Out = 0;//如果我们有一个字符、则复位
    }
    hm1flag = true;//此标志启动进程以确定何时可以处理新消息
    }

    要关闭 RS485 变送器、请执行以下操作:

    我在单独的半毫秒中断中有代码、可以稍后返回并关闭发送器。  我看到有一个选项可以在发送最后一位时获得中断。  我想我需要实施它。

    if (Host_1_HB_TRANSFER_FINISED)//在需要时关闭 RS485 发送器

    if (UARTBusy (UartPort_HB)== false)//当 UARTBusy 变为 false 时、我们完成了发送、继续禁用发送器

    Disable_Uart Port_HB_Transmiter ();//移至 v2.27 中的中断
    HOST_1_HB_TRANSFER_FINISED = FALSE;//发送器现在已关闭、复位标志
    TRANSMIT_ACTIVE_HB = FALSE;//全部完成发送
    }
    }

    我有什么遗漏吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您能解释更多以下内容吗? “您可以添加 UART_INT_TX 以首先准备 TXFIFO 中的数据。“

    例如、首次设置 UART 后、TXFIFO 将为空。 如果您使用 1/8 阈值启用 TX 中断、则 TX 中断将立即触发、因为空小于 FIFO 的 1/8。 在用于 TXFIFO 中断的 ISR 中、您最多可以将 16 个数据写入 TX FIFO。 在 TXFIFO 只剩下两个数据(即发送 14 个数据)后、下一个 TX 中断才会出现。

    现在、我的设备大部分时间都在工作。   有时我会进行看门狗复位、因此我认为存在一个中断发生、而我没有处理。  有什么想法可能是什么?  我将尝试在此处包含所有相关代码。

    看门狗将首先生成 NMI 中断、然后再拉低复位。 您需要检查是否已清除 WD 中断。  

    如果在清除第一个超时中断之前、计时器再次倒计时至零状态、则、和
    通过设置 WDTCTL 寄存器的 RESETN 位(看门狗计时器)来启用复位信号
    将其复位信号置为有效。 如果在 32 位计数器到达其之前清除中断
    第二次超时、32 位计数器加载 WDTLOAD 寄存器中的值并进行计数
    从该值恢复。

    [引述 userid=“345142" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1534215/tm4c129xnczad-how-to-set-up-interrupt-for-transmit-buffer-empty/5902072 #5902072“]

    首先、启用发送中断。

    ROM_UARTIntEnable (UART1_BASE、UART_INT_RX | UART_INT_RT | UART_INT_TX);//在此处添加 UART_INT_TX 以启用发送中断

    配置:

    ROM_UARTConfigSetExpClk (UART1_BASE、ui32SysClock、9600、(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_ODD));//根据我们的 Modbus 规范、需要奇校验

    [/报价]

    到目前为止我没有看到任何问题。  

    [引述 userid=“345142" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1534215/tm4c129xnczad-how-to-set-up-interrupt-for-transmit-buffer-empty/5902072 #5902072“]

    在中断处理程序中:

    UARTHB_Status = ROM_UARTIntStatus (UART1_BASE、TRUE);//这会返回所有中断处于活动状态的位映射值、以便将这些中断清除。
    ROM_UARTIntClear (UART1_BASE、UARTHB_Status);//清除先前读取中激活的所有中断。 (请查看 UARTIntEnable 的文档以查看这些位。)

    IF (UARTHB_Status &(UART_INT_RX | UART_INT_RT))

    while (ROM_UARTCharsAvail (UART1_BASE))

    Ch = UARTCharGetNonBlocking (UART1_BASE);//如果没有可用字符、会发生什么情况?
    put_in_input_buffer_hb ((char)ch );
    HB_SDR Time_Out = 0;//如果我们有一个字符、则复位
    }
    hm1flag = true;//此标志启动进程以确定何时可以处理新消息
    }

    [/报价]

    TX 和 RX 中断由同一 ISR 共享。 您处理 TX 中断的代码在哪里? 如果出现 TX 中断、只需清除标志、对吧?

    这里的代码基本上就是我之前所说的、您实际上并不需要启用 TXFIFO 中断。 当出现 RX 中断时、您只需将数据写入 TXFIFO、即可根据接收的内容开始发送。  

    在 uart_echo 示例中、具有类似的代码。  

    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Get the interrrupt status.
        //
        ui32Status = MAP_UARTIntStatus(UART0_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        MAP_UARTIntClear(UART0_BASE, ui32Status);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(MAP_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            MAP_UARTCharPutNonBlocking(UART0_BASE,
                                       MAP_UARTCharGetNonBlocking(UART0_BASE));
    
            //
            // Blink the LED to show a character transfer is occuring.
            //
            MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
    
            //
            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
            //
            SysCtlDelay(g_ui32SysClock / (1000 * 3));
    
            //
            // Turn off the LED
            //
            MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
        }
    }

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

    我的错。  我 在中断处理程序中共享了代码以进行接收、但不进行发送。  这里是:

    IF (UARTHB_Status 和 (UART_INT_TX))

    IF (characters_to_send_HB)

    for (I = 0;I < 300;I++)//填充 FIFO 缓冲区。 注意:在 v2.27 之前、绝不会启用 FIFO 缓冲区。

    IF (MUST_RESEND_char_HB)
    GLOBAL_CHAR_HB = CHARACTER_TO_RESENT_HB;
    暴露
    global_char_hb = get_from_output_buffer_hb ();
    如果 (UARTCharPutNonBlocking (UartPort_HB、GLOBAL_char_HB)== false)//字符未进入 FIFO、则必须重试。 UART1_BASE(替换 UARTCharPut)

    Character_TO_RESENT_HB = GLOBAL_char_HB;
    MUST_RESEND_CHAR_HB = true;
    休息;
    }
    暴露

    MUST_RESEND_CHAR_HB = false;
    }

    // while (UARTBusy (UartPort_HB));//当我们通过 UART 发送出去时、尤其是在中断中、我们肯定不会像此处那样循环!

    IF (OUT_wrptr_HB = OUT_rdptr_HB)

    HOST_1_HB_TRANSFER_FINISED = TRUE;
    characters_to_send_hb = false;
    休息;
    }

    }
    }
    }

    此练习的主要目的是避免主代码循环、等待发送寄存器为空以关闭 RS485 发送器。

    我仍然不明白这一点:“你在这里的代码基本上就是我之前所说的,你不需要启用 TXFIFO 中断。 当出现 RX 中断时、您只需将数据写入 TXFIFO、即可根据接收的内容开始发送。“

    我的问题不是启动变速器、我的问题是知道何时关闭变送器、我不想坐下来并循环。

    我将了解看门狗设置。  我的代码可以工作一个小时、我想、无需重置。  我是否未处理可能导致中断并使我在中断中保持锁定状态的特定条件?

    谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我仍然不明白这一点:“这里的代码基本上就是我之前说过的、您并不真正需要启用 TXFIFO 中断。 当 RX 中断到来时、您只需将数据写入 TXFIFO、即可根据接收的内容开始传输。

    很抱歉混淆。 我想您可以忽略我的上述评论、因为它可能不适合您的应用。 我指的是用于 RX 中断处理的 uart_echo 示例代码(另请参阅下面的)。 在此中断 ISR 中、 何时调用  UARTCharPutNonBlocking 来填充 TXFIFO 取决于接收到的内容。  

    MAP_UARTCharPutNonBlocking (UART0_BASE、MAP_UARTCharGetNonBlocking (UART0_BASE));

    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Get the interrrupt status.
        //
        ui32Status = MAP_UARTIntStatus(UART0_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        MAP_UARTIntClear(UART0_BASE, ui32Status);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(MAP_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            MAP_UARTCharPutNonBlocking(UART0_BASE,
                                       MAP_UARTCharGetNonBlocking(UART0_BASE));
    
            //
            // Blink the LED to show a character transfer is occuring.
            //
            MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
    
            //
            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
            //
            SysCtlDelay(g_ui32SysClock / (1000 * 3));
    
            //
            // Turn off the LED
            //
            MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
        }
    }

    [引述 userid=“345142" url="“ url="~“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1534215/tm4c129xnczad-how-to-set-up-interrupt-for-transmit-buffer-empty/5902243 #5902243“]

    我的问题不是启动变速器、我的问题是知道何时关闭变送器、我不想坐下来并循环。

    [/报价]

    你不知道你期待收到多少? 如果您提前知道要接收的数据数量、则可以关闭发送器以关闭接收预期数据计数的方式。 或者、您可以在总线处于非活动状态的特定持续时间后使用计时器关闭发送器。  

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

    我们主要进行 Modbus 通信,因此主机可以发送功能 1、2、3、4、6(或其他一些)类型的消息,这是根据我们的 Modbus 协议实施定义的。  需要等效于 3.5 个字符的静默周期、如果接收到的消息是有效的查询或命令、我们的器件可以响应。  我认为很难或不可能提前知道将收到多少个字符,但我们可以在字符停止后查找超时。

    完成回复后、我们可以打开 RS485 发送器。  发送所有字符后、我会在半毫秒的周期性中断中再进行一次检查、以查看传输何时完成并留出一点延迟 、然后关闭发送器。  主机发送另一个查询或命令之前应存在延迟。

    它现在可以处理所有发送,而不是仅仅坐在主循环中循环,等待传输完成以关闭发送器)、但有时系统会停止通信、然后我们的器件会在可能 7 到 10 秒后复位。  通信错误不应导致像这样的复位。

    我习惯于我们的系统运行数小时、而不会在办公室出现任何通信错误。  如果您对从何处开始寻找它会重置的原因有任何想法、请告诉我。  一种想法是、如果发生了我不知道的中断、并且我永远不会清除导致中断的条件、并且它一直调用中断处理程序、这将导致看门狗复位。

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

    如何在 TivaWareTm 外设驱动程序库中了解有关这些项目的更多信息?  如何找出导致 DSR 中断的原因?

    30.2.2.2.30 UARTIntEnable
    启用单独的 UART 中断源。
    原型:
    Void
    UARTIntEnable (uint32_t ui32Base、
    uint32_t ui32IntFlags)
    参数:
    ui32Base 是 UART 端口的基地址。
    ui32IntFlags 是要启用的中断源的位掩码。
    说明:
    此函数启用指示的 UART 中断源。 仅启用的源
    可以反映到处理器中断;禁用的源对处理器没有影响。
    ui32IntFlags 参数是以下任何一种的逻辑“或“运算结果:
    UART_INT_9BIT - 9 位地址匹配中断
    UART_INT_OE — 溢出错误中断
    UART_INT_BE — 中断错误中断
    UART_INT_PE — 奇偶校验错误中断
    UART_INT_FE — 组帧错误中断
    UART_INT_RT — 接收超时中断
    UART_INT_TX — 发送中断
    UART_INT_RX — 接收中断
    UART_INT_DSR - DSR 中断
    UART_INT_DCD - DCD 中断
    UART_INT_CTS - CTS 中断
    UART_INT_RI - RI 中断
    返回:
    无。

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

    您好:Mark、

     如果您未在调制解调器或流控制模式下使用 UART、则不应收到 DTR 错误。 DSR 用于数据集就绪。 您是否收到 DSR 中断?  

     也想给你的头,我将在明天度假,直到一周结束. 我的答复将被推迟。  

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

    感谢您对计划的关注。  我没有得到这个中断,我只是拉出了一个我不会立即识别的中断。

    如果我可能会问、您在此处引用了什么文档?  这是 TI 文档。

    谢谢

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

    是的、它来自数据表。 只需在器件数据表中搜索 DSR 即可。