TI中文支持网
TI专业的中文技术问题搜集分享网站

MSP430 UART学习分享-基于MSP-EXP430FR5969

本身从事硬件工作,最近心血来潮,用我手上的MSP-EXP430FR5969学习UART,接下来会发布SPI,I2C的文档。纯属分享学习经历,有什么错误请大家积极指出。参考文档的下载链接我一并给出,图片好像显示不出来,我把PDF版本一起放进来,直接导出来的,没有排版,大家别介意。

http://www.ti.com.cn/cn/lit/ds/zhcsch3e/zhcsch3e.pdf

http://www.ti.com.cn/cn/lit/ug/slau367n/slau367n.pdf

下面开始:

实例代码:
//  MSP430FR59xx Demo – USCI_A0 External Loopback test @ 115200 baud
//
//  Description: This demo connects TX to RX of the MSP430 UART
//  The example code shows proper initialization of registers
//  and interrupts to receive and transmit data. If data is incorrect P1.0 LED is
//  turned ON.
//  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = 1MHz
//
//
//                MSP430FR5969
//             —————–
//       RST -|     P2.0/UCA0TXD|—-|
//            |                 |    |
//           -|                 |    |
//            |     P2.1/UCA0RXD|—-|
//            |                 |
//            |             P1.0|—> LED
//
//   P. Thanigai
//   Texas Instruments Inc.
//   August 2012
//   Built with CCS V4 and IAR Embedded Workbench Version: 5.5
//******************************************************************************
#include <msp430.h>
volatile unsigned char RXData = 0;
volatile unsigned char TXData = 1;
int main(void)
{
  WDTCTL = WDTPW | WDTHOLD;                 // Stop watchdog
  // Configure GPIO
  P1OUT &= ~BIT0;                           // Clear P1.0 output latch
  P1DIR |= BIT0;                            // For LED on P1.0
  P2SEL1 |= BIT0 | BIT1;                    // USCI_A0 UART operation
  P2SEL0 &= ~(BIT0 | BIT1);
  // Disable the GPIO power-on default high-impedance mode to activate
  // previously configured port settings
  PM5CTL0 &= ~LOCKLPM5;
  // Configure USCI_A0 for UART mode
  UCA0CTLW0 = UCSWRST;                      // Put eUSCI in reset
  UCA0CTL1 |= UCSSEL__SMCLK;                // CLK = SMCLK
  UCA0BR0 = 8;                              // 1000000/115200 = 8.68
  UCA0MCTLW = 0xD600;                       // 1000000/115200 – INT(1000000/115200)=0.68
                                            // UCBRSx value = 0xD6 (See UG)
  UCA0BR1 = 0;
  UCA0CTL1 &= ~UCSWRST;                     // release from reset
  UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt
  while (1)
  {
    while(!(UCA0IFG & UCTXIFG));
    UCA0TXBUF = TXData++;                     // Load data onto buffer
  }
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG))
  {
    case USCI_NONE: break;
    case USCI_UART_UCRXIFG:
      RXData = UCA0RXBUF;                   // Read buffer
      if(RXData != TXData)                  // Check value
      {
        P1OUT |= BIT0;                      // If incorrect turn on P1.0
          while(1);                         // Trap CPU
      }
      TXData++;                             // increment data byte
      break;
    case USCI_UART_UCTXIFG: break;
    case USCI_UART_UCSTTIFG: break;
    case USCI_UART_UCTXCPTIFG: break;
  }
}
分析:
1、对于MSP430单片机,如果是要验证程序的话,首先需要关闭看门狗定时器,以保证正常调试。在产品量产后,可以不关闭看门狗来防止系统死机,但需要计算程序执行时间,进行喂狗操作。
通过以下代码关闭看门狗。
    WDTCTL = WDTPW | WDTHOLD;
其中:WDTPW = 0x5A00, WDTHOLD = 0x0080. 写入密码并关闭看门狗。
2、配置GPIO口。
  // Configure GPIO
  P1OUT &= ~BIT0;                           // Clear P1.0 output latch
  P1DIR |= BIT0;                            // For LED on P1.0
通过下面的文档说明可以知道如何配置:
12.2 Digital I/O Operation
The digital I/O are configured with user software. The setup and operation of the digital I/O are discussed
in the following sections.
12.2.1 Input Registers (PxIN)
Each bit in each PxIN register reflects the value of the input signal at the corresponding I/O pin when the
pin is configured as I/O function. These registers are read only.
• Bit = 0: Input is low
• Bit = 1: Input is high
NOTE: Writing to read-only registers PxIN
Writing to these read-only registers results in increased current consumption while the write
attempt is active.
12.2.2 Output Registers (PxOUT)
Each bit in each PxOUT register is the value to be output on the corresponding I/O pin when the pin is
configured as I/O function, output direction.
• Bit = 0: Output is low
• Bit = 1: Output is high
If the pin is configured as I/O function, input direction and the pullup or pulldown resistor are enabled; the
corresponding bit in the PxOUT register selects pullup or pulldown.
• Bit = 0: Pin is pulled down
• Bit = 1: Pin is pulled up
12.2.3 Direction Registers (PxDIR)
Each bit in each PxDIR register selects the direction of the corresponding I/O pin, regardless of the
selected function for the pin. PxDIR bits for I/O pins that are selected for other functions must be set as
required by the other function.
• Bit = 0: Port pin is switched to input direction
• Bit = 1: Port pin is switched to output direction
12.2.4 Pullup or Pulldown Resistor Enable Registers (PxREN)
Each bit in each PxREN register enables or disables the pullup or pulldown resistor of the corresponding
I/O pin. The corresponding bit in the PxOUT register selects if the pin contains a pullup or pulldown.
• Bit = 0: Pullup or pulldown resistor disabled
• Bit = 1: Pullup or pulldown resistor enabled
Table 12-1 summarizes the use of PxDIR, PxREN, and PxOUT for proper I/O configuration.
Table 12-1. I/O Configuration
3、设置引脚为外设模式。

  P2SEL1 |= BIT0 | BIT1;                    // USCI_A0 UART operation
  P2SEL0 &= ~(BIT0 | BIT1);
通过下面的文档说明可以知道如何配置:
因为PxSEL1和PxSEL0位不驻留在连续的地址中,所以不能同时更改这两个位。
4、解锁端口配置。
    PM5CTL0 &= ~LOCKLPM5;
其中,LOCKLPM5 = 0x0001.可参考下面的文档说明
5、配置时钟。
这里没有配置时钟,为默认值:
//  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = 1MHz
如果需要配置时钟,可以参考下面的配置方法:
时钟系统操作
在PUC之后,CS模块默认配置为:
•选择LFXT作为LFXTCLK的振荡源。选择LFXTCLK为ACLK(SELAx = 0)的时钟源,ACLK不可分频(DIVAx = 0)。
•选择DCOCLK为MCLK和SMCLK(SELMx = SELSx = 3)时钟源,每个为8分频(DIVMx = DIVSx = 3)。
•LFXIN和LFXOUT引脚设置为通用I / O,并且LFXT保持禁用,直到I / O端口配置为LFXT工作模式。
•HFXIN和HFXOUT引脚设置为通用I / O,HFXT禁用。
如前所述,默认情况下选择LFXT,但LFXT被禁用。晶体管脚(LFXIN,LFXOUT)与通用I / O共用。要使能LFXT,必须设置与晶体管脚相关的PSEL位。当LFXTCLK使用32768-Hz晶体时,故障控制逻辑立即导致时钟源切换,ACLK由LFMODCLK提供,MCLK和SMCLK由MODCLK提供,因为LFXT没有立即稳定(见第3.2.8节)。
状态寄存器控制位(SCG0,SCG1,OSCOFF和CPUOFF)配置MSP430工作模式,并启用或禁用时钟系统模块的部分(请参见系统复位,中断和 操作模式章节)。通过CSCTL6注册CSCTL0,配置CS模块。
在程序执行期间,CS模块可以随时由软件进行配置或重新配置。 CS控制寄存器受密码保护,以防止无意中访问。
实例说明:配置 ACLK = 32768Hz, MCLK = SMCLK = BRCLK = default DCO = ~1MHz
首先,我们配置LFXIN和LFXOUT为LFXT工作模式。
  PJSEL0 |= BIT4 | BIT5;                    // Configure XT1 pins
注意,之后需要解锁端口。
接下来,设置时钟:
(1)解锁时钟,CS控制寄存器受密码保护,以防止无意中访问。

  CSCTL0_H = CSKEY >> 8;                    // Unlock CS registers

其中,CSKEY = 0xA500。

(2)设置DCO时钟源频率。需要DCORESL和DCOFSEL配合设置。
  CSCTL1 = DCOFSEL_0;                       // Set DCO to 1MHz
其中,DCOFSEL_0 = 0x0000。
(3)设置各时钟的时钟源
  CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;
其中,SELA__LFXTCLK = 0x0000,SELS__DCOCLK = 0x0030,SELM__DCOCLK = 0x0003。
(4)设置分频参数
 CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;     // Set all dividers
其中,DIVA__1、DIVS__1、DIVM__1 都为0x0000。
(5)开启LFXT
  CSCTL4 &= ~LFXTOFF;                       // Enable LFXT1
其中,LFXTOFF = 0x0001。
这里有一个需要注意里面一个名词LFXTBYPASS的理解,之前使用STM32时,里面有一个说明,可以参考下:
外部时钟源(HSE旁路)

在这个模式里,必须提供外部时钟。它的频率最高可达25MHz。用户可通过设置在时钟控制寄

存器中的HSEBYP和HSEON位来选择这一模式。外部时钟信号(50%占空比的方波、正弦波或

三角波)必须连到SOC_IN管脚,同时保证OSC_OUT管脚悬空。见图8。

外部晶体/陶瓷谐振器(HSE晶体)

4~16Mz外部振荡器可为系统提供更为精确的主时钟。相关的硬件配置可参考图8,进一步信息

可参考数据手册的电气特性部分。

在时钟控制寄存器RCC_CR中的HSERDY位用来指示高速外部振荡器是否稳定。在启动时,直

到这一位被硬件置’1’,时钟才被释放出来。如果在时钟中断寄存器RCC_CIR中允许产生中断,

将会产生相应中断。

HSE晶体可以通过设置时钟控制寄存器里RCC_CR中的HSEON位被启动和关闭。
(6)检测晶振是否正常
首先软件清除寄存器里对应的HFXT或者LFXT晶振错误标志。接着测试晶振是否正常。
  do
  {
    CSCTL5 &= ~LFXTOFFG;                    // Clear XT1 fault flag
    SFRIFG1 &= ~OFIFG;
  }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
(7)晶振正常后所处时钟配置寄存器。
  CSCTL0_H = 0;                             // Lock CS registers
6、配置USCI_A0为UART模式。
(1)在配置或者重新配置eUSCI_A 模块时应该先将UCSWRST置1以避免出现位置错误,配置完之后释放复位。

  UCA0CTLW0 = UCSWRST;                      // Put eUSCI in reset

  UCA0CTL1 &= ~UCSWRST;                     // release from reset
     
(2)设置eUSCI_A时钟源,作为波特率时钟源。
  UCA0CTL1 |= UCSSEL__SMCLK;                // CLK = SMCLK
选择SMCLK为时钟源。
(3)设置波特率。
首先计算波特率参数。
对于给定的BRCLK时钟源,使用的波特率决定了所需的分频因子N:
N = fBRCLK /波特率
分频因子N通常是非整数值,因此,使用至少一个分频器和一个调制器级来尽可能接近该因子。
如果N等于或大于16,TI建议通过设置UCOS16来使用过采样波特率生成模式。
注意:波特率设置快速设置
要计算波特率生成的正确设置,请执行以下步骤:
1.计算N = fBRCLK /波特率[如果N> 16继续步骤3,否则步骤2]
2. OS16 = 0,UCBRx = INT(N)[继续步骤4]
3. OS16 = 1,UCBRx = INT(N / 16),UCBRFx = INT([(N / 16) – INT(N / 16)]×16)
可以通过查看表24-4中的N(= N-INT(N))的小数部分来找到UCBRSx
5.如果选择OS16 = 0,TI建议执行详细的错误计算。
也可以直接查表Table 24-5确认波特率参数。
UCBRx = INT(N)
  UCA0BR0 = 8;                              // 1000000/115200 = 8.68
因为N <16 ,所以OS16 = 0,UCBRFx 不需要写, 由8.68-8=0.68查Table 24-4得UCBRSx = 0xD6
  UCA0MCTLW = 0xD600;                       // 1000000/115200 – INT(1000000/115200)=0.68
                                                                // UCBRSx value = 0xD6 (See UG)
  UCA0BR1 = 0;

接下来使能中断

  UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt
7、通过中断标志判断状态

  while (1)
  {
    while(!(UCA0IFG & UCTXIFG));
    UCA0TXBUF = TXData++;                     // Load data onto buffer
  }
当发送完成后往发送buffer装载数据。
8、中断函数子程序。
可以参考下面的例程:
Example 24-1. UCAxIV Software Example
#pragma vector = USCI_A0_VECTOR __interrupt void USCI_A0_ISR(void) {
    switch(__even_in_range(UCA0IV,18)) {
        case 0x00: // Vector 0: No interrupts
            break;
        case 0x02: … // Vector 2: UCRXIFG
            break;
        case 0x04: … // Vector 4: UCTXIFG
            break;
        case 0x06: … // Vector 6: UCSTTIFG
            break;
        case 0x08: … // Vector 8: UCTXCPTIFG
            break;
        default: break;
    }
}
其中,__even_in_range(UCA0IV,18)的解释:
使用__even_in_range 的好处是可以生成效率比较高的代码,在判断多中断源的中断的来源时可以使用此函数。
原型:unsigned short __even_in_range(unsigned short value, unsignedshort upper_limit); 
功能:只能与switch 语句结合使用,判断value 是否为偶数且小于等于upper_limit。
Seven Han:

文档整理很详细,感谢您的分享!

灰小子:

感谢分享,很详细的讲解

Butterfly:

谢谢分享,代码对应文档说明,很详细。

yanqing zhou:

回复 Seven Han:

Seven 你好:

         我现在有一个问题,那就是我现在用SPI的时候,发现USCI_A0配置为UART和SPI模式时UCA0CTLW0每一位的定义不一样了。

示例代码里面没有单独选择工作模式的代码。eUSCI_A在UART和SPI两种模式是通过哪里切换的,只要PxSEL设置了两个引脚就是UART模式,四个引脚就自动进入SPI模式?

而且SPI的示例代码里面有这样一句:

  UCA0MCTLW = 0;                            // No modulation

我在SPI的模式说明里发现没有对这个寄存器的说明,是不是和UART模式时的寄存器一模一样。用来配置波特率参数?

灰小子:

回复 yanqing zhou:

你看的版本好像有点老。最新的是Chapter 30和Chapter 31两章。

msp430并没有具体切换uart和spi的寄存器,或者说没有单独的用作切换通讯方式的寄存器。

我是这样理解的:eUSCI模块的不同寄存器配置组合满足不同的通讯方式,而且在不同通讯方式下寄存器的名称有些相同有些不同。

yanqing zhou:

回复 灰小子:

但这样就无法确认我正在操作时寄存器处于哪个模块的状态下?

赞(0)
未经允许不得转载:TI中文支持网 » MSP430 UART学习分享-基于MSP-EXP430FR5969
分享到: 更多 (0)