RSS订阅信息安全技术跟踪与研究:技术、平台、会议、论文、产业
你现在的位置:首页 / 技术积累 / 正文

MSP430的UART串口通信详解

0 技术积累 | 2016年6月13日
转载申明:本站原创,欢迎转载。但转载时请保留原文地址。
原文地址:http://www.vonwei.com/post/MSP430UART.html

         MSP430的串口通信由一个称为USCIUniversal Serial Communications Interface)的片上外设处理。USCI外设可以处理多种串口通信格式,包含同步的和异步的,如SPII2CIrDAUART等。MSP430G2553上有两个USCI模块,分别是USCI_A0USCI_B0,前者可以配置用于处理LINIrDASPIUART通信,而后者可以用于处理SPII2C通信。

         本文主要介绍配置MSP430G2553USCI_A0模块,实现异步串行通信即UART模式。UART异步串行通信模式被广泛的用于与外部设备通信,如与PC、笔记本、GSM模块、GPS模块等通信,而且其也是很多标准协议(RS232,RS422,RS485等)的基石。UART模式使用两个引脚来传输(UCA0TXD)和接受(UCA0RXD)数据。USCI_A0处于UART模式的简单框图如下:

         从上图可知,USCI的时钟源可以是来自SMCLK或者ACLK,生成的BRCLK用于产生需要的计时。UC0CLK是一个外部时钟源。

         本文的例子主要是配置MSP430 UART,传输和接受数据的波特率为9600bps8 databitsno Parity1 stop bit

 

1. 系统时钟配置

         下面一段代码配置DCO产生1MHz,使用子系统时钟SMCLK作为UART时钟:

-------------------------------------------code start------------------------------------------------------------------------

         if (CALBC1_1MHZ == 0xFF) // If calibration constant erased

         {

                  while(1);            // do not load, trap CPU!!

         }

         DCOCTL  = 0;             // Select lowest DCOx and MODx settings

         BCSCTL1 = CALBC1_1MHZ;   // Set range

         DCOCTL  = CALDCO_1MHZ;   // Set DCO step + modulation

-------------------------------------------code end------------------------------------------------------------------------

为了产生精确的1MHz时钟,需要将校准常量加载到基本时钟系统寄存器(BCSCTL1)和DCO控制寄存器(DCOCTL)中。CALBC1_1MHZ是头文件msp430g2553.h中定义的常量,头文件中还定义有其它常量,可以配置DCO操作于1MHz8MHz12MHz16MHz,即CALBC1_1MHZ,CALBC1_8MHZ,CALBC1_12MHZ,CALBC1_16MHZ,这些常量值在出厂时已经校准好,写在芯片上的保护存储区域,如果不小心把这些常量值擦除了,则必须重新校准。

 

2. UART需要的寄存器

         UCAxCTL0寄存器,由于我们使用的是USC1_A0模块,因此需要使用UCA0CTL0寄存器,该寄存器控制着Parity选择、数据传输方向、LSB或者MSB优先、字符长度、stop bit、传输模式等的设置。我们的选择中,UCA0CTL0寄存器的所有比特位都为0,因此程序中不必配置。

         UCAxCTL1寄存器,需要使用UCA0CTL1中的两个重要比特位,UCSSELx(用来选择时钟源,我们需要选择为SMCLK @1MHz)和UCSWRST(用于将USCI模块置于reset状态,推荐对寄存器进行任何改变之前将USCI置于reset状态)。

         UCAxSTAT寄存器,需要使用UCA0STAT中的两个重要比特位,UCLISTEN(可以用于选择内部循环模式Loop Back mode,这样UCAxTXD会内部反馈给receiver),UCBUSY(指示是否一个传输或者接受操作正在进行中)。

         UCAxBR0寄存器和UCAxBR1寄存器,两个8位寄存器,用于为波特率生成器设置时钟预置分频器值。

         UCAxTXBUF寄存器,一个8位数据寄存器,相当于一个传输缓冲区,即MSP430 UART将要传输的一个字节。

         UCAxRXBUF寄存器,也是一个8位数据寄存器,相当于一个接受缓冲区,用于存储接收到的字节。

         注意,由于使用的是USC1_A0模块,上述寄存器中的x都要变成0.

 

3. 波特率配置

         MSP430的用户手册中给出了一个波特率选择表,根据该表可以很容易的对波特率进行配置,该表如下:

通过该表找到对应的值填入UCA0BR0 UCA0BR1两个寄存器中,就可以配置波特率。由于我们使用SMCLK @ 1MHz作为BRCLK9600bps作为波特率,表中其对应的UCBRx值为104,将该值放入寄存器UCA0BR0UCA0BR1中即可。

       配置波特率时另一个需要考虑的寄存器是UCAxMCTL (UCA0MCTL),该寄存器用于选择调制级别(modulation stage),将表中对应的UCBRSx值(这里为1)放到UCA0MCTL寄存器中可以配置modulation stage

 

4. MSP430 UART的中断

         MSP430G2553拥有一个数据传输中断和一个数据接收中断,在使用前必须现在IE2寄存器中将这两个终端开启(enabled)。IFG2寄存器中的两个flags位用于指示数据在传输还是在接收。

         IE2寄存器:UCA0TXIE用于开启/关闭传输中断,UCA0RXIE用于开启/关闭接收中断。

         IFG2寄存器:UCA0TXIFGUSCI_A0传输中断flag,当UCA0TXBUF为空时设置该位;UCA0RXIFGUSCI_A0接收中断flag,当UCA0RXBUF接收到一个完整的字符时设置该位,应该记得中对应的中断处理器程序ISR中手动清除掉该flag

 

5. 代码-UART传输:采用内部循环模式

         两个设备之间进行通信的一个困难时,出现问题很难定位,可能是接受设备代码的问题,也可能是通信连接的问题,还可能是发送设备代码的问题等等。为了使得开发UART代码更加容易,MSP430提供了内部循环模式,即Loop Back mode,通过UCAxSTAT寄存器可以进行配置。该模式下,UART的传输口的输出会自动连接到接受口的输入,即MSP430设备自己传输自己接受。

         下面的代码(在CCS下编译通过)通过UART传输一个ASCII字符‘A’UART配置为内部循环模式,接受的字符会存储在设备的UCA0RXBUF寄存器中。通过两个LED灯来指示传输和接受操作。

-------------------------------------------code start------------------------------------------------------------------------

#include <msp430.h>

 

/*

 * main.c

 */

int main(void) {

    WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

 

    //------------------- 配置时钟 -------------------//

    if (CALBC1_1MHZ==0xFF)   // If calibration constant erased

     {

        while(1);          // do not load, trap CPU!!

     }

 

    DCOCTL  = 0;             // Select lowest DCOx and MODx settings

    BCSCTL1 = CALBC1_1MHZ;   // Set range

    DCOCTL  = CALDCO_1MHZ;   // Set DCO step + modulation

 

      //---------------- 配置LED灯,P1.0P1.6分别对应LED1LED2 ----------------------//

 

    P1DIR  |=  BIT0 + BIT6;  // P1.0 and P1.6 output

    P1OUT  &= ~BIT0 + BIT6;  // P1.0 and P1.6 = 0

 

      //--------- 配置UARTP1.1P1.2两个引脚分别对应UART的输入和输出,通过PXSEL寄存器可以配置哪个用作接受RXD,哪个用作传输TXD --------//

 

    P1SEL  |=  BIT1 + BIT2;  // P1.1 UCA0RXD input

    P1SEL2 |=  BIT1 + BIT2;  // P1.2 UCA0TXD output

 

      //------------UART(USCI_A0) 的寄存器和波特率配置----------------//

 

    UCA0CTL1 |=  UCSSEL_2 + UCSWRST;  // USCI Clock = SMCLK,USCI_A0 disabled

    UCA0BR0   =  104;                 // 104 From datasheet table-

    UCA0BR1   =  0;                   // -selects baudrate =9600,clk = SMCLK

    UCA0MCTL  =  UCBRS_1;             // Modulation value = 1 from datasheet

    UCA0STAT |=  UCLISTEN;            // loop back mode enabled,配置为内部循环模式,即自己的TXD传输给自己的RXD接受

    UCA0CTL1 &= ~UCSWRST;             // Clear UCSWRST to enable USCI_A0

 

      //---------------- 开启传输中断和接受中断,同时开启全局中断,然后在UCA0TXBUF寄存器中写入一个A ------------------//

 

    IE2 |= UCA0TXIE;                  // Enable the Transmit interrupt

    IE2 |= UCA0RXIE;                  // Enable the Receive  interrupt

    _BIS_SR(GIE);                     // Enable the global interrupt

 

    UCA0TXBUF = 'A';                  // Transmit a byte

 

    _BIS_SR(LPM0_bits + GIE);         // Going to LPM0

   

    return 0;

}

 

//-----------------------------------------------------------------------//

  //                Transmit and Receive interrupts                        //

  //-----------------------------------------------------------------------//

#pragma vector = USCIAB0TX_VECTOR

  __interrupt void TransmitInterrupt(void)

  {//UCA0TXBUF寄存器的A传输后,传输中断会点亮LED 1

    P1OUT  ^= BIT0;//light up P1.0 Led on Tx

  }

 

#pragma vector = USCIAB0RX_VECTOR

  __interrupt void ReceiveInterrupt(void)

  {//传输的字符A会被接受到UCA0RXBUF寄存器中,接受中断会点亮LED 2,同时记住在此ISR中手动清除掉UCA0RXIFG标记

    P1OUT  ^= BIT6;     // light up P1.6 LED on RX

    IFG2 &= ~UCA0RXIFG; // Clear RX flag

  }

 

-------------------------------------------code end ------------------------------------------------------------------------

 

测试该程序的结果如下

         UCA0STAT |=  UCLISTEN这句代码是通过内部寄存器自动配置为内部循环模式,不用将P1.1P1.2连接起来,代码就可以正常执行,传输和接受操作都正常,LED1LED2都会亮。

         注释掉UCA0STAT |=  UCLISTEN代码,再次执行时,会发现只有LED1亮,而LED2不会亮,说明传输出去了,但是没有在本设备上接受。

         注释掉UCA0STAT |=  UCLISTEN代码后,用引脚线将P1.1P1.2连接起来,再次看看执行效果,会发现LED1LED2都会亮,说明传输和接受都正常,连接这两个引脚后,数据也在该设备上接受了。

 

6. 与实际机器通过UART通信

         继续使用上面的代码,不过将内部循环模式取消掉,即注释掉UCA0STAT |=  UCLISTEN。将J3配置为HW UART,如下图:

通过USB线连接MSP430 Launchpad后,在设备管理器中可以看到端口处多了一个“MSP430 Application UART COMxx”设备,在PC上通过串口终端工具(PuTTYTera等)连接上对应的COMxx,可以看到接收到的A

     

连接上USB线,并配置好Tera后,不会出现A。按一下MSP430上的reset按钮,就会出现一个A,图中出现多个A,是因为按了多次reset按钮,每次reset后,默认都会执行我们上面的程序,即发送一个A。然后PC上的终端工具Tera就接收到了该字符并显示。在Tera中随便按Enter键,相当于是PC发送一个字符;MSP430的接受中断会接受这个字符,最终会看到按下PCEnter键后,MSP430上面的LED 2也亮了,说明其接受到了。

         再次强调,必须将MSP430上的跳脚设置为HW UART,否则接受和发送都不会成功。至于HW UARTSW UART的区别,有其历史原因,这里不再叙述。

         后面的博客会进一步实验,在PC上通过程序与MSP 430UART交互数据。

 

附注-推荐两个比较好的MSP430学习博客:

http://www.argenox.com/library/msp430/

http://xanthium.in/

参考:http://xanthium.in/Serial-Communication-MSP430-UART-USCI_A



  • ------------------分隔线----------------

  • 如果感兴趣,欢迎关注本站微信号,跟踪最新博文信息,手机微信扫一扫下面的二维码,即可关注!
  • 微月信公众号
  • 推荐您阅读更多有关于“ 嵌入式设备  UART  串口通信   ”的文章

    请填写你的在线分享代码
    上一篇:设备唯一标识方法(Unique Identifier):如何在Windows系统上获取设备的唯一标识下一篇:PC与MSP430G2553通过UART通信编程实践

    猜你喜欢

    评论列表:

    发表评论

    必填

    选填

    选填

    必填,不填不让过哦,嘻嘻。

    记住我,下次回复时不用重新输入个人信息

    本站介绍
    最近发表
    本年最热文章
    本月最热文章
    网站分类
    文章归档