MSP430F5529 DriverLib 库函数学习笔记(四)UART通信


平台:Code Composer Studio 10.3.1

MSP430F5529 LaunchPad™ Development Kit
(MSP‑EXP430F5529LP)

硬知识

USCI通信模块

       通用串行通信接口(USCI)模块支持多种串行通信模式,不同的USCI模块支持不同的通信模式。每个不同的USCI模块以不同的字母命名,如USCI_A、USCI_B等。如果在一个MSP430单片机上实现了不止一个相同的USCI模块,那么这些模块将以递增的数字命名。例如,当一个MSP430单片机支持两个USCI_A模块时,这两个模块应该被命名为USCI_A0和USCI_A1。具体可查阅相关芯片的数据手册,来确定该芯片具有哪些USCI通信模块。
       USCI_Ax模块支持以下模式:
 UART通信模式;
 具有脉冲整形的IrDA通信模式;
 具有自动波特率检测的LIN通信模式;
 SPI通信模式。
       USCI_Bx模块支持以下通信模式:
 I2C通信模式;
 SPI通信模式。

USCI的UART模式

       异步串行通信(UART)的特点如下:
 传输7位或8位数据,可采用奇校验、偶校验或者无校验;
 具有独立的发送和接收移位寄存器;
 具有独立的发送和接收缓冲寄存器;
 支持最低位优先或最高位优先的数据发送和接收方式;
 内置多处理器系统,包括线路空闲和地址位通信协议;
 通过有效的起始位检测将MSP430单片机从低功耗模式下唤醒;
 可编程实现分频因子为整数或小数的波特率;
 具有用于检测错误或排除错误的状态标志位;
 具有用于地址检测的状态标志位;
 具有独立的发送和接收中断能力。
在UART模式下,USCI_Ax的结构如图所示。
在这里插入图片描述

1. USCI初始化和复位

       通过产生一个PUC复位信号或者置位UCSWRST控制位可以使USCI模块复位。在产生一个PUC复位信号之后,系统可自动置位UCSWRST控制位,保持USCI模块在复位状态。若UCSWRST控制位置位,将重置UCRXIE、UCTXIE、UCRXIFG、UCRXERR、UCBRK、UCPE、UCOE、UCFE、UCSTOE和UCBTOE寄存器,并置位UCTXIFG中断标志位。清除UCSWRST控制位,USCI模块才可进行工作。
因此,可按照以下步骤进行初始化或重新配置USCI模块:
① 置位UCSWRST控制位;
② 在UCSWRST=1时,初始化所有的USCI寄存器(包括UCTxCTL1);
③ 将相应的引脚端口配置为UART通信功能;
④ 软件清除UCSWRST控制位;
⑤ 通过设置接收或发送中断使能控制寄存器UCRXIE和UCTXIE或两者之一,使能中断。

2. 异步通信字符格式

       如图所示,异步通信字符格式由5个部分组成:一个起始位、7位或8位数据位、一个奇/偶/无校验位、一个地址位和一个或两个停止位。其中,用户可以通过软件设置数据位、停止位的位数,还可以设置奇偶校验位的有无。通过选择时钟源和波特率寄存器的数据来确定传输速率。UCMSB控制位用来设置传输的方向和选择最低位还是最高位先发送。一般情况下,对于UART通信选择先发送最低位。
在这里插入图片描述

3. 异步多机通信模式

       当两个设备异步通信时,不需要多机通信协议。当3个或更多的设备通信时,USCI支持两种多机通信模式,即线路空闲和地址位多机模式。信息以一个多帧数据块,从一个指定的源传送到一个或多个目的位置。在同一个串行链路上,多个处理机之间可以用这些格式来交换信息,实现在多处理机通信系统间的有效数据传输。控制寄存器的UCMODEx控制位可用来确定这两种模式,这两种模式具有唤醒发送、地址特征和激活等功能。在两种多处理机模式下,USCI数据交换过程可以用数据查询方式,也可以用中断方式来实现。
(1)线路空闲多机模式
       当UCMODEx控制位被配置为01时,USCI就选择了线路空闲多机模式,如图7.1.3所示。在这种模式下,发送和接收数据线上的数据块被空闲时间分割。图(a)为数据块传输的总体示意,图(b)为每个数据块中字符的传输示意。在图(a)中,在字符的一个或两个停止位之后,若收到10个以上的1,则表示检测到接收线路空闲。在识别到线路空闲后,波特率发生器就会被关断,直到检测到下一个起始位才会重新被启动。当检测到空闲线路后,将置位UCIDLE标志位。在图(b)中,每两个数据块之间的线路空闲时间应少于10个空闲周期,这样数据才能正确、正常地传输。
在这里插入图片描述
(2)地址位多机模式
       当UCMODEx控制位被配置为10时,USCI就选择了地址位多机模式。在这种模式下,字符包含一个附加的位作为地址标志。地址位多机模式的格式如图所示。数据块的第1个字符带有一个置位的地址位,用以表明该字符是一个地址。当接收到的字符地址位置位且被传送到UCAxRXBUF接收缓冲寄存器中,USCI模块将置位UCADDR标志位。
在这里插入图片描述

4. 自动波特率检测

       当UCMODEx控制位被配置为11时,就选择了带自动波特率选择的UART模式。对于UART自动波特率检测方式,在数据帧前面会有一个包含打断和同步域的同步序列。当在总线上检测到11个或更多个0时,被识别为总线打断。如果总线打断的长度超过21位时间长度,则将置位打断超时错误标志UCBTOE。当接收打断或同步域时,USCI不能发送数据。同步域在打断域之后,示意图如左图所示。
       在1个字节里,同步域包含数据055h,如右图所示。同步是基于这种模式的第一个下降沿和最后一个下降沿之间的时间测量,如果通过置位UCABDEN控制位,将使能自动波特率检测功能,则发送波特率发生器通常用于时间的测量。否则,在该模式下只接收并不测量。测量的结果将被移送到波特率控制寄存器(UCAxBR0、UCAxBR1和UCAxMCTL)中。如果同步域的长度超过了可测量的时间,将置位同步超时错误标志位UCSTOE。
在这里插入图片描述

5. IrDA编码和解码

       当置位UCIREN控制位时,将会使能IrDA编码器和解码器,并对IrDA通信提供硬件编码和解码。
(1)IrDA编码
       IrDA编码器会在UART数据流的基础上,对UART传输中遇到的每一位0发送一个脉冲进行编码,编码方式如图所示,脉冲的持续时间由UCIRTXPLx进行定义。

(2)IrDA解码
       当UCIRRXPL=0时,解码器检测到高电平,否则检测低电平。除了模拟抗尖峰脉冲滤波器,USCI内部还包含可编程数字滤波器,用户可通过置位UCIRRXFE控制位使能该内部可编程数字滤波器。当UCIRRXFE置位时,只有超过编程过滤长度的脉冲可以通过,短脉冲被丢弃。过滤器长度UCIRRXFLx的编程计算公式如下
在这里插入图片描述
在这里插入图片描述

6. 自动错误检测

       USCI模块接收字符时,能够自动进行校验错误、帧错误、溢出错误和打断状态检测。当检测到它们各自的状态时,会置位相应的中断标志位UCFE、UCPE、UCOE和UCBRK。当这些错误标志位置位时,UCRXERR也会被置位。各种错误的含义和标志如表所示。
在这里插入图片描述

7. USCI接收使能

       通过清除UCSWRST控制位可以使能USCI模块,此时,接收端准备接收数据并处于空闲状态,接收波特率发生器处于准备状态,但并没有产生时钟。
       起始位的下降沿可以使能波特率发生器。UART状态机可检测有效起始位,如果未检测到有效起始位,则UART状态机返回空闲状态同时停止波特率发生器;如果检测到有效起始位,则字符将会被接收。
       当选择线路空闲多机模式时(UCMODEx=01),在接收完一个字符之后,UART状态机检测空闲线路。若检测到一个起始位,则接收下一个字符。否则,如果在线路上检测到10个1,就会置位UCIDLE空闲标志位,并且UART状态机返回空闲状态同时波特率发生器被禁止。
       抑制接收数据脉冲干扰能够防止USCI模块意外启动,任何在UCAxRXD的时间少于抗尖峰脉冲时间tt(近似150ns)的短时脉冲都将被USCI忽略,紧接着进行初始化,如左图所示,若在UCAxRXD上的短时脉冲时间少于tt,USCI并没有开始接收数据。
       当一个尖峰脉冲时间长于tt,或者在UCAxRXD上发生一个有效的起始位,USCI开始接收工作并采用多数表决方式,如右图所示。如果多数表决没有检测到起始位,则USCI停止接收字符。
在这里插入图片描述

8. USCI发送使能

       通过清除UCSWRST控制位可以使能USCI模块,此时,发送端准备发送数据并处于空闲状态,发送波特率发生器处于准备状态,但是,并没有产生时钟。
       通过写数据到发送缓冲寄存器中,USCI就可以开始发送数据。波特率发生器开始工作,当发送移位寄存器为空时,在下一个BITCLK上,发送缓冲寄存器中的数据将被移送到发送移位寄存器中。
       在前一字节发送完成之后,只要发送缓冲寄存器UCAxTXBUF中有新数据,发送即可继续。若前一字节发送完成之后,发送缓冲寄存器UCAxTXBUF中并没有写入新的数据,发送端将返回空闲状态,同时停止波特率发生器。

9. UART波特率的产生

       USCI波特率发生器可以从非标准的时钟源频率中产生标准的波特率,可以通过UCOS16控制位选择系统提供的两种操作模式,分别为:产生低频波特率模式(UCOS16=0)和产生过采样波特率模式(UCOS16=1)。UART波特率的参考时钟来自于BRCLK,BRCLK可以通过UCSSELx控制位配置为外部时钟UCAxCLK或内部时钟ACLK或SMCLK。
(1)产生低频波特率模式
       当UCOS16=0时,选择低频波特率模式。该模式允许从低频时钟源产生标准的波特率(例如,从32768Hz晶振产生9600bps的波特率)。通过使用较低的输入频率,可以降低系统的功耗。注意:在高频输入或高分频设置下,使用这种模式,将导致在更小的窗口中采用多数表决方式,因此会降低多数表决法的优势。
       在低频模式下,波特率发生器使用1个预分频器和1个调制器产生时钟时序。在这种组合下,产生的波特率支持小数分频。在这种模式下,最大的USCI波特率是UART源时钟频率BRCLK的1/3。
       每一位的时序如图所示。对于接收的每一位,为了确定该位的值,采用多数表决法,即3取2表决法。每次表决时采样3次,最终该位的值至少在采样中出现两次。这些采样发生在(N/2-1/2),N/2和(N/2+1/2)个BRCLK周期处,如图中的方框所示,这里的N是每个BITCLK包含的BRCLKs的数值,图中的m为调制设置,具体请参见下表。
在这里插入图片描述
在这里插入图片描述
(2)产生过采样波特率模式
       当UCOS16=1时,选择过采样模式。该模式支持在较高的输入参考时钟频率下,产生较高的UART波特率。该模式的参考时钟为经预分频器和调制器产生的BITCLK16时钟,该时钟频率为BITCLK的1/16。因此,在计算分频系数时,需将波特率发生器的参考时钟频率除以16之后,再进行计算。例如,若波特率发生器的参考时钟BITCLK选择内部的SMCLK=1048576Hz,最终需要产生9600bps的波特率,首先将BITCLK除以16为65536Hz作为该模式下的波特率参考时钟,计算分频系数为n=65536/9600=6.83。
       这种组合方式支持BITCLK16和BITCLK产生不是整数倍的波特率,在这种情况下,最大的USCI波特率是UART源时钟频率的1/16。当UCBRx设置为0或1时,将忽略第一级分频器和调制器,BITCLK16等于BITCLK,在这种情况下,BITCLK16没有调制,因此将忽略UCBRFx位。
       BITCLK16的调制是建立在如下表所示的UCBRFx设置的基础之上的。表中的0和1表示m的值,m=1时所对应的BITCLK的周期比m=0时所对应的BITCLK的周期要长,具体原理请参考产生低频波特率模式下的调制原理。
在这里插入图片描述

10. UART波特率的设置(重要)

       设置方法:设置波特率时,首先要选择合适的时钟源。对于较低的波特率(9600bps以下),可以选择ACLK作为时钟源,这使得在LPM3模式下仍然能够使用串口。由于串口接收过程中有一个三取二表决逻辑,这需要至少3个时钟周期,因此要求分频系数必须大于3。所以,在波特率高于9600bps的情况下,应选择频率较高的SMCLK作为时钟源。在某些特殊应用中,也可以使用外部的时钟输入作为波特率发生器的时钟源。
对于给定的BRCLK时钟源,所使用的波特率将决定分频因子N,计算公式为
在这里插入图片描述
分频因子N通常不是一个整数值 ,因此至少需要一个分频器和一个调制器来尽可能接近分频因子。如果N等于或大于16,可以通过置位UCOS16选择过采样波特率产生模式。

(1)低频波特率设置

在低频模式下,分频因子的整数部分通过预分频器实现,配置方式为(其中INT为取整)
在这里插入图片描述

小数部分由调制器实现,配置方式为(round为取附近整数)
在这里插入图片描述
【例1】 在MSP430单片机中,使用ACLK作为串口时钟源,波特率设为4800bps。
       分析:在ACLK=32768Hz时产生4800bps波特率,需要的分频系数是32768/4800=6.83。整数部分为6,小数部分为0.83。将整数部分赋给UCA0BR寄存器,调制器分频余数为0.83 × 8 = 6.64,取最接近的整数7,因此将7赋给UCBRS控制位。

(2)过采样波特率设置

在过采样模式下,预分频设置为:
在这里插入图片描述
调制器设置为:
在这里插入图片描述
【例2】 在MSP430单片机中,使用SMCLK作为串口时钟源,波特率设置为9600bps。
       分析:在SMCLK=1048576Hz时产生9600bps波特率,需要的分频系数N=1048576/ 9600=109.23,大于16分频,因此应选择过采样波特率产生模式,预分频UCBR应设置为INT(N/16)=INT(6.83)=6。调制器UCBRF应设置为0.83 × 16 = 13.28,取最接近的整数13,因此将13赋给UCBRF控制位。
波特率设置也可直接参考下表
在这里插入图片描述
在这里插入图片描述
也可以从MSP430 USCI/EUSCI UART Baud Rate Calculation中获取

UART API(机翻)

USCI_A_UART API被分为几组功能:
USCI_A_UART模块的配置和控制的函数,
用于发送和接收数据的函数,
以及处理中断处理和处理DMA的函数。

USCI_A_UART的配置和控制函数:

USCI_A_UART_init(uint16_t baseAddress, USCI_A_UART_initParam ∗param)
//初始化函数
USCI_A_UART_enable(uint16_t baseAddress)
//使能UART模块
USCI_A_UART_disable(uint16_t baseAddress)
//失能UART模块
USCI_A_UART_setDormant(uint16_t baseAddress)
//将UART模块设置为休眠模式
USCI_A_UART_resetDormant(uint16_t baseAddress)
//从休眠模式重新启用UART模块

参数

baseAddress
是USCI_A_UART模块的基地址

USCI_A0_BASE
USCI_A1_BASE

USCI_A_UART_initParam 结构体

typedef struct USCI_A_UART_initParam {
    //! Selects Clock source.
    //! \n Valid values are:
    //! - \b USCI_A_UART_CLOCKSOURCE_SMCLK
    //! - \b USCI_A_UART_CLOCKSOURCE_ACLK
    uint8_t selectClockSource;
    //! Is the value to be written into UCBRx bits
    uint16_t clockPrescalar;
    //! Is First modulation stage register setting. This value is a pre-
    //! calculated value which can be obtained from the Device Users Guide.
    //! This value is written into UCBRFx bits of UCAxMCTLW.
    uint8_t firstModReg;
    //! Is Second modulation stage register setting. This value is a pre-
    //! calculated value which can be obtained from the Device Users Guide.
    //! This value is written into UCBRSx bits of UCAxMCTLW.
    uint8_t secondModReg;
    //! Is the desired parity.
    //! \n Valid values are:
    //! - \b USCI_A_UART_NO_PARITY [Default]
    //! - \b USCI_A_UART_ODD_PARITY
    //! - \b USCI_A_UART_EVEN_PARITY
    uint8_t parity;
    //! Controls direction of receive and transmit shift register.
    //! \n Valid values are:
    //! - \b USCI_A_UART_MSB_FIRST
    //! - \b USCI_A_UART_LSB_FIRST [Default]
    uint8_t msborLsbFirst;
    //! Indicates one/two STOP bits
    //! \n Valid values are:
    //! - \b USCI_A_UART_ONE_STOP_BIT [Default]
    //! - \b USCI_A_UART_TWO_STOP_BITS
    uint8_t numberofStopBits;
    //! Selects the mode of operation
    //! \n Valid values are:
    //! - \b USCI_A_UART_MODE [Default]
    //! - \b USCI_A_UART_IDLE_LINE_MULTI_PROCESSOR_MODE
    //! - \b USCI_A_UART_ADDRESS_BIT_MULTI_PROCESSOR_MODE
    //! - \b USCI_A_UART_AUTOMATIC_BAUDRATE_DETECTION_MODE
    uint8_t uartMode;
    //! Indicates low frequency or oversampling baud generation
    //! \n Valid values are:
    //! - \b USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION
    //! - \b USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION
    uint8_t overSampling;
} USCI_A_UART_initParam;

其中的clockPrescalar,firstModReg,secondModReg,overSampling
可在MSP430 USCI/EUSCI UART Baud Rate Calculation中获取

用于发送和接收数据的函数

USCI_A_UART_transmitData(uint16_t baseAddress, uint8_t transmitData)		
//通过UART模块传输一个字节
USCI_A_UART_receiveData(uint16_t baseAddress)								
//接收一个已发送到UART模块的字节。
USCI_A_UART_transmitAddress(uint16_t baseAddress, uint8_t transmitAddress)	
//Transmits the next byte to be transmitted marked as address depending on selected multiprocessor mode
USCI_A_UART_transmitBreak(uint16_t baseAddress)
//传输中断

参数

baseAddress
是USCI_A_UART模块的基地址

USCI_A0_BASE
USCI_A1_BASE

transmitData
UART模块要传输的数据
transmitAddress
is the next byte to be transmitted

管理USCI_A_UART中断和状态的函数

USCI_A_UART_enableInterrupt(uint16_t baseAddress, uint8_t mask)
//启用UART中断
USCI_A_UART_disableInterrupt(uint16_t baseAddress, uint8_t mask)
//失能UART中断
USCI_A_UART_getInterruptStatus(uint16_t baseAddress, uint8_t mask)
//获取当前UART中断状态。这将根据传递的标志返回UART模块的中断状态
USCI_A_UART_clearInterrupt(uint16_t baseAddress, uint8_t mask)
//清除UART中断源,使其不再断言。当使用中断向量生成器时,最高中断标志将自动清除
USCI_A_UART_queryStatusFlags(uint16_t baseAddress, uint8_t mask)
//获取当前UART状态标志。这将根据传递的标志返回UART模块的状态。

参数

baseAddress
是USCI_A_UART模块的基地址

USCI_A0_BASE
USCI_A1_BASE

mask
USCI_A_UART_enableInterrupt、
USCI_A_UART_disableInterrupt:

/*
is the bit mask of the interrupt sources to be enabled. Mask value is the logical
OR of any of the following:
*/
USCI_A_UART_RECEIVE_INTERRUPT	// - Receive interrupt
USCI_A_UART_TRANSMIT_INTERRUPT	// - Transmit interrupt
USCI_A_UART_RECEIVE_ERRONEOUSCHAR_INTERRUPT	// - Receive erroneous-character interrupt enable
USCI_A_UART_BREAKCHAR_INTERRUPT	// - Receive break character interrupt enable

USCI_A_UART_getInterruptStatus、
USCI_A_UART_clearInterrupt:

/*
is the masked interrupt flag status to be returned. Mask value is the logical OR
of any of the following:
*/
USCI_A_UART_RECEIVE_INTERRUPT_FLAG	// - Receive interrupt flag
USCI_A_UART_TRANSMIT_INTERRUPT_FLAG	// - Transmit interrupt flag

USCI_A_UART_queryStatusFlags:

/*
is the masked interrupt flag status to be returned. Mask value is the logical OR
of any of the following:
*/
USCI_A_UART_LISTEN_ENABLE
USCI_A_UART_FRAMING_ERROR
USCI_A_UART_OVERRUN_ERROR
USCI_A_UART_PARITY_ERROR
USCI_A_UART_BREAK_DETECT
USCI_A_UART_RECEIVE_ERROR
USCI_A_UART_ADDRESS_RECEIVED
USCI_A_UART_IDLELINE
USCI_A_UART_BUSY

DMA相关

USCI_A_UART_getReceiveBufferAddressForDMA(uint16_t baseAddress)
//返回UART DMA模块的RX缓冲区地址
USCI_A_UART_getTransmitBufferAddressForDMA(uint16_t baseAddress)
//返回UART DMA模块的TX缓冲区地址

参数

baseAddress
是USCI_A_UART模块的基地址

USCI_A0_BASE
USCI_A1_BASE

通过DriverLib库和硬件知识编写UART初始化函数

根据之前的知识,我们可以写出如下初始化函数
baseAddress的参数可选为
USCI_A0_BASE、USCI_A1_BASE,
分别对应P3.3、P3.4和P4.4、P4.5
Baudrate为目标波特率

bool UART_Init(uint16_t baseAddress, uint32_t Baudrate)
{
    float UART_Temp = 0;
    USCI_A_UART_initParam huart = {0};
	//将所用引脚复用为UART模式
    if(baseAddress == USCI_A0_BASE)         //P3.3, P3.4 = USCI_A0 TXD/RXD
    {
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN3);
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN4);
    }
    else if(baseAddress == USCI_A1_BASE)    //P4.4, P4.5 = USCI_A1 TXD/RXD
    {
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P4, GPIO_PIN4);
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN5);
    }
	//当目标波特率较低时,UART选用时钟源为ACLK,反之选择SMCLK
	//调用UCS_getACLK/UCS_getSMCLK前需正确调用UCS_setExternalClockSource函数,我已加到SystemClock_Init函数中
    if(Baudrate <= 9600)
    {
        huart.selectClockSource = USCI_A_UART_CLOCKSOURCE_ACLK;
        UART_Temp = (float)UCS_getACLK()/Baudrate;
    }
    else
    {
        huart.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK;
        UART_Temp = (float)UCS_getSMCLK()/Baudrate;
    }
	
    if(UART_Temp < 16)	//当分频因子小于16时,采用低频波特率设置
        huart.overSampling = USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;
    else	//反之,采用过采样波特率设置
    {
        huart.overSampling = USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;
        UART_Temp /= 16;
    }

    huart.clockPrescalar = (int)UART_Temp;

    if(huart.overSampling == USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION)
    {	//低频波特率设置	UCBRSx
        huart.secondModReg = (int)((UART_Temp - huart.clockPrescalar) * 8);
    }
    else
    {	//过采样波特率设置 UCBRFx
        huart.firstModReg = (int)((UART_Temp - huart.clockPrescalar) * 16);
    }

    huart.parity = USCI_A_UART_NO_PARITY;
    huart.msborLsbFirst = USCI_A_UART_LSB_FIRST;
    huart.numberofStopBits = USCI_A_UART_ONE_STOP_BIT;
    huart.uartMode = USCI_A_UART_MODE;

    if (STATUS_FAIL == USCI_A_UART_init(baseAddress, &huart))
    {	//初始化对应串口
        return STATUS_FAIL;
    }

    //Enable UART module for operation 使能对应串口
    USCI_A_UART_enable(baseAddress);	

    //Enable Receive Interrupt 启用串口中断
    USCI_A_UART_clearInterrupt(baseAddress, USCI_A_UART_RECEIVE_INTERRUPT);	
    USCI_A_UART_enableInterrupt(baseAddress, USCI_A_UART_RECEIVE_INTERRUPT);	

    return STATUS_SUCCESS;
}

串口中断服务函数 接收一个字符就回发一个

//******************************************************************************
//
//This is the USCI_A0 interrupt vector service routine.
//
//******************************************************************************
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR (void)
{
    uint8_t receivedData = 0;
    switch (__even_in_range(UCA0IV,4))
    {
        //Vector 2 - RXIFG
        case 2:
            receivedData = USCI_A_UART_receiveData(USCI_A0_BASE);
            USCI_A_UART_transmitData(USCI_A0_BASE,receivedData);
            break;
        default:
            break;
    }
}

//******************************************************************************
//
//This is the USCI_A1 interrupt vector service routine.
//
//******************************************************************************
#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR (void)
{
    uint8_t receivedData = 0;
    switch (__even_in_range(UCA1IV,4))
    {
        //Vector 2 - RXIFG
        case 2:
            receivedData = USCI_A_UART_receiveData(USCI_A1_BASE);
            USCI_A_UART_transmitData(USCI_A1_BASE,receivedData);
            break;
        default:
            break;
    }
}

原理图的串口部分

USCI_A0 UART对应P3.3、P3.4
在这里插入图片描述
USCI_A1 UART对应P4.4、P4.5
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如图所示,MSP430F5529的USCI_A1 UART 通过 eZ-FET 与USB通讯
在这里插入图片描述
换句话说,插上microUSB后识别到的串口应为USCI_A1 UART

上机实战

整个源文件如下

#include "driverlib.h"

#define MCLK_IN_HZ      25000000

#define delay_us(x)     __delay_cycles((MCLK_IN_HZ/1000000*(x)))
#define delay_ms(x)     __delay_cycles((MCLK_IN_HZ/1000*(x)))

void SystemClock_Init(void)
{
    PMM_setVCore(PMM_CORE_LEVEL_3);     //高主频工作需要较高的核心电压

    //XT1引脚复用
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4);
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN5);

    //起振XT1
    UCS_turnOnLFXT1(UCS_XT1_DRIVE_3,UCS_XCAP_3);

    //XT2引脚复用
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN2);
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);

    //起振XT2
    UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);

    //XT2作为FLL参考时钟,先8分频,再50倍频 4MHz / 8 * 50 = 25MHz
    UCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_8);
    UCS_initFLLSettle(25000, 50);

    //XT1作为ACLK时钟源 = 32768Hz
    UCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);

    //DCOCLK作为MCLK时钟源 = 25MHz
    UCS_initClockSignal(UCS_MCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);

    //DCOCLK作为SMCLK时钟源 = 25MHz
    UCS_initClockSignal(UCS_SMCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);

    //设置外部时钟源的频率,使得在调用UCS_getMCLK, UCS_getSMCLK 或 UCS_getACLK时可得到正确值
    UCS_setExternalClockSource(32768, 4000000);
}

bool UART_Init(uint16_t baseAddress, uint32_t Baudrate)
{
    float UART_Temp = 0;
    USCI_A_UART_initParam huart = {0};

    if(baseAddress == USCI_A0_BASE)         //P3.3, P3.4 = USCI_A0 TXD/RXD
    {
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN3);
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN4);
    }
    else if(baseAddress == USCI_A1_BASE)    //P4.4, P4.5 = USCI_A1 TXD/RXD
    {
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P4, GPIO_PIN4);
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN5);
    }

    if(Baudrate <= 9600)
    {
        huart.selectClockSource = USCI_A_UART_CLOCKSOURCE_ACLK;
        UART_Temp = (float)UCS_getACLK()/Baudrate;
    }
    else
    {
        huart.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK;
        UART_Temp = (float)UCS_getSMCLK()/Baudrate;
    }

    if(UART_Temp < 16)
        huart.overSampling = USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;
    else
    {
        huart.overSampling = USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;
        UART_Temp /= 16;
    }

    huart.clockPrescalar = (int)UART_Temp;

    if(huart.overSampling == USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION)
    {
        huart.secondModReg = (int)((UART_Temp - huart.clockPrescalar) * 8);
    }
    else
    {
        huart.firstModReg = (int)((UART_Temp - huart.clockPrescalar) * 16);
    }

    huart.parity = USCI_A_UART_NO_PARITY;
    huart.msborLsbFirst = USCI_A_UART_LSB_FIRST;
    huart.numberofStopBits = USCI_A_UART_ONE_STOP_BIT;
    huart.uartMode = USCI_A_UART_MODE;

    if (STATUS_FAIL == USCI_A_UART_init(baseAddress, &huart))
    {
        return STATUS_FAIL;
    }

    //Enable UART module for operation
    USCI_A_UART_enable(baseAddress);

    //Enable Receive Interrupt
    USCI_A_UART_clearInterrupt(baseAddress, USCI_A_UART_RECEIVE_INTERRUPT);
    USCI_A_UART_enableInterrupt(baseAddress, USCI_A_UART_RECEIVE_INTERRUPT);

    return STATUS_SUCCESS;
}

int main(void)
{
    WDT_A_hold(WDT_A_BASE);
    SystemClock_Init();

    UART_Init(USCI_A1_BASE, 115200);

    //interrupts enabled
    __bis_SR_register(GIE);

    while(1)
    {

    }
}

//******************************************************************************
//
//This is the USCI_A0 interrupt vector service routine.
//
//******************************************************************************
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR (void)
{
    uint8_t receivedData = 0;
    switch (__even_in_range(UCA0IV,4))
    {
        //Vector 2 - RXIFG
        case 2:
            receivedData = USCI_A_UART_receiveData(USCI_A0_BASE);
            USCI_A_UART_transmitData(USCI_A0_BASE,receivedData);
            break;
        default:
            break;
    }
}

//******************************************************************************
//
//This is the USCI_A1 interrupt vector service routine.
//
//******************************************************************************
#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR (void)
{
    uint8_t receivedData = 0;
    switch (__even_in_range(UCA1IV,4))
    {
        //Vector 2 - RXIFG
        case 2:
            receivedData = USCI_A_UART_receiveData(USCI_A1_BASE);
            USCI_A_UART_transmitData(USCI_A1_BASE,receivedData);
            break;
        default:
            break;
    }
}


在main函数中,通过

UART_Init(USCI_A1_BASE, 115200);	

初始化我们用到的串口
连上串口调试助手,成功回显
在这里插入图片描述
修改波特率,通讯仍能成功
在这里插入图片描述
在这里插入图片描述

评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乙酸氧铍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值