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.

[参考译文] MSP432P401R:在 SPI 总线上提供 TX/Rx、同时为 UART ISR 提供服务

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/570002/msp432p401r-tx-rx-on-spi-bus-while-servicing-a-uart-isr

器件型号:MSP432P401R

我可以使用一些帮助。 我正在使用红色的 MSP432 Launchpad。 我启动了 UART、并努力将字符回显到终端并搜索设置命令。 我还设置了 SPI 块、并对模拟器件 AD7124-8 ADC 的 ID 寄存器执行 Ping 操作。 我有一个名为 ADC_CMD()的子例程,它传输一个字节的数据,后跟一个虚拟0x00字节,以保持 SCLK 计时,然后等待 SPI ISR 设置完成标志。 SPI ISR 缓存第二个接收到的字节并设置完成标志。

我想让其中一条 UART 命令对 ADC 的 ID 寄存器执行 Ping 操作。 我遇到了一个问题、当我在 UART ISR 中调用 ADC_CMD ()例程时、SPI ISR 永远不会触发、因此 ADC_CMD ()例程就在那里并等待。

我已尽量减少代码:

#include "driverlib.h"


void main (void){


//停止看门狗计时器
WDT_A_HOLD (WDT_A_BASE);

//设置端口,UART intterupt,SPI 中断
initHardware();


ADC_CMD (0x45);//这在这里工作


while (1);
}

/********
ADC_CMD (txByte
/
void ADC_CMD (uint_fast8_t txByte){
//
发送 txByte
//
////发送虚拟0x00字节
//
//////等待 SPI ISR 设置完成标志
//



********
// EUSCIA0_IRQHandler () 
// UART 中断处理程序 ********* / void EUSCIA0_IRQHandler (void){ //清除 UART 中断标志 uint32_t status = SPI_getEnableInterruptStatus (EUSCI_A0_BASE); UART_clearInterruptFlag (EUSCI_A0_BASE、STATUS); //禁用 UART 中断 MAP_UART_DisableInterruptStatus (EUSCI_A0_BASE、EUSCI_A_UART_receive_interrupt); //将字符回显到用户 printMSG(&receiveByte,1); if (receiveByte='\r\n'){ // 执行填充 // adc_cmd (0x45);//此处不起作用 // //执行更多填充 // } //启用 UART 中断映 射_UART_enableInterrupt (EUSCI_A0_BASE、EUSCI_A_UART_receive_interrupt); } /******** // EUSCIB0_IRQHandler ()
// SPI 中断处理程序 ********* / void EUSCIB0_IRQHandler (void){ // 接收两个字节的数据,设置完成标志 // }

我认为问题是 UART ISR 标志未被清除、因此微控制器仍被设置为处理 UART ISR 并防止触发其他可屏蔽中断。 使用 UART ISR、我清除 UART ISR 标志并禁用中断、但 SPI 中断仍然不会触发。  

如果有任何帮助,将不胜感激。

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

    您的问题是您正在尝试嵌套 IRQ。 -在 UART ISR 中,当 IRQ 被全局禁用时,您会期望发生其它 IRQ,这显然是不可能的。 甚至不考虑实现嵌套 IRQ、您的应用程序不需要此类 IRQ (它们很少有)。 最好将命令处理从 UART ISR 移到 main()代码中,使用 UART ISR _only_进行数据/字符传输。 ISR 应尽可能具有缺陷性、应仅处理硬件 I/O 并快速完成。 将应用程序代码放入 ISR 是一个坏主意、除非你真的知道你在做什么、否则没有其他合理的方法。

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

    谢谢 Ilmars。

    很抱歉、我在编程方面没有太多经验。 那么、一个更好的主意是让 ISR 收集 Rx 数据、然后设置"执行某项操作"标志、然后让主循环轮询"执行某项操作"标志并做出相应的反应吗?

    如果我没有主循环、而只是将微循环放置在 LPM 中、这将如何工作?

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

    [引用 user="Brett O'Connor1">]很抱歉、我在编程方面没有太多经验。 因此、更好的做法是让 ISR 收集 Rx 数据、然后设置"执行某些操作"标志、然后让主循环轮询"执行某些操作"标志并做出相应的反应吗?

    是的、在这种情况下、使用全局标志进行通信是常用的方法。 UART ISR 接收字节、将其放入(循环)缓冲区、并将全局标志设置为信号主循环、然后主循环处理数据。

    //伪代码显示思想:
    中断 USART_ISR ()
    {
    RXDATA = UCA0RXBUF;
    datareceived_flag = 1;
    }
    
    
    main ()
    {
    while (1){
    if (datareceived_flag){
    Do _Your _Stuff with (RXdata);
    datareceived_flag = 0;
    }
    __sleep();
    }
    
    

    [引用 user="Brett O'Connor1"]如果我没有主循环,而只是将微循环放在 LPM 中,这将如何工作?

    它可以是一个具有 ISR 的外设、另一个没有 (在轮询模式中)的外设、也可以是具有 IRQ 嵌套的复杂代码、或者只是不起作用。 "无主循环"方法只有在处理单个外设的 IRQ 时才是很好的、基本上就是这样。 [编辑].. 或多个外设 它们不会交互、不会考虑业务、也不会相互通知。 您害怕主循环或什么? )