This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430F2274:f2274

Guru**** 2582405 points
Other Parts Discussed in Thread: MSP430F2274

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/612361/msp430f2274-f2274

器件型号:MSP430F2274

您好!

我使用的是"Linux debian 3.16.0-4-AMD64 #1 SMP Debian 3.16.39-1+deb8u2 (2017-03-07) x86_64 GNU/Linux" 、我已经设置了 MSP430-gcc 工具链并能够在我的 MSP430F2274上运行闪烁程序。 现在、我将介绍应用开发、在此之前、我想设置 UART 以进行调试。 但是、由于某种原因、我无法在终端上获取字节。 我已经交叉检查了我的代码、没有发现任何可能导致此问题的漏洞。 请在下面查找我的源代码、

gpio.c

/* include 的*/
#include 

/*定义*/
#define MAX_PIN_NO_INVALID ******255

/
*函数名称:GPIO_configure
*说明:将 GPIO 配置为 I/O
*返回:0 =成功
-1 =失败
*参数:@port_no =端口号
@PINS_NO =端口中用于配置
的引脚 /
signed char
GPIO_configure (unsigned char port_no、unsigned char pins_no)
{
signed char ret = 0;
if (pins_no > MAX_PIN_NO_INVALID)
PORT_NO = 0;
开关(PORT_NO)
{
案例1:
P1DIR = PINS_NO;
中断;
案例2:
P2DIR = PINS_NO;
中断;
案例3:
P3DIR = PINS_NO;
中断;
案例4:
P4DIR = PINS_NO;
中断;
默认值:
RET =-1;
}
返回(RET);
}

/*********
*函数名称:GPIO_write
*说明:将 GPIO 设置为高电平或低
电平*返回:0 =成功
-1 =失败
*参数:@port_no =端口号
@PINS_NO =用于设置高电平或低电平的引脚
/
有符号 char
GPIO_write (unsigned char port_no、unsigned char pin_no_val)
{
signed char ret = 0;
if (pin_no_val > MAX_PIN_NO_INVALID)
PORT_NO = 0;
开关(PORT_NO)
{
案例1:
P1OUT = PIN_NO_Val;
中断;
案例2:
P1OUT = PIN_NO_Val;
中断;
案例3:
P1OUT = PIN_NO_Val;
中断;
案例4:
P1OUT = PIN_NO_Val;
中断;
默认值:
RET =-1;
}
返回(RET);
}

/*********
*函数名称:GPIO_Read
*说明:读取 GPIO 的状态
*返回:0或1 =成功
-1 =失败
*参数:@port_no =端口号
@PINS_NO =待读取的引脚
/
signed char
GPIO_read (unsigned char port_no、unsigned char pin_no)
{
signed char ret = 0;
if (pin_no = BIT0)||(pin_no = BIT1)||(pin_no = BIT2)
||(PIN_NO == BIT3)||(PIN_NO == BIT4)||(PIN_NO == BIT5)
||(PIN_NO == BIT6)||(PIN_NO == BIT7)
{
/*不执行任何操作*/
}
其他
{
PORT_NO = 0;
}
开关(PORT_NO)
{
案例1:
RET = P1IN & PIN_NO;
中断;
案例2:
RET = P2IN 和 PIN_NO;
中断;
案例3:
RET = P3IN 和 PIN_NO;
中断;
案例4:
RET = P4IN 和 PIN_NO;
中断;
默认值:
RET =-1;
}
返回(RET);
}

/*********
*函数名称:GPIO_mux
*说明:选择 GPIO 备用函数
*返回 :0 =成功
-1 =失败
*参数 : @PORT_NO =端口号
@PINS_NO =引脚到多路复用器
/
signed char
GPIO_mux (unsigned char port_no、unsigned char pins_no)
{
signed char ret = 0;
if (pins_no > MAX_PIN_NO_INVALID)
PORT_NO = 0;
开关(PORT_NO)
{
案例1:
P1SEL|= PINS_NO;
中断;
案例2:
P2SEL|= PINS_NO;
中断;
案例3:
P3SEL|= PINS_NO;
中断;
案例4:
P4SEL|= PINS_NO;
中断;
默认值:
RET =-1;
}
返回(RET);
}

UART.c.

/* Lib 包括*/
#include 
#include "GPIO_DRIVER.h"

/*定义*/
#define UARTA0_PORT_NO0x03//* P3 *
/#define UARTA0_PINS_MUX_VAL0x30// P3.4 (TXD)& P3.5 (RXD)*//

本地函数声明*/
static void UART_MUX_PINS ();
void-*-/UART-(-* static-/UART-)

函数定义-------------------------------------------------------- */
static void
UART_mux_pins ()
{
signed char ret;
if (ret = GPIO_mux (UARTA0_PORT_NO、UARTA0_PINS_MUX_VAL)=-1)
{
/*调试代码- LED 闪烁5次、表示出现故障*/
}
其他
{
/*调试代码- LED 闪烁2次、表示所有正常*/
}
}

静态空
UART_CONFIGURE ()
{
//寄存器设置*/
UCA0CTL0 = 0x00;
UCA0CTL1 |= UCSWRST + UCSSEL_2;
UCA0BR0 = 0x65;
UCA0BR1 = 0x03;
UCA0MCTL = UCBRS_1;
// UCA0BR0 |= UCATX2
~

;UCARXIE= UCA0ST2;UCARXIE*= UCA0MCTL |= UCARXIE2;UCARXIESD*= UCA0+ UCA0 = UCA0 |= UCA0;UCA0 = UCA0 = UCA0 = UCAST+ UCA0



/*启用全局/可屏蔽中断*/
_BIS_SR (GIE);
}

void
UART_init ()
{
UART_mux_pins ();
UART_configure ();
}/../../---------------

//
// 发送和接收中断 ///////---------------
//

#pragma vector = USCIAB0TX_Vector
__interrupt void
TransmitInterrupt (void)
{
GPIO_write (0x01、0x01);
}

#pragma vector = USCIAB0RX_vector
__interrupt void
ReceiveInterrupt (void)
{
IFG2 &&~UCA0RXIFG;
}

3.主要.c.

/* Lib 包括*/
#include 
#include "GPIO_DRIVER.h"
#include "UART_DRIVER.h"

int
main ()
{
signed char ret = 0;
WDTCTL = WDTPW + WDTHOLD;//如果

(CALBC1_1MHz = 0xFF)则停止看门狗//如果校准常数被擦除
{
同时(1);//不加载,陷阱 CPU!
}

DCOCTL = 0;//选择最低 DCOx 和 MODx 设置
BCSCTL1 = CALBC1_8MHZ;//设置范围
DCOCTL = CALDCO_8MHZ;//设置 DCO 阶跃+调制
if (ret = GPIO_configure (1、0x01)=-1)
{
/*调试代码- LED 闪烁5次、表示出现故障*/
}
UART_INIT ();
UCA0TXBUF ='A';
} 

目前、我只是希望从 MSP 向终端(/dev/ttyAMC0)发送一个字节。 我正在使用 MSP430 eZ430-RF2500开发工具。 我也尝试过环回测试、但不起作用。 为使其正常工作提供的任何支持都很有帮助。谢谢。

Vinay Divakar

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您连接到 P3.4和 P3.5的是什么?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >TransmitInterrupt (void)
    >{
    gpio_write (0x01,0x01);
    >}

    This ISR doesn't do anything to clear the Tx interrupt. As soon as you set GIE, this interrupt will trigger continuously, and you'll never get to the point of writing to TXBUF.

    一个简单的修复方法是将 UCA0TXBUF='A'移动到传输中断。 这将为您提供一串'A'字符、而不是单个字符、但您可能会发现调试更容易。 长期而言、您可能会定期在 ISR 中设置 UCA0TXBUF。

    未经请求:我的计算器显示1MHz/0x365在1200bps 的基础上关闭了>4%。 只有你知道你在这里要做什么、但是一个833=0x341的分频值应该可以得到非常准确的1200bps。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    、 我没有将任何东西连接到 P3.4和 P3.5。 我假设它们已经连接到 UART 到板载 USB 转换器、通过该转换器可以向串行终端发送字节并从串行终端接收字节。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    ,我做了您建议的更改,现在我在串行终端上看到了一串'A'字符。 但是,我有一些澄清,只是为了确保我的理解正确,我们在这里的同一页上。

    关于清除 Tx 中断、您是否意味着在我将数据字节放入 UCA0TXBUF 后立即清除 IFG2中的 UCA0TXIFG (这应该通过 s/w -手动完成)? 一旦 UCA0TXBUF 中的字节被输出并且变为空、那么在这个情况下、UCA0TXIFG 标志是否不会自动置位? 指示它已准备好接收下一个字节的数据。

    关于我在代码中设置 GIE 后立即连续触发中断的问题。 您是不是说、在软件中的那个实例中、UCA0TXBUF 是空的、这反过来又持续触发 Tx 中断 ISR、从而持续设置 UCA0TXIFG 标志?

    3) 3)如果我在设置 GIE 之前放置语句"UCA0TXBUF ='A':"、然后在设置 GIE 之后、我始终检查是否设置 UCA0TXIFG。 如果置位、我将下一个数据字节放入 UCA0TXBUF 中。 通过这种方式、我可以编写子例程、将多个数据字节发送到串行终端。 这是否可行?

    有关上述内容的任何见解都将有所帮助。

    未经请求:这是一个很好的收获。 我在 UCA0BR0中设置的值也出错了、它应该是0x41、即十进制的65、对于8 MHz 时钟的9600 bps。 谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    1) 1)存储到 TXBUF 中会清除 TXIFG、至少会有一段时间。 你可以明确地清除 TXIFG,但我不推荐它(习惯)--如果你没有要发送的东西,就关闭 TXIE。 当您有新数据要发送时(并且您只需重新开启 TXIE)、TXIFG 就会处于"已接收"状态。

    2) 2)是的。 如果你不以某种方式使 TXIFG 变为0、中断条件将保持、你将直接退回到 ISR (永远)。 TXIFG 不会通过进入 ISR 自动清零。

    3) 3)您刚才介绍了"轮询模式"、这也是一种非常好的执行方式(优点和缺点以及所有这些优点)。 对于轮询模式、请勿打开 TXIE (您可以丢弃 ISR)。

    TI 有一组 F2274示例(请查看产品页面),我很确定 UART --轮询模式和中断模式--都涵盖在这里。 我怀疑如果您谷歌搜索"MSP430 UART 循环缓冲器"(或某些此类缓冲器)、您会发现许多其他人如何执行中断模式的示例。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢、我已经下载了代码示例。 但是、我不想像示例中所示那样在 ISR 内执行到 TXBUFF 的写入。 我希望有一个独立于 ISR 的独立例程来打印字符串。 接下来、我要问最后一个与 IFG2中的 TXIFG 标志相关的问题。  

    当我们 在打开 TXIE 前将一个字节复制到 TXBUFF 寄存器时、TXIFG 的状态是什么? 如下代码片段所示:

    unsigned char UART_PrintStr (char * str_ptr){
    int len = 0、i = 0;
    len = strlen (len_ptr);
    while (str!= 0){
    /*默认情况下、IFG2中的 TXIFG 为'1'*/
    如果((IFG2 & 0x02)= 1){
    /* TXIFG 现在会发生什么情况? *
    UCA0TXBUF = str_ptr [i++];
    
    /*打开 TXIE */
    IE2 |= UCA0TXIE;
    
    len-;
    }
    }
    /* TXIE 的翻转*/
    IE2 = 0x00;
    } 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当 TXBUF 变为空(恰好在复位之后、或者当字节已经被移动到内部输出移位寄存器时)、TXIFG 被置位。

    当您写入 TXBUF 时、TXIFG 被清零。

    如果 UART 之前处于空闲状态、那么它将立即开始输出字节、并且 TXBUF 将很快再次变为空闲状态。 因此、在这种情况下、TXIFG 可能会再次被置位(用于下一个字节)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    那么、基本上、您是说 TXIFG 的设置或清零独立于正在设置或未设置的 TXIE、还是完全独立于 TX 中断使能位?。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、TXIFG 和 TXIE 完全独立。

    (只有当两个位(和 GIE)都被置位时、才会获得一个中断。)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Clemens Ladisch 几乎解释了所有事情、但具体而言:

    1) 1)您实现了轮询模式、这很好;只需删除对 TXIE 的引用、因为它们会使您遇到问题。

    2)> if (((IFG2 & 0x02)= 1){

    此条件从不为真。 尝试:

    > IF (IFG2 & 0x02){

    或更好的:

    > IF (IFG2 & UCA0TXIFG){

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我能够将字符传输到终端。 但是、我注意到一些奇怪的东西、即一些字符丢失了。 例如、 如果我发送一个字符串"Hello World"、它将打印为"Hello wod"、如果该字符串足够长、则会丢失几个字符。 我不知道为什么会发生这种情况。 下面是我用于打印字符串的代码片段。

    unsigned char
    UART_PrintStr (char * str_ptr)
    {
    int len = 0、i = 0、ret = 0;
    len = strlen (str_ptr);
    ret = len;
    while (len!= 0)
    {
    while (!(IFG2 & UCA0TXIFG));
    UCA0TXBUF = str_ptr [i++];
    len-;
    }
    返回(RET);
    }
    
    

    我正尝试按以下方式打印字符串:

    UART_PrintStr ("欢迎使用 DeplyEmbedded!\r\n"); 

    此外、不再使用 TXIE (中断)。 对这个问题的任何见解都将是有益的。 谢谢。

    PS:我正在使用 eZ430-RF2500开发工具。

    
    


     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    代码对我来说看起来很好。 我不记得在 eZ430上看到了这个症状、但自从我使用它已经有一段时间了。

    您是否仍在设置 UCA0MCTL?

    导线另一端是哪种设备?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、我确实设置了 UCA0MCTL。 下面是我执行的 UARTA0寄存器设置:

    静态空
    UART_configure ()
    {
    /*寄存器设置*/
    UCA0CTL0 = 0x00;
    UCA0CTL1 |= UCSWRST + UCSSEL_2;
    UCA0BR0 = 0x41;
    UCA0BR1 = 0x03;
    UCA0MCTL = UCBRS_1;
    UCA0CTL1 &=~UCSWRST;
    // IE2 |= UCA0RXIE;
    }
    

    另一端是我的笔记本电脑。 我只需打开 gtkterm、将端口配置为9600bps 并在 eZ430上运行程序。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    各位、对该问题的故障排除有任何见解吗? 我需要尽快发布这些 API。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我没有任何等效的设备、因此我无法尝试。

    我从未有机会将 UCA0MCTL 设置为0以外的任何值。 也就是说、我不能声称这会导致您的症状。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我尝试运行连接到另一台 PC 的 USB 端口的设备、假设问题可能是接触松动、但同样的问题仍然存在。 更改 UCA0MCTL 不起作用。

    所有这些之后、我现在怀疑它是硬件问题或 USB 转 UART 转换器芯片的问题。 因此、将尝试在另一个 MSP430上运行软件并进行检查。 谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、我还会在这个问题上取得一些进展。

    我使用另一个硬件测试了该程序,同一问题仍然存在。 然后、在代码中添加较长的延迟后、程序能够以非常慢的速率打印所有字符。 这种修复方法很奇怪、很丑、毫无意义。

    我假设可能是字符丢失、因为新字节正在被加载到 TXBUF 中、取代了之前的字节、即使在将前一个字节送入终端之前也是如此(UCA0TXIFG 始终为"0"?)。 因此、在终端上打印完每个字符后、在代码中、我在将下一个字节写入 TXBUF 之前给予了很长的延迟。 我尝试将此延迟进一步减少到100 us、但随后缺失字符的问题再次出现。

    现在、我确定这不是硬件问题、我不确定我在软件中做什么是错误的。 下面是代码片段、其中包含我为打印字符串而添加的延迟。

    unsigned char
    UART_PrintStr (char * str_ptr)
    {
    int len = 0、i = 0、ret = 0;
    len = strlen (str_ptr);
    ret = len;
    while (len!= 0)
    {
    while (!(IFG2 & UCA0TXIFG));
    UCA0TXBUF = str_ptr [i++];
    len-;
    __delay_cycles (800000);
    }
    返回(RET);
    }
    

    我还附加了源代码文件。 如果您能深入了解此问题的原因并在不需要增加延迟的情况下使其正常工作、将会有所帮助。 谢谢。

    e2e.ti.com/.../msp430_5F00_codes.tar.gz