我遇到了MSP432 eUSI_A UART丢失UCAxIFG寄存器中的UCTXIFG标志导致发射器挂起的问题。 仅在同时传输和接收字符时出现问题。 如果我没有接收,发射器工作正常,但当它开始接收字符时,UCTXIFG标志停止发出,并且发射器中断不会发生。 (所有这些都是在尝试在微型和PC之间实施数据传输协议时发现的,我在过去的几年中使用各种MSP430s和TIVA芯片多次实施了这种协议,没有遇到任何问题。) 我设法将这归结为一个非常小的演示程序,它可靠地再现了问题。 在此程序中,每次发生EUSCI_A_UART_Transmit_interrupT_flag中断时,我都会发送'c'。 每次发生EUSCI_A_UART_receive中断标志中断时,我都会收到该字符并忽略它。 我连接到PC上的超级终端,并收到一串'c'字符,只要我不尝试将字符键入到微型计算机,这些字符就会继续。 当我将字符键入到微电脑时(有时会占用大量字符),它最终将停止发送。 当我查看该程序正在执行的操作时,我发现UCTXIFG已关闭。 它保持关闭,并且EUSCI_A_UART_Transmit_InterrupT_flag中断未发生。 但它接收到的字符正常。
我正在使用红色MSP432 Launchpad,版本C MSP432和1.50 驱动程序库的00.12 版本。
要重现此问题:
1.使用00.12 1.50 编译并链接程序,然后将其下载到MSP432启动板。
2.在PC上打开超级终端,并以92.16万波特,8位,无奇偶校验,无流控制的方式连接到Launchpad的用户UART端口。
3.启动公共卫生和社会福利部的方案432。 您应该会在超级终端上看到连续的'c'字符串。
4.在键盘上键入fast to HyperTerminal。 您可能需要在键盘上按几秒钟。 最后,'c'字符将停止。
5.回顾MSP432计划,您将看到UCTXIFG已关闭,不再继续。
该程序还包含我一直使用的变通办法的代码。 如果取消注释"#define KLUDGEY_FIX"语句,则编译变通办法。 然后,代码将尝试使用EUSCI_A_UART_Transmit_Complete_interrupt来检测UCTXIFG的丢失并输出到TXBUF。 这会导致所有中断恢复,并且EUSCI_A_UART_Transmit_InterrupT_flag中断再次开始发生。 使用此代码时,我无法使用超级终端使传输器出现故障。
我尝试过较慢波特率的代码。 我仍然能够使其失败,但需要在超级终端上输入更多内容。
此错误似乎与勘误表(SSLAZ610J)中为Rev C和Rev D处理器报告的许多eUSCI错误相似,但不完全相同。 虽然我的变通办法似乎可以正常工作,但最好能够真正解决问题,因为我正在处理的设备最终将是一种医疗设备,必须符合严格的可靠性标准。
/*
对于波特率9600和SMCLK =2400万,设置BRDIV=156,UCxBRF=4,UCxBRS=0
对于波特率11.52万和SMCLK =2400万,设置BRDIV=13,UCxBRF=0,UCxBRS=37
对于波特率23.04万和SMCLK =2400万,设置BRDIV=6,UCxBRF=8,UCxBRS=32
对于波特率46.08万和SMCLK =2400万,设置BRDIV=3,UCxBRF=4,UCxBRS=2
对于波特率92.16万和SMCLK =2400万,设置BRDIV=1,UCxBRF=10,UCxBRS=0
*/
/* DriverLib包括*/
#include "driverlib.h"
/*标准包括*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#Define Launchpad_only
// Launchpad上P2上的RGB LED针脚
#define P2_RED_LED_H GPIO _PIN0
#define P2_BLUE_LED_H GPIO _PIN2
#define P2_GREG_LED_H GPIO _PIN1
#define P2_All_LEDs_H (P2_RED_LED_H|P2_BLUE_LED_H|P2_GREG_LED_H)
//#define KLUDGEY_FIX实现错误的解决方法,其中eUSI_A单元在UCAxIFG寄存器中丢失UCTXIFG标志。
//#定义KLUDGEY_FIX
//假定SMCLK =2400万,将波特率设置为92.16万
#define A0_BRDIV 1.
#define A0_UCxBRF 10.
#define A0_UCXBRS 0
const eUSI_UART_Config uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK时钟源
A0_BRDIV, // BRDIV
A0_UCxBRF, // UCxBRF
A0_UCxBRS, // UCxBRS
EUSCI_A_UART_NO_PARity ,//无奇偶校验
EUSCI_A_UART_LSB优先, // LSB优先
EUSCI_A_UART_ONE_STOP_BIT ,//一个停止位
EUSCI_A_UART_MODE, // UART模式
EUSCI_A_UART_ORTS_Ooversampling_BAUDRATE_generation // Oversampling
};
空InitUart ()
{
/*在UART模式下选择WFP 1.2 和WFP 1.3 */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin (GPIO端口P1,GPIO _PIN2 | GPIO _PIN3,GPIO主要模块功能);
/*配置UART模块*/
MAP_UART_INITModule (EUSCI_A0_BASE,&uartConfig);
/*启用UART模块*/
MAP_UART_enableModule (EUSCI_A0_BASE);
/*启用中断*/
#ifdef KLUDGEY_FIX
MAP_UART_enableInterrupt (EUSCI_A0_BASE,EUSCI_A_UART_receive _interrupt | EUSCI_A_UART_Transmit_interrupt | EUSCI_A_UART_Transmit_Complete_interrupt);
#否则
MAP_UART_enableInterrupt (EUSCI_A0_BASE,EUSCI_A_UART_receive _interrupt | EUSCI_A_UART_Transmit_interrupt);
#endif
MAP_Interrupt_enableInterrupt (INT_EUSCIA0);
//开始传输字符
MAP_UART_HESRData(EUSI_A0_base,(uint_fast8_t)'c');
}
// ESCI A0 UART接收ISR -将数据回波到PC主机
void EUSCIA0_IRQHandler (void)
{
UINT32_t status = MAP_UART_getEnabableInterruptStatus(EUSSCI_A0_base);
MAP_UART_CLEARInterruptFlag (EUSCI_A0_BASE,状态);
IF (状态和EUSCI_A_UART_receive中断标志)
{
//丢弃收到的数据
MAP_UART_receiveData (EUSCI_A0_BASE);
}
IF (状态和EUSCI_A_UART_Transmit_InterrupT_flag)
{
//在此处传输下一个字节
MAP_UART_HESRData(EUSI_A0_base,(uint_fast8_t)'c');
}
#ifdef KLUDGEY_FIX
否则
{
//尝试缓解UCTXIFG标志丢失的问题。 当您以高波特率传输时,似乎会发生这种情况
//同时也接收字节。 该错误似乎与一些USC144等USCI勘误表项目类似,但在本例中,我们是
//正在使用与MCLK同步的时钟源。 在此修复程序中,我们尝试使用UCTXCPTIFG (传输完成)来检测时间
//我们可以在丢失UCTXIFG标志后发送下一个字符。 勘误表项目USGI42表明,这也可能存在问题,
//但到目前为止的测试表明此修复程序有效。
UINT_fast8_t intEnabled;
// UART_getEnabledInterruptStatus将仅返回EUSCI_A_UART_receive中断标志或EUSCI_A_UART_Transmit_InterrupT_flag SO
//我们必须以这种方式获得EUSCI_A_UART_Transmit_complete_interrupT_flag。
状态= UART_getInterruptStatus (EUSCI_A0_BASE,EUSCI_A_UART_Transmit_Complete_Interrupt_flag);
intEnabled = EUSCI_A_CMSIS (EUSSCI_A0_base)->IE;
IF (未启用和状态)
{
UART_clearInterruptFlag (EUSCI_A0_BASE,EUSCI_A_UART_Transmit_Complete_InterrupT_flag);
//在没有设置TXIFG的情况下不可能完成传输,但当发射器挂起时,我们就能做到这一点
如果(!BISTBAND_PERI(EUSI_A_CMIS(EUSSCI_A0_base)->IFG, EUSCI_A_IFG_TXIFG_OFS))
EUSCI_A_CMSIS (EUSI_A0_base)->TXBUF ='X'; //尝试重新启动发射器
}
}
#endif // KLUDGEY_FIX
}
内部主(无效)
{
/*停止监视程序*/
MAP_WDT_A_HoldTimer();
//设置核心电压和闪存等待状态以支持以48 MHz运行
MAP_PCM_setPowerState(PCM_AM_DCC_VCORE1);
MAP_FlashCTL_setWaitState(FLASH_BANK0, 1);
MAP_FlashCTL_setWaitState(FLASH_Bank1, 1);
/*将GPIO配置为输出*/
MAP_GPIO_setAsOutputPin (GPIO端口P1,GPIO _PIN0);
#ifdef Launchpad_only //设置RGB LED输出引脚
MAP_GPIO_setAsOutputPin (GPIO端口P2,P2_All_LEDs_H);
MAP_GPIO_setOutputLowOnPin (GPIO端口P2,P2_All_LEDs_H);
#endif
//将ACLK设置为VLOCLK (9.4 kHz)
MAP_CS_INITClockSignal (CS_ACLK,CS_VLOCLK_SELECT,CS_CLock_diver_1);
/*将DCO设置为48MHz */
MAP_CS_setDCOCenteredFrequency (CS_DCO_Frequency_48);
//将DCO用于MCLK和SMCLK
MAP_CS_INITClockSignal (CS_MCLK,CS_DCOCLK_SELECT,CS_CLock_diver_1);
MAP_CS_INITClockSignal (CS_SMCLK,CS_DCOCLK_SELECT,CS_CLock_DICROLOR_2);
/*启用FPU并启用堆栈(用于ISR)*/
MAP_FPU_enableModule();
MAP_FPU_enableLazyStacking();
//初始化UART并传输第一个字符
InitUart();
/*启用主中断*/
MAP_Interrupt_enableMaster();
//所有操作现在都处于中断级别
while (true)(对)
MAP_PCM_GotoLPM0();
}