【问题标题】:UART Serial Bridge using MSP430 FR5994使用 MSP430 FR5994 的 UART 串​​行桥接器
【发布时间】:2021-09-28 11:11:18
【问题描述】:

我正在尝试使用 MSP430 创建一个 UART 桥接器。我有一个传感器向 MSP430 发送字符串,我打算将其发送到我的 PC。此外,传感器响应我打算通过 MSP430 桥使用我的 PC 发送的命令。我发送到传感器的命令没有任何缺陷地到达它。但是,传感器发送的消息到达连接到我的 PC 的 UART 的 TXBUF,但没有出现在终端上。在检查寄存器时,我在 TXBUF 上看到 0x000A,但它似乎收到了所有字符。但是什么都没有打印出来。

我正在使用以下代码:

#include <msp430.h> 

unsigned char *msg;

unsigned char i=0 , j=0;

int main(void)

{

 WDTCTL = WDTPW | WDTHOLD;      // stop watchdog timer

// Pin Initialization

P6SEL1 |= BIT1;
P6SEL0 &= ~BIT1;
P6SEL1 |= BIT0;
P6SEL0 &= ~BIT0;
P2SEL1 |= BIT5;
P2SEL0 &= ~BIT5;
P2SEL1 |= BIT6;
P2SEL0 &= ~BIT6;

PM5CTL0 &= ~LOCKLPM5;

// UART Initialization
UCA1CTLW0 |= UCSWRST;
UCA1CTLW0 |= UCSSEL__SMCLK;     // Using 1 MHZ clock
UCA3CTLW0 |= UCSWRST;
UCA3CTLW0 |= UCSSEL__SMCLK;
UCA3BRW = 6;                    // Baud Rate set to 9600
UCA3MCTLW = UCOS16 | UCBRF_8 | 0x2000;
UCA1BRW = 6;
UCA1MCTLW = UCOS16 | UCBRF_8 | 0x2000;

UCA3CTLW0 &= ~UCSWRST;
UCA1CTLW0 &= ~UCSWRST;
UCA3IE |= UCRXIE;
UCA1IE |= UCRXIE;
__enable_interrupt();           // Interrupt enable
while (1)
{}
}

// UART A3 connected to the PC.
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=EUSCI_A3_VECTOR
__interrupt void USCI_A3_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(EUSCI_A3_VECTOR))) USCI_A3_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA3IV, USCI_UART_UCTXCPTIFG))
{
    case USCI_NONE: break;
    case USCI_UART_UCRXIFG:
        while(!(UCA3IFG&UCTXIFG));
        UCA1TXBUF = UCA3RXBUF;
        __no_operation();
        break;
    case USCI_UART_UCTXIFG: break;
    case USCI_UART_UCSTTIFG: break;
    case USCI_UART_UCTXCPTIFG: break;
    default: break;
   }
 }


 // UART A1 connected to the sensor.
 #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
 #pragma vector=EUSCI_A1_VECTOR
 __interrupt void USCI_A1_ISR(void)
 #elif defined(__GNUC__)
 void __attribute__ ((interrupt(EUSCI_A1_VECTOR))) USCI_A1_ISR (void)
 #else
 #error Compiler not supported!
 #endif
{
switch(__even_in_range(UCA1IV, USCI_UART_UCTXCPTIFG))
{
    case USCI_NONE: break;
    case USCI_UART_UCRXIFG:
        while(!(UCA1IFG&UCTXIFG));          //Trying to read a string
        {
            *(msg+i) = UCA1RXBUF;
            j = *(msg+i);
            UCA3TXBUF = j;
            i++;
        }
        break;
    case USCI_UART_UCTXIFG: break;
    case USCI_UART_UCSTTIFG: break;
    case USCI_UART_UCTXCPTIFG: break;
    default: break;
}

}

请帮忙。 提前致谢。

【问题讨论】:

  • 一些需要考虑的事情:msg 指向哪里?程序运行时i 中有哪些值?为什么USCI_A1_ISR 中有大括号?
  • 首先尝试从 MSP430 向 PC 连续发送一个已知值(例如:'A5')。如果这行得通,那就去实现你的要求。
  • 我尝试正常从 MSP430 向 PC 发送 0x0031,它成功了。然后我尝试接收消息,但仍然只是将 0x0031 发送到 PC,但没有成功。
  • 好的,忙!我会调查这个
  • 我使用模拟器将 UCA3 更改为 UCA0,以在 Micro-USB 端口获取数据,此处代码运行良好,但不适用于 UCA3。可能是什么问题??

标签: embedded uart msp430 texas-instruments


【解决方案1】:

首先,我在您的列表中看到的问题:

(p1) 即使两个 UART 的波特率相同,但在 PC 和传感器同时发送数据的情况下,您的设计并未使用适当的缓冲(参见下面的问题 3) .更糟糕的是,您的两个 ISR 都包含不缓冲的阻塞 while 循环,只会浪费时间直到中断标志清除。

(p2) 您的来源(如下所示)可能编码错误:

while(!(UCA1IFG&UCTXIFG));          //Trying to read a string
{
  *(msg+i) = UCA1RXBUF;
  j = *(msg+i);
  UCA3TXBUF = j;
  i++;
}

因为 while 循环的主体实际上是空的,因为尾随“;”所以后面的开/关括号内的代码不是while循环的一部分。

(p3) 指针变量 msg 从未初始化。它很可能指向随机堆内存或堆栈的未使用部分,因此程序不会立即崩溃。最终,它会因为变量 i 递增但从不递减,因此内存是传感器 ISR“使用一次”。

我的建议:

(s1) 声明两个缓冲区,一个用于来自 PC 的数据,另一个用于来自传感器的数据。删除“unsigned char *msg”并替换为如下内容:

unsigned char pc_data[256];
unsigned char sensor_data[256];

大小 256 是为了在与 8 位索引变量一起使用时创建一个穷人循环缓冲区。当变量达到 255 并递增时,它会简单地回滚到 0。在这种情况下 ij em> 正如您已经声明的那样可以使用,但也许 pc_data_indexsensor_data_index 会更好理解。您还需要另外两个变量来确定缓冲区的大小,可能是 pc_data_countsensor_data_count。如果您的处理器无法承受这么多的缓冲区空间,则减少到模数(即 2^BUFSIZE,其中 BUFSIZE = 32)并在更新索引时使用模运算符:

pc_data_index = (pc_data_index + 1) % BUFSIZE;

(s2) 更改两个 ISR 例程以处理 USCI_UART_UCRXIFG 和 USCI_UART_UCTXIFG 中断事件。 ISR 不应包含任何循环,只是缓冲数据或从缓冲区中写出数据。这是一个例子:

switch(__even_in_range(UCA1IV, USCI_UART_UCTXCPTIFG))
{
    case USCI_NONE: break;
    case USCI_UART_UCRXIFG:
        // Byte was received from sensor, so buffer it
        sensor_data[sensor_data_count++] = UCA1RXBUF;
        sensor_data_index = (sensor_data_index + 1) % BUFSIZE;
        // Enable the TX interrupts to send the buffered data
        UCA1IE |= UCTXIE;
        break;
    case USCI_UART_UCTXIFG: 
        // Sensor UART is ready to send next byte
        UCA3TXBUF = sensor_data[sensor_data_index];
        sensor_data_count--;
        // Disable the TX interrupt if no more data to send
        if (sensor_data_count == 0) UCA1IE &= ~UCTXIE;
        break;

【讨论】:

    最近更新 更多