Blogs

MSP430 LaunchPad教程 - 第4部分 - UART传输

enrico garante.2013年7月3日20评论

今天,我们将学习如何使用UART与Launchpad进行沟通。为此目的,我将替换电路板附带的默认微控制器 MSP430G2553.。它是MSP430值线中最强大的设备,它配备了集成的硬件UART模块,以及16 kB的闪存,512字节的SRAM和8通道,10位ADC。

快速链接

UART通信在处理传感器时可能有用:作为基本示例,我们可以使用连接到Launchpad上的UART引脚的廉价蓝牙模块将从温度传感器与内部ADC的温度传感器发送的数据发送到计算机。

本文以PDF格式提供,便于打印

在本教程中,我们将看到一个程序等待从UART端口接收某个字符,然后向其他设备发送响应。通信在115200 BPS的全双工中发生,8位数据,没有奇偶校验和1个停止位。

足够的喋喋不休,让我们从教程开始!第一个陈述将为您熟悉:

#include "msp430g2553.h"
#define TXLED BIT0
#define RXLED BIT6
#define TXD BIT2
#define RXD BIT1
const char string[] = { "你好 World\r\n" };
unsigned int i; //Counter 

一如既往,我们包括微控制器的标题文件,然后定义一些宏以更好地阅读。
然后,我们声明了一个字符数组(一个简单的C字符串),它将将我们的响应存储到另一个终端。最后,我们声明一个计数器变量,将在发送响应时稍后帮助我们。

int main(void)
{
   WDTCTL = WDTPW + WDTHOLD; // Stop WDT
   DCOCTL = 0; // Select lowest DCOx and MODx settings<
   BCSCTL1 = CALBC1_1MHZ; // Set DCO
   DCOCTL = CALDCO_1MHZ;

这是主要的例程:它第一行将禁用看门狗定时器。之后,我们有三行代码将校准并将内部振荡器设置为1 MHz。 

这将是主时钟(SMCLK.)由UART和所有其他车载外围设备使用。

   P2DIR = 0xFF; // All P2.x outputs<
   P2OUT &= 0x00; // All P2.x reset
   P1SEL |= RXD + TXD ; // P1.1 = RXD, P1.2=TXD
   P1SEL2 |= RXD + TXD ; // P1.1 = RXD, P1.2=TXD
   P1DIR |= RXLED + TXLED;
   P1OUT &= 0x00;

现在我们设置了输入和输出:使用前两行我们禁用G2553上的Port2;禁用我们不使用的I / O引脚是一个好主意,以减少噪声和电流消耗。

第3行和4确保P1.1和P1.2切换到“特殊功能”模式,即G2553为UART模式。事实上 P1SELP1SEL2 寄存器将PORT1引脚复用到各种内部外围设备。
不幸的是,我们无法选择用作TXD或RXD的PIN,正如您所阅读的那样 数据表 (第43页)。
最后两行简单地设置了车载LED。

   UCA0CTL1 |= UCSSEL_2; // SMCLK
   UCA0BR0 = 0x08; // 1MHz 115200
   UCA0BR1 = 0x00; // 1MHz 115200
   UCA0MCTL = UCBRS2 + UCBRS0; // Modulation UCBRSx = 5
   UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
   UC0IE |= UCA0RXIE; // Enable USCI_A0 RX interrupt

这是好东西。使用第一行我们选择 SMCLK. 作为UART模块的时钟源,用于生成所需的波特率(我们也可以选择外部水晶 ACLK.UCSSEL_1如果我们初始化了它)。

UCA0BR0.UCA0BR1. 选择波特率:实际上它们存储整数分频器 SMCLK. (1 MHz)。在这种情况下,我们有1MHz / 8 = 125000,但实际上我们需要115200,我们将会带一些会随着时间的推移积累一些错误。
出于显而易见的原因,我们甚至无法选择9,因为否则波特率将在115200年的BPS下。但是 UCA0MCTL. 注册来帮助我们。
此寄存器实际上是控制“调制”:它将在8到9之间选择分频器,因此在通信期间切换波特率以包含累积的错误。
8作为分频器,我们有125000-115200 = 9600(+ 8.5%)错误。有9,我们有115200-111111 = 4089(-3.6%)错误。
调制器将粗略地工作:

第一次使用/ 8,+ 8.5%off
下一位使用/ 9,-3.6%折扣,累计+ 4.9%
下一位使用/ 9,-3.6%折扣,累计1.3%
下一位使用/ 9,-3.6%折扣,累计-2.3%
下一位使用/ 8,+ 8.5%折扣,累计6.2%

等等。


你可以从中看到 设备用户指南 在第424页,有一个表显示给定某一的分隔符 SMCLK. 频率和所需的波特率,具有预期的发射和接收的最小值和最大误差速率。
从该表中也拍摄了5的调制值。

使用最后一行,我们启用UART模块和“接收事件”的中断,我们很快就会分析。

   __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ int until Byte RXed
   while (1)
   { }
}

主程序的最后一行将以低功耗模式将微控制器放置并启用全局中断标志,并进入无限循环。

#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
   P1OUT |= RXLED;
   if (UCA0RXBUF == 'a') // 'u' received?
   {
      i = 0; 
      UC0IE |= UCA0TXIE; // Enable USCI_A0 TX interrupt
      UCA0TXBUF = string[i++];
   }
   P1OUT &= ~RXLED;
}

这是我们收到某些内容时将执行的中断例程。如果您遵循了教程系列,您的声明不应该对您未知,否则返回到 中断 教程。
首先,我们点亮了一个将向我们展示我们收到一个字节的LED。然后我们读了 UCA0RXBUF. 寄存器存储所接收的数据。
如果存储的字节是“A”,则我们重置计数器并使发射器中断将处理响应的发送。
之后我们加载了 UCA0TXBUF. 使用前面声明的响应字符串中的第一个字符。该寄存器包含要发送的数据。
最后,我们关掉LED。

#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
   P1OUT |= TXLED;
   UCA0TXBUF = string[i++]; // TX next character
   if (i == sizeof string - 1) // TX over?
      UC0IE &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt
   P1OUT &= ~TXLED;
}

]
这是发射器中断例程。正如我们之前所做的那样,我们打开一个将告诉我们我们正在传递某些东西的领导。
然后我们加载下一个字符以在缓冲区中发送。如果在响应字符串中发送仍有字符,我们将关闭LED并等待当前字节的传输结束。
当由UART模块发送字符时,将再次发生TX中断,并且将为下一个字符执行例程。
如果我们意识到我们已到达响应字符串数组的末尾(使用sizeof语句返回我们在阵列中有多少个字节),我们会禁用TX中断并返回主循环。

这是参考的完整代码:

#include "msp430g2553.h"
 
#define TXLED BIT0
#define RXLED BIT6
#define TXD BIT2
#define RXD BIT1
 
const char string[] = { "你好 World\r\n" };
unsigned int i; //Counter
 
int main(void)
{
   WDTCTL = WDTPW + WDTHOLD; // Stop WDT
   DCOCTL = 0; // Select lowest DCOx and MODx settings
   BCSCTL1 = CALBC1_1MHZ; // Set DCO
   DCOCTL = CALDCO_1MHZ;
   P2DIR |= 0xFF; // All P2.x outputs
   P2OUT &= 0x00; // All P2.x reset
   P1SEL |= RXD + TXD ; // P1.1 = RXD, P1.2=TXD
   P1SEL2 |= RXD + TXD ; // P1.1 = RXD, P1.2=TXD
   P1DIR |= RXLED + TXLED;
   P1OUT &= 0x00;
   UCA0CTL1 |= UCSSEL_2; // SMCLK
   UCA0BR0 = 0x08; // 1MHz 115200
   UCA0BR1 = 0x00; // 1MHz 115200
   UCA0MCTL = UCBRS2 + UCBRS0; // Modulation UCBRSx = 5
   UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
   UC0IE |= UCA0RXIE; // Enable USCI_A0 RX interrupt
   __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ int until Byte RXed
   while (1)
   { }
}
 
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
   P1OUT |= TXLED; 
     UCA0TXBUF = string[i++]; // TX next character 
    if (i == sizeof string - 1) // TX over? 
       UC0IE &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt 
    P1OUT &= ~TXLED; } 
  
#pragma vector=USCIAB0RX_VECTOR 
__interrupt void USCI0RX_ISR(void) 
{ 
   P1OUT |= RXLED; 
    if (UCA0RXBUF == 'a') // 'a' received?
    { 
       i = 0; 
       UC0IE |= UCA0TXIE; // Enable USCI_A0 TX interrupt 
      UCA0TXBUF = string[i++]; 
    } 
    P1OUT &= ~RXLED;
}

这是我们与Launchpad旅程中的最后一集。我希望您享受它,并且您已经获得了与MSP430微控制器的有价值的知识。


[]
评论 键盘2014年8月20日
你好
谢谢你的这个漂亮的教程,但我有一个问题。
我无法理解你为什么设置“uca0mctl = ucbrs2 + ucbrs0; //调制ucbrsx = 5”
ICH我在现场424的表格中查看了UserGuide,并查看BRCLK 1000000波特率115200,而不是我将UCA0MCTL = UCBRS6设置。矿石我误解了你?
谢谢你的帮助
[]
评论 Mark132015年6月3日
UCBRS2 + UCBRS0 = 101 = 6
UCBRSX = 5表示六,因为第一个是零
15.4.5
[]
评论 尼尔隆2015年5月28日
嗨Enrico,非常感谢您的说明!
我试图在我的Lounchpad上使用你的代码,但我无法在端口1.2上看到具有示波器的数据传输的任何迹象。通过调试我证明了Line UCA0TXBUF = String [I ++]已被调用,而TX缓冲寄存器确实获取数据。无论1.2端口都不会发生任何事情。是否有其他我应该做的事情实际传输数据?非常感谢你。
[]
评论 Roballen10.2013年8月24日
谢谢你写这个。按行评论的行非常有用。
[]
评论 Raul352013年9月28日
嗨Enrico,这是程序的条件有效吗?,即。用腻子或超级终端,Wath是您对测试的建议?问候!
[]
评论 贝加兰特2013年11月2日
我使用LaughtPad的内部COM到USB转换器,用腻子测试了它。
[]
评论 比利77.2016年7月7日
我想知道你在哪里得到了中断函数的名称。它们不在家庭指导中,也不是数据表。家庭指南中唯一的代码是装配,名称不一样。
[]
评论 Wygonski95.2013年11月5日
谢谢你的例子和伟大的解释。有必要更改TXD和RXD的J3跳线吗? Launchpad不是9600波特吗?
[]
评论 贝加兰特2013年11月29日
是的,您必须将跳线放在J3上,以便使用Lauchpad的USB COM端口。此端口仅限于9600 BPS,但您可以使用连接到UART引脚的外部转换器并更快地转换。
[]
评论 Rohit30793.2013年11月9日
#pragma矢量的使用是什么?
[]
评论 贝加兰特2013年11月29日
#pragma向量= xxx是一个指令,告诉编译器xxx中断将由以下函数提供服务。
看看中断教程!
[]
评论 Carlos482013年12月13日
感谢您的教程,您会知道学习编程MSP430的任何官方指南吗?最佳问候
[]
评论 Fabiomarinoshi2013年12月13日
嗨Enrico,出色的作品!你为什么不对待I2C和SPI通信?我认为他们会非常有用。问候。
[]
评论 Nikitha62.2013年12月16日
嗨Enrico,我怀疑是在MSP430上工作。如何仅打印仅接收缓冲值。
[]
评论 贝加兰特2014年2月14日
如果我已经理解正确,你想回应你刚刚传输到MSP430的内容。为此,请在中断例程中放置UCA0TXBUF = UCA0RXBUF。
[]
评论 Megha33.2014年3月17日
嘿 !
你的教程很棒!我完全喜欢你的解释。
我有一些疑惑,请帮帮我
我试图通过UART发送和接收数据,让多通道ADC工作。目前,我有串行通信代码工作,但我需要引脚1.1(TXD)和1.2(RXD)进行。另一方面,我想使用6个其他频道进行ADC采样。我一直在尝试从1.3,1.4,1.5,1.6和1.7上采样。

从我收集的内容,在预成型多声道采样时设置inch_7将允许ADC从A0-A7采样。但我不想从A1和A2采样,因为这些引脚被用于串行传输。

关于如何设置的任何想法或提示?
[]
评论 配音2014年6月2日
你好

我是一个新手,新毕业,并任务在MSP4305659上编程RS232。我没有使用这种类型的处理器或这种类型的USCI端口进行经验,以执行RS232。您是否有任何指导,您知道的任何教程或网站都可以使用这家处理器提供一些指导?

谢谢

配音
[]
评论 Manasu24.2015年1月11日
嗨Enrico,
我在MSP430F5438中使用了IRDA模式的UART。
但是,它将输出阀门始终为我通过遥控器发送的所有命令始终为255。
TSOP34838是我使用的IR接收器,I Hae直接将该IR接收器的输出连接到MSP430F5438中UART的RX引脚。
谢谢
[]
评论 Nagendra Prasath.2015年3月1日
你好,先生,
教程很有用。使用MSP430F5529,我应该在上面的串行通信方案中更换什么。
[]
评论 克里斯TTU.2015年4月26日
嘿谢谢你的上传,但我想知道你是否实际上可以在代码中改变一些东西,以将字符发送到RAM内存而不是闪存。

要发布回复评论,请单击连接到每个注释的“回复”按钮。发布新的评论(不是回复评论),请在评论的顶部查看“写评论”选项卡。

注册将允许您参加所有相关网站的论坛,并为您提供所有PDF下载。

注册

我同意 使用条款隐私政策.

尝试我们偶尔但流行的时事通讯。非常容易取消订阅。
或登录