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.

[参考译文] MSP430FR5739:MSP430 UART 未接收数据

Guru**** 1145030 points
Other Parts Discussed in Thread: MSP430FR5739, MSP-EXP430FR5739
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/814853/msp430fr5739-msp430-uart-not-receiving-data

器件型号:MSP430FR5739
主题中讨论的其他器件: MSP-EXP430FR5739

您好!

我正在从事一个项目、该项目将在器件中集成一个 MSP430FR5739。 这是我第一次使用微控制器、所以我只是想弄清楚如何使用每个子系统。 我正在尝试弄清楚如何将 UART 数据发送到芯片。 我有 MSP-EXP430FR5739实验板、我将使用它来测试我的代码、然后再转到现实器件。

为了测试 UART、我有如下所示的代码:

#include 
#include 
//UART 参数、直接从示例代码中提取。
#define SMCLK_115200 0
#define SMCLK_9600 1
#define ACLK_9600 2
//这些只是 SET_GPIO 函数的任意常数。
#define PIN_J0 99
#define PIN_J1 98

#define UART_MODE SMCLK_9600

void initGPIO()
{
PJDIR = 0b00000011;//PJ.1、PJ.0
}
void initClockTo16MHz ()
{
//时钟系统设置
CSCTL0_H = CSKKEY_H; //解锁 CS 寄存器
CSCTL1 = 0; //清除 DCO 设置
CSCTL1 |= DCORSEL | DCOFSEL_2; //将 DCO 设置为16MHz

//将所有时钟设置为从 DCO 运行
CSCTL2 = SELA_DCOCLK | SELM_DCOCLK | SELM_DCOCLK;
CSCTL3 = DIVA_0 | DIVS_0 | DIVM_0; //将所有分频器设置为/1

CSCTL4 |= XT1DRIVE_0;
CSCTL4 &= XT1OFF;

操作
{
CSCTL5 &=~XT1OFFG;
//清除 XT1故障标志
SFRIFG1 &=~OFIFG;
} while (SFRIFG1&OFIFG); //测试振荡器故障标志

CSCTL0_H = 0; //锁定 CS 寄存器
}

void initUART()
{
//将 USCI_A0配置为 UART 模式
UCA0CTLW0 = UCSWRST; //将 eUSCI 置于复位状态

#if UART_MODE = SMCLK_115200

UCA0CTLW0 |= UCSSEL_SMCLK; // CLK = SMCLK

//波特率设置
//使用系列用户指南中的表30-5
UCA0BR0 = 8;
UCA0BR1=0;
UCA0MCTLW |= UCOS16 | UCBRF_10 | 0xF700;//0xF700为 UCBRSx = 0xF7

#elif UART_MODE = SMCLK_9600

UCA0CTLW0 |= UCSSEL_SMCLK; // CLK = SMCLK

//波特率设置
//使用系列用户指南中的表30-5
UCA0BR0 = 104;
UCA0BR1=0;
UCA0MCTLW |= UCOS16 | UCBRF_2 | 0xD600;//0xD600为 UCBRSx = 0xD6

#Elif UART_MODE = ACLK_9600

UCA0CTLW0 |= UCSSEL_ACLK; // CLK = ACLK
//波特率计算
// 32768/(9600)= 3.4133
//分数部分= 0.4133
//使用系列用户指南中的表24-5
UCA0BR0=3; // 32768/9600
UCA0BR1=0;
UCA0MCTLW |= 0x9200;//0x9200为 UCBRSx = 0x92

其他
#错误"请将波特率指定为115200或9600 "
#endif

UCA0CTLW0 &=~UCSWRST; //初始化 eUSCI
}
void set_gpio (pin、state)
{
IF (引脚= PIN_J0)
{
IF (PJOUT & 0b00000001)
PJOUT &=(状态* 0b00000001);
其他
PJOUT |=(状态* 0b00000001);
}
IF (引脚==引脚_J1)
{
IF (PJOUT 和0b00000010)
PJOUT &=(状态* 0b00000010);
其他
PJOUT |=(状态* 0b00000010);
}
}
void delay_milliseconds (int duration)
{
//此处的每个循环将等待1ms (因为时钟为16MHz),直到持续时间为空。
while (持续时间)
{
_DELAY_CYCLES (16000);
持续时间--;
}
}

//*********
int main (void)
{
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器


//UART 内容就在这里
initClockTo16MHz();
inituart();
initGPIO();

while (1)
{
delay_milliseconds (1000);
IF (UCA0IFG 和 UCRXIFG)
{
SET_GPIO (PIN_J1、1);
delay_milliseconds (1000);
SET_GPIO (PIN_J1、0);
}
SET_GPIO (PIN_J0、1);
delay_milliseconds (1000);
SET_GPIO (PIN_J0、0);
}
} 

我知道这个代码可以大大改进、我应该使用中断、但是现在我只想获得一些证据、证明我的电路板正在接收 UART 数据。 根据我的理解、我的代码应该一直运行、一直闪烁 J0 LED、直到它接收到 UART 数据。 一旦它接收到数据、UCRXIFG 标志应该被激活、因此 UCA0IFG 和 UCRXIFG 应该返回"真"、并且它应该使 J1 LED 闪烁一次。 当我从计算机上的终端发送数据(使用 Arduino IDE 中的串行监视器、波特率设置为9600)时、我不会看到第二个闪烁的 LED。 我在 RXD 线路上连接了一个示波器、以确认正在发送数据。 连接示波器后、我在计算机上的串行监视器中打了一个 R。 我测量了一个到达的波形(其中 H 为高电平、L 为低电平):HHHHHHHHHHHHHHHHHLLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLHLLLHLLLHLHHHHHHHHHHHHHHHH。 我使用 ASCII 表将这些数据分开、它显示了一个开始位、一个 R、一个停止位、一个开始位、一个 NL 线路馈送和一个最终停止位(这些位与返回其休眠高电平状态的信号混合)。 因此、正确的数据肯定会发送到电路板。 我在电路板上设置了所有跳线、以便按照其出现的方式进行排列、跳线全部对齐以跨电路板上的虚线。 那么、如果我已经验证了电路板上存在正确的数据、那么为什么我的代码没有使 J1 LED 闪烁、因为发送 R 应该会导致 UCRXIFG 标志被置位? 我想我在 UART 设置中做了一切、最终得到了9600波特率、一个停止位、并且无奇偶校验、但可能还有其他的事情我会错过吗?

遗憾的是、Resource Explorer 中的所有示例代码都使用中断、我还不希望这样做。 再说一次、在我继续处理中断及其工作方式之前、只需尝试通过简单的线性执行编程开始让我的脚湿透。 谢谢!

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

    尊敬的 Thomas:

    感谢您发帖、我们将开始研究这个问题。

    祝你一切顺利、

    Colin Adema

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

    尊敬的 Thomas:

    我相信您忘记了设置 eUSCIA0 UART 引脚来提供它们的替代功能。 在您的代码中、它们当前只是用作 GPIO 引脚、因此即使在线路上、它们也不会检测到任何 UART 数据。

    在 GPIO 初始化或 UART 初始化中写入这2行会将它们配置为 UART 引脚:

    P2SEL1 |= BIT0 + BIT1;
    P2SEL0 &=~(BIT0 + BIT1);

    我已经对此进行了测试、并且能够使两个 LED 闪烁。

    祝你一切顺利、

    Colin Adema

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

    太棒了! 这就是诀窍! 非常感谢!

    编辑:实际上、我不确定。 因此、是的、这使得芯片能够接收数据、但我实际上无法读取这些数据。 一旦我进入"IF (UCA0IFG 和 UCRXIFG)"块、我将尝试说"long received = UCA0RXBUF"、然后根据接收到的内容做出决策。 但不管我发送到 UART 中什么、我最终都只接收到 UCA0RXBUF 中的换行符(0x000A)。 当我向 UART 发送数据时、我只能检索最后一个字符。 如果我发送的字符没有后缀换行符、则它会成功接收到该单个字符。 但是、我希望能够发送一串字符、从而导致发生行为。 我希望能够一次从 UCA0RXBUF 中读取一个字符、但在我有机会从缓冲区复制到变量之前、每个传入的字符看起来好像会启动 RX 缓冲区中的任何内容。 我是否缺少一个"技巧"来执行此操作?

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

    尊敬的 Thomas:

    当您尝试修改代码以接收字符串时、您的代码中是否仍然存在这些延迟? 当轮询以读取多个字节时、这些延迟将对您有效。

    例如、如果您在 delay_milliseconds (1000)行中发送字符串、则数据将在您等待检查是否收到任何数据时填充缓冲区。 在您检查时、最后一个数据字节将是唯一剩下的内容、这就是您见证该行为的原因。

    删除这些延迟将解决您发布的代码中的问题、我可以通过创建接收缓冲区数组并使用"Hello World!"等示例字符串进行测试 并且能够看到缓冲区中的所有数据。 但是、如果您计划编写更多的代码和/或希望保留代码中的延迟、我强烈建议您使用中断、以便您可以在发送数据后几乎立即存储接收到的数据。

    祝你一切顺利、

    Colin Adema

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

    明白。 我认为缓冲器会挂起、或者尽管存在延迟。 感谢您的帮助!