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.

[参考译文] MSP430FR2355:UCTXCPTIFG ISR 和低功耗模式有问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1388760/msp430fr2355-problem-with-uctxcptifg-isr-and-low-power-mode

器件型号:MSP430FR2355

工具与软件:

我的团队已经确定了性能指标、即传输256字节数据包的功耗。 作为概念验证、我曾尝试为我的 MSP430 Launchpad 编写一个程序 unsigned char 阵列、 文本[256] 、用0至255的整数填充(即无符号8位整数的限制、以使事情变得简单)、然后 CPU 将每个字节发送到 UART 以供 CCS 中的控制台读取。

以 Brock Lameres 的 ADC 中断示例代码为指南、我尝试在字节被发送到缓冲区后将 MCU 切换到低功耗模式、然后在完成传输时触发 IRQ、以重新打开 CPU 并使其递增 无符号整型位置 . 遗憾的是、基于调试器中的单步执行程序、一旦 CPU 关闭、它看起来就会停止。

我缺少什么?

// Global variables
unsigned char text[256];    // 256-byte array
unsigned int position;     // position in text

// Main program
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	
	// Configure UART
	UCA1CTLW0 |= UCSWRST; // UART in software reset mode
	UCA1CTLW0 |= UCSSEL__SMCLK; // SMCLK as BRClk
	UCA1BRW = 8; // baud rate = 115.2k
/*    UCA1MCTLW = 0x2081;    // 1,000,000 BRCLK, 9,600 baud, with 16x oversampling
    UCA1BRW = 6;*/

	// Configure ports
	P4SEL1 &= ~BIT3;
	P4SEL0 |= BIT3;

	PM5CTL0 &= ~LOCKLPM5;

    // Take UART out of software reset
    UCA1CTLW0 &= ~UCSWRST;

    // Configure transmit interrupt
    UCA1IFG &= ~UCTXCPTIFG; // clear transmit complete flag
	UCA1IE |= UCTXCPTIE; // enable transmit complete interrupt
	__enable_interrupt();


	// pre-populate array "text" with all possible positive 8-bit integers
	for (position = 0; position < 256; position++) text[position] = position;
	position = 0; // reset position

	// run loop
	while (1) {
	    UCA1TXBUF = text[position]; // transmit current element of text
	    // uncomment this and comment out next line if not using low-power mode
//	    while (!(UCA1IFG & UCTXIFG));
	    __bis_SR_register(GIE | LPM0_bits); // enable maskable IRQs,
	}                                       // turn off CPU for LPM

	return 0;
}

// Interrupt Service Routine; comment this out for non-low-power test
#pragma vector = USCI_A1_VECTOR
__interrupt void CyclePosition() {
    __bic_SR_register_on_exit(LPM0_bits);   // wake up CPU
    if (position == 255) position = 0;
    else position++;                             // increment position
    UCA1IFG &= ~UCTXCPTIFG;                 // clear transmit complete flag
}

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

    我看不出你在哪里

    UCA0TXBUF =文本[位置]

    全局变量。 如果你不这样做,就不需要中断了。, main ()应该永远不会再次运行。

    你可能也应该撒一些"挥发性"。

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

    等待的常见中断为 TXIFG。 又名 TXBUF 为空、可接受下一个字符。 然后、ISR 将数据写入 TXBUF 以清除中断。

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

    我将在 main ()底部的 while 循环中执行它。

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

    你确定吗? 这就是我的教科书(Brock Lameres 的 Embedded Systems Design)对两项中断的评价:

    MSP430为 eUSCI_Ax 外设提供各种中断、包括两个专用于 UART 传输的中断。 第一个 Tx IRQ 被称为发送中断(UCTXIFG)。 当 Tx 缓冲区数据被写入时、UCTXIFG 标志将被清除。 当 Tx 缓冲区数据已被移动到移位寄存器且缓冲区为空时、UCTXIFG 被置1。 UCTXIFG 仅指示 Tx 缓冲区为空、而不是最后一个字符已完全移出。 第二个 Tx IRQ 被称为发送完成中断(UCTXCPTIFG)。 当 Tx 移位寄存器中的整个字节已经被移出并且它为一个新字符做好准备时、UCTXCPTIFG 被置位。 两个 Tx IRQ 通过 UCAxIE 寄存器内的 UCTXIE 和 UCTXCPTIE 位启用。 两个 Tx IRQ 的标志被称为 UCTXIFG 和 UCTXCPTIFG、保存在 UCAxIFG 寄存器中。

    我当然可以使用 TXIFG 来尝试它、这样做对我来说更有意义。

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

    电压。 这就是我一直在这个系统上执行的方法、每一个系统都会返回到68000。 或者也许是 KIM-1和6502。 当您向 TXBUF 写入数据以响应 TXIFG 时、当前字符完成时有数据等待。 因此在开始下一个采样之前没有延迟。 通过使用 TXCPT 中断、从停止位的结束到下一个开始位的开始有一个延迟。 通常情况下并不复杂。

    (您可能还会注意到、当与 DMA 配合使用时、DMA 系统使用 TXIFG 来触发传输。)

    TXCPT 中断用于告知传输何时完成。 只是它已断开。 文档说(表22-6)它在最后一个字符之后设置(即 TXBUF 中没有数据正在等待)、但在每个字符之后设置。 因而更正了勘误表 USCI42。

    它是否有其他错误? 不知道。

    但除了不对变量位置使用 volatile 之外、我认为您的代码没有任何明显的问题。 这可能会导致主 while 循环执行意外操作。  

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

    那么为什么要这么做中断呢?

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

    是的、这样做了:现在传输效果很好。 虽然我选中此复选框、但我还是找到了一种填充数组的更好方法:我将 for 循环更改为 do/while (位置< 255)、这让我将位置改为 char、 (我想先把它当成一个字符、但遇到了一些问题、因为我忘了做/虽然是一件事、但以前从来没有机会使用它。)

    #include <msp430.h> 
    
    
    /**
     * main.c
     */
    
    // Global variables
    unsigned char text[256];    // 256-byte array
    volatile unsigned char position;     // position in text
    
    // Main program
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	
    	// Configure UART
    	UCA1CTLW0 |= UCSWRST; // UART in software reset mode
    	UCA1CTLW0 |= UCSSEL__SMCLK; // SMCLK as BRClk
    	UCA1BRW = 8; // baud rate = 115.2k
    /*    UCA1MCTLW = 0x2081;    // 1,000,000 BRCLK, 9,600 baud, with 16x oversampling
        UCA1BRW = 6;*/
    
    	// Configure ports
    	P4SEL1 &= ~BIT3;
    	P4SEL0 |= BIT3;
    
    	PM5CTL0 &= ~LOCKLPM5;
    
        // Take UART out of software reset
        UCA1CTLW0 &= ~UCSWRST;
    
        // Configure transmit interrupt
        UCA1IFG &= ~UCTXIFG; // clear transmit complete flag
    	UCA1IE |= UCTXIE; // enable transmit complete interrupt
    	__enable_interrupt();
    
    
    	// pre-populate array "text" with all possible positive 8-bit integers
    	do {
    	    text[position] = position;
    	    position++;
    	} while (position < 255);
    	position = 0; // reset position
    
    	// run loop
    	while (1) {
    	    UCA1TXBUF = text[position]; // transmit current element of text
    	    // uncomment this and comment out next line if not using low-power mode
    //	    while (!(UCA1IFG & UCTXIFG));
    	    __bis_SR_register(GIE | LPM0_bits); // enable maskable IRQs,
    	}                                       // turn off CPU for LPM
    
    	return 0;
    }
    
    // Interrupt Service Routine; comment this out for non-low-power test
    #pragma vector = EUSCI_A1_VECTOR
    __interrupt void CyclePosition() {
        __bic_SR_register_on_exit(LPM0_bits);   // wake up CPU
        position++;                             // increment position
        UCA1IFG &= ~UCTXIFG;                 // clear transmit complete flag
    }

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

    更好(并且更常见)的 ISR:

    {
      switch(UCA1IV)
      {
        case UCIV_UCTXIFG:
          UCA1TXBUF = text[position++];
          break;
        default:
        
    }

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

    我不想让她再爽爽爽,我就射了。"