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.

[参考译文] MSP430FR5969:与 USCIA1的 UART 通信不起作用

Guru**** 2555630 points
Other Parts Discussed in Thread: MSP430FR5969

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/598213/msp430fr5969-uart-communication-with-uscia1-not-working

器件型号:MSP430FR5969

大家好、

我正在使用 CCS Composer、我希望通过 UART 通信从 msp430FR5969与 ESP8266模块进行通信。 基本上、我想通过 USCI_A1中断向 ESP8266发送 AT 命令、以便获得答案(确定)、并使用 USCI_A0模块将其发送到 PC 上的串行监视器。

问题是代码永远不会进入 USCI_A1的中断、而只会进入 USCI_A0的中断。

//
//通过 UART 发送数据:尝试获取对 AT 的响应
//*********
//

#include 
#include "driverlib.h"
#include "stdint.h"
#include 
#include 


#define RX_buffer_length 100

static volatile uint8_t RXbuffer[RX_buffer_length];
static volatile uint8_t RXbufferIDX;

#define RX_buffer_Length1 100

static volatile uint8_t RXbufferIDX1
;-----------



// UART 发送/解析字符串函数
//---------------------------------------------

//----------------------------------
// UART 接口
//--------------------------------------------------------

//USCI_A0
#define UART_TX_READY (UCA0IFG 和 UCTXIFG)
#define UART_RX_READY (UCA0IFG 和 UCRXIFG)
#define UART_TX_DONE (UCA0IFG 和 UCTXCPTIFG)
#define UART_RESET_TX_DONE (UCA0IFG &=~UCTXCPTIFG)

//USCI_A1
#define UART_TX_READY_1 (UCA1IFG 和 UCTXIFG)
#define UART_RX_READY_1 (UCA1IFG 和 UCRXIFG)
#define UART_TX_DONE_1 (UCA1IFG 和 UCTXCPTIFG)
#define UART_RESET_TX_DONE_1 (UCA1IFG &=~UCTXCPTIFG)


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//--------------------------------
// USCI_A0的函数
//------------------------------

//使用 UART
静态 void send_char (char c)
{发送单个字符
//通过 UART 测试发送数据
while (!UART_TX_READY)
;
UCA0TXBUF = c;
while (!UART_TX_DONE)
;
UART_RESET_TX_DONE;
}

//使用 UART
静态 void send_str (char str[])
{发送字符串
while (*str !='\0')
{
send_char (* str);
STR++;
}
}

静态 void send_int (int n、int b)
{
静态字符数字[]="0123456789ABCDEF";
char buffer[5];
int i = 0、符号;

如果((符号= n)< 0)
{
N =-n;
}

操作
{
Buffer[i++]=数字[n % b];
}
while ((n /= b)>0);

如果(符号< 0)
{
Buffer[i++]='-';
}

while (--i >=0)
{
send_char (buffer[i]);
}
}

静态 void new_line()
{
send_char (0xD);
SEND_CHAR (0xA);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//--------------------------------
// USCI_A1的函数
//---------------------------------


静态空 send_char1 (char c)
{
//通过 UART 测试发送数据


while (!UART_TX_READY_1)
;
UCA1TXBUF = c;
while (!UART_TX_DONE_1)
;
UART_RESET_TX_DONE_1;
}

静态空 SEND_STF1 (char str[])
{
while (*str !='\0')
{
send_char1 (* str);
STR++;
}
}

静态 void send_int1 (int n、int b)
{
静态字符数字[]="0123456789ABCDEF";
char buffer[5];
int i = 0、符号;

如果((符号= n)< 0)
{
N =-n;
}

操作
{
Buffer[i++]=数字[n % b];
}
while ((n /= b)>0);

如果(符号< 0)
{
Buffer[i++]='-';
}

while (--i >=0)
{
send_char1 (buffer[i]);
}
}

静态 void new_line1()
{
SEND_CHAR1 (0xD);
SEND_CHAR1 (0xA);
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//--------------------------------
// UART 初始化
//------------------

void init_uart_A0 (void)
{
// UART1端口
// 2.0:TX
// 2.1:RX
P2SEL1 |=(BIT0 | BIT1);
P2SEL0 &=~(BIT0 | BIT1);

//------------------------------------
// UART 的初始化
//-无奇偶校验
//- LSB 优先
//-一个停止位
//- 8位数据
//- UART 模式(异步)
//-使用 SMCLK 时钟(速率= 1MHz)
//-错误字符被拒绝
//-无中断字符中断
//-未处于休眠状态
//-软件复位被禁用
//-波特率:9600波特
//------------------------------------
UCA0CTLW0 = UCSWRST;//复位
UCA0CTLW0 = UCSSEL_SMCLK;
//设置波特率
UCA0BR0=6;
UCA0BR1 = 0x00;
UCA0MCTLW |= UCOS16 | UCBRF_8;
UCA0IE |= UCRXIE; //启用 USCI_A0 RX 中断
UCA0CTLW0 &=~UCSWRST;//取消复位
}


void init_UART_A1 (void)
{
// UART1端口
// 2.5:TX
// 2.6:RX
P2SEL1 |=(BIT5 | BIT6);
P2SEL0 &=~(BIT5 | BIT6);

UCA1CTLW0 = UCSWRST;//复位
UCA1CTLW0 |= UCSSEL_SMCLK;
//设置波特率
UCA1BR0=6;
UCA1BR1 = 0x00;
UCA1MCTLW |= UCOS16 | UCBRF_8;
UCA1IE |= UCRXIE; //启用 USCI_A1 RX 中断
UCA1IE |= UCTXIE; //启用 USCI_A1 TX 中断
UCA1CTLW0 &=~UCSWRST;//取消重置
}


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//--------------------------------
//初始化时钟
//---------------------
静态空 init_clock (void)
{
//--------------------------------
//设置时钟
// MCLK 为1MHz,由 DCO 供源
// SMCLK 为1MHz,由用于 UART 通信的 DCO 供源
// ACLK 为32kHz,由 LFXT 供源,用于与传感器连接的 I2C 通信
//--------------------------------
CSCTL0_H = CSKEY >> 8;//解锁 CS 寄存器
CSCTL1 = DCOFSEL_0; //将 DCO 设置为8MHz
CSCTL2 = SELA_LFXTCLK | SELESS__DCOCLK | SELM_DCOCLK;//设置 ACLK = LFXT (32kHz)并且 MCLK = SMCLK = DCO。
CSCTL3 = DIVA__1 | DIVM_1 | DIVM__1;//所有分频器都设置为1
CSCTL0_H = 0x01;//锁定寄存
器}


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
///----------------------------------
// USCI_A0中断矢量处理例程。
///----------------------------------

#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
#pragma vector=USCI_A0_vector
__interrupt
#elif defined (__GNU__)
__attribute__(INTERRUPT (USCI_A0_Vector)))
#endif
void USCI_A0_ISR (void
)
开关(__evo_in_range (UCA0IV、USCI_UART_UCTXCPTIFG))
{
USCI_NONE 案例:
中断;
USCI_UART_UCRXIFG 案例:

RXbuffer[RXbufferIDX]= UCA0RXBUF;
RXbufferIDX =(RXbufferIDX + 1)% RX_buffer_length;
LPM3_EXIT;
中断;
USCI_UART_UCTXIFG 案例:
中断;
USCI_UART_UCSTTIFG 案例:
中断;
USCI_UART_UCTXCPTIFG 案例:
中断;
}
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
///----------------------------------
// USCI_A1中断矢量处理例程。
///----------------------------------

#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
#pragma vector=USCI_A1_vector
__interrupt
#elif defined (__GNU__)
__attribute__(INTERRUPT (USCI_A1_vector)))
#endif
void USCI_A1_ISR (void
)
//调试字符串、以了解中断是否正常工作
send_str ("Success USCI_A1_ISR");
new_line();

开关(__evo_in_range (UCA1IV、USCI_UART_UCTXCPTIFG))
{
USCI_NONE 案例:
中断;
USCI_UART_UCRXIFG 案例:

RXbuffer1[RXbufferIDX1]= UCA1RXBUF;
RXbufferIDX1 =(RXbufferIDX1 + 1)% RX_buffer_Length1;
send_str ("接收到的数据!");
send_int (RXbufferIDX、10);
new_line();
LPM3_EXIT;
中断;
USCI_UART_UCTXIFG 案例:
中断;
USCI_UART_UCSTTIFG 案例:
中断;
USCI_UART_UCTXCPTIFG 案例:
中断;
}
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//main

void main (void)
{
volatile unsigned j;
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
PM5CTL0 &=~LOCKLPM5; // MSP430FR5969需要此功能!


init_clock();
init_uart_A0 ();
init_uart_a1();

_EINT();//全局启用中断。

while (1)
{
send_str ("begin");
new_line();

send_char1 ('a');
SEND_CHAR1 ("T");
new_line1();

send_str("at send");
new_line();

LPM3;

}
} 

 

在这里、我们可以看到代码从未进入 USCI_A1中断。

开始
发送时
开始
发送时
开始
发送时
开始
如果问题看起来不好、我很抱歉、这是我第一次在论坛上提问、因此我不太实用。
提前感谢您的回复!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Samuele、

    乍一看、我看不到您的代码有任何明显的错误。 我首先要做的是、让我动手使用逻辑分析仪或示波器、并探测 RX 和 TX 线路。 通过这种方式、您可以查看两个器件之间是否实际传输了任何数据。 完成此操作后、您可以上传传输的图像吗?

    我还建议阅读 《MSP430 MCU 上 eUSCI 和 USCI 串行通信常见问题解决方案》的第2和第3部分。 保持更新!

    此致、  
    Caleb Overbay

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

    现在我没有示波器、所以我不得不等到星期六才制作探头。

    总之、我忘记了说我也尝试在没有进入低功耗模式(因此没有中断例程)的情况下进行轮询、结果表现良好:RX 和 TX 工作正常。
    此外:我首先尝试过它只是通过 USCI_A0与 MSP430通信、它运行良好、然后我添加了 USCI_A1部分代码并尝试与 ESP8266通信、但它不起作用、并且 USCI_A0部分也不起作用。

    在第54行{while (!UART_TX_READY)}的函数 send_char 中阻止的代码。

    希望这将有所帮助。

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

    您好、Samuele、

    我忽略了您进入 LPM3的情况。 这可能是问题所在。 请通读《  MSP430 MCU 上 eUSCI 和 USCI 串行通信常见问题解决方案》的第3.2节"在低功耗模式下使用 UART 的方法"。  

    看起来您是使用 SMCLK 来采购 UART、而该源在 LPM3中关闭。  您可以在《MSP430FR59xx 混合信号微控制器》第6.3节中的 LPM 中查看哪些时钟处于活动状态。 我看到您已经设置了一个32kHz LFXT 拉电流 ACLK、该拉电流在 LPM3中仍然有效。 您可以将 UART 通信设置为9600波特(来自 ACLK)、我希望问题可以解决。  

    此致、  

    Caleb Overbay

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

    您好 Caleb、

    我尝试将 LPM 模式更改为 LPM1、然后更改为 LMP0 (当然、检查 smclk 是否已启用)、但它不起作用。

    因此我尝试设置 ACLK、我不确定这是正确的方法、因为它给我在 UART0中带来了一些问题(以前效果很好)。

    如果这是错误的、您能告诉我吗?

    void init_uart_A0 (void)
    {
    // UART1端口
    // 2.0:TX
    // 2.1:RX
    P2SEL1 |=(BIT0 | BIT1);
    P2SEL0 &=~(BIT0 | BIT1);
    
    //------------------------------------
    // UART 的初始化
    //-无奇偶校验
    //- LSB 优先
    //-一个停止位
    //- 8位数据
    //- UART 模式(异步)
    //-使用 ACLK 时钟(速率= 32kHz)
    //-错误字符被拒绝
    //-无中断字符中断
    //-未处于休眠状态
    //-软件复位被禁用
    //-波特率:9600波特
    //------------------------------------
    UCA0CTLW0 = UCSWRST;//复位
    UCA0CTLW0 = UCSSEL_ACLK;
    //设置波特率
    UCA0BR0=3;
    UCA0BR1 = 0x00;
    UCA0MCTLW = UCOS16; //生成低频波特率所需
    UCA0IE |= UCRXIE; //启用 USCI_A0 RX 中断
    UCA0CTLW0 &=~UCSWRST; //取消复位
    }
    
    
    void init_uart_a1 (void)
    {
    // UART1端口
    // 2.5:TX
    // 2.6:RX
    P2SEL1 |=(BIT5 | BIT6);
    P2SEL0 &=~(BIT5 | BIT6);
    
    UCA1CTLW0 = UCSWRST;//复位
    UCA1CTLW0 |= UCSSEL_ACLK;
    //设置波特率
    UCA1BR0 = 3;
    UCA1BR1 = 0x00;
    //UCA1MCTLW |= UCBRF_8;
    UCA1MCTLW = UCOS16;
    UCA1IE |= UCRXIE; //启用 USCI_A1 RX 中断
    UCA1IE |= UCTXIE; //启用 USCI_A1 TX 中断
    UCA1CTLW0 &=~UCSWRST;//取消复位
    } 

    此致、

    Samuele

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    > UCA1IE |= UCRXIE; //启用 USCI_A1 RX 中断
    > UCA1IE |= UCTXIE; //启用 USCI_A1 TX 中断
    > UCA1CTLW0 &=~UCSWRST;//取消复位

    1) 1)在使 UART 退出复位状态后设置 IE 位。 (另请参见 SLAU36TE 21.3.1秒)。
    2) 2)完全不设置 TXIE。 您的 ISR 不处理它、因此它将干扰您的轮询模式代码。
    3) 3)在(单字节) Rx 中断期间发送字符串将(高概率)导致 Rx 数据丢失。 现在这不会影响您、因为您只需要选择"是"/"否"、但最终会出现这种情况。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Bruce、

    我已经完成了你推荐的工作、但它不起作用。

    [引用用户="Bruce McKenney47378"]

    1) 1)在使 UART 退出复位状态后设置 IE 位。 (另请参见 SLAU36TE 21.3.1秒)。

    [/报价]

    我想它不会改变、因为我要用一个掩码来设置它、并且我还会在正确的位置退出复位模式、屏蔽一个0。

    无论如何、我决定只使用 UART USCI_A0将 ESP TX 连接 到 MSP 调试接收、移除跳线、将 ESP Rx 连接到 MSP 发送器、这样我就无法通过串行监视器与 MSP 进行通信、但我可以接收 ESP 响应。 现在工作正常。

    感谢大家的回答!


    Samuele

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

    您好、Samuele、

    听到您能够让事情正常工作是很好的。 我同意 Bruce 提出的所有观点、并建议您在开发应用时将这些观点考虑在内。

    当您尝试从 LFXT 运行 UART 时、您说您遇到了一些问题。 这可能是由于晶体未正确振荡造成的。 在 init_clock()中,您将 ACLK 设置为来自 LFXT1,但不要检查任何故障标志以确保 LFXT1正确振荡。 下面显示了正确设置外部晶体的示例。 MSP430Ware 中还有一些示例 、可通过 TI Resource Explorer 在 CCS 中访问这些示例。

    // XT1设置
    CSCTL0_H = CSKEY >> 8; //解锁 CS 寄存
    器 CSCTL2 = SELA_LFXTCLK | SELS__DCOCLK | SELM_DCOCLK;
    CSCTL3 = DIVA__1 | DIVS__1; //设置所有分频
    器 CSCTL4 &=~LFXTOFF;
    执行
    {
    CSCTL5 &=~LFXTOFFG; //清除 XT1故障标志
    SFRIFG1 &=~OFIFG;
    } while (SFRIFG1&OFIFG); //测试振荡器故障标志
    CSCTL0_H = 0; //锁定 CS 寄存器 

    此致、  
    Caleb Overbay