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.

[参考译文] MSP430G2553:在具有 BoosterPack 的 Launchpad 上进行编程仅在调试时有效

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1405748/msp430g2553-program-on-launchpad-with-boosterpack-only-works-when-debugging

器件型号:MSP430G2553

工具与软件:

您好:

提前感谢您提供的任何帮助。 我在 MSP-EXP430G2 Launchpad 开发套件上运行一个应用、但使用的是较旧的 CircuitCo 教育版 BoosterPack。 应用程序使用霍尔效应传感器来确定主轴的速度、并在我调试应用时将其显示在 BoosterPack LCD 上、但当我退出调试器时、LCD 上显示的最后一位信息会在退出之前保留、并且主轴速度不会更新。 当我移除仿真板的跳线并通过 J6从外部电源为器件供电时、该应用也无法正常工作。 上电后、我必须按下复位按钮、然后只能看到开始启动界面、不显示主轴速度。

我已经查看过各种论坛中的一些使用调试器运行代码的示例、而不是在调试器关闭时运行代码、但我在这些示例中看不到与我的情况相关的内容。

您对如何解决此问题有什么建议吗? 再次感谢。

设置:

Code Composer Studio 版本:11.1.0.00011、运行 Windows 10的 PC。

观看安装在 launchpad 板上的晶体并移除 EDU BoosterPack 上的白色 LED (我将使用该引脚13作为霍尔效应传感器电路的输入)。

霍尔效应传感器电路。

和我的代码。

#include <msp430.h> 
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <intrinsics.h>

#define EBP_CS BIT0    //chip select
#define EBP_CLK BIT5   //clock
#define EBP_MOSI BIT7  //data line
#define EBP_RS BIT3    //command vs data
#define SENSOR_PIN BIT5   //attach key to P2_5 TA1.2
#define AFTER_BUSY_DELAY 40  //used to wait additional time after UCBUSY clears

void InitBPLCD(void);
void InitSPI(void);
void InitPorts(void);
void InitHallSensor(void);
void itoa(long unsigned int value, char *result, unsigned int base);

unsigned int WriteCommand(unsigned int cmd);
void WriteData(void);
void ClearHome(void);
void SetRowLine(unsigned int row, unsigned int line);

char charsToLCD[32] = {'\0'};
uint32_t timerDiff = 0;
uint8_t computeSpeed = 0;
uint8_t speedCount = 0;

volatile unsigned int cntOvrFloTAR = 0;
volatile unsigned int sendData = 0;
volatile uint16_t currTimerCounts = 4;
volatile uint16_t prevTimerCounts = 0;


/**
 * main.c
 */
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	//set up Basic Clock Module
    BCSCTL1 |= DIVA_3; //this write clears all other bits; divide ACLK/8
    BCSCTL3 |= XCAP_3; //sets internal capacitance for watch crystal

	InitPorts();
	InitSPI();
	InitHallSensor();
	InitBPLCD();
    __delay_cycles(1000);
    strcpy(charsToLCD, "0123456789012345testing testing!");
    WriteData();
    __delay_cycles(1000);

    //Set up Timer1A
    // capture on rising edge, CCI2B input, synchronous cap, capture mode, ints enabled
    TA1CCTL2 = CM_1 | CCIS_1 | SCS | CAP | CCIE;
    // Continuous, divide clock by 1, ACLK, clear, enable
    TA1CTL = MC_2 | ID_0 | TASSEL_1 | TACLR | TAIE;
    __enable_interrupt();

    for(;;){
        // do nothing
        if (computeSpeed > 0){
            computeSpeed = 0;
            timerDiff = currTimerCounts - prevTimerCounts;
            //clear buffer
            charsToLCD[0] = '\0';
            itoa(timerDiff, charsToLCD, 10);
            WriteData();
        }
        /*
        if (sendData == 2)
        {
            sendData = 0;
            charsToLCD[0] = '\0';
            strcpy(charsToLCD, "0123456789012345running testing!");
            WriteData();
        }
        */
    }

	return 0;
}
#pragma vector = TIMER1_A1_VECTOR
__interrupt void TIMER1_A1_ISR (void){
    switch (__even_in_range(TA1IV, 10)){
    case 0:
        break;
    case TA1IV_TACCR2:
        TA1CCTL2 &= ~CCIE;    // disable further CCIE interrupts
        prevTimerCounts = currTimerCounts;
        currTimerCounts = TA1CCR2;
        ++speedCount;
        if (speedCount > 3){
            computeSpeed = 1;
            speedCount = 0;
        }
        cntOvrFloTAR = 0; //reset TAR rollover counter
        TA1CCTL2 &= ~CCIFG; // clear the CCRO flag
        TA1CCTL2 |= CCIE; //enable interrupts
        break;
    case TA1IV_TAIFG:
        ++cntOvrFloTAR;
        /*if (cntOvrFloTAR > 2){ // been idle
            //set flag to go to sleep
            cntOvrFloTAR = 0;
            sendData = 2;
        }else{
            sendData = 1;
        }*/
        break;
    default:
        for (;;){
            //Should not be possible
        }
    }
}
void InitBPLCD(void){ //copying bp_LCD.cpp from Energia sketch
    WriteCommand(0x30); //function set
    __delay_cycles(27);
    WriteCommand(0x30); //function set
    __delay_cycles(27);
    WriteCommand(0x30); //function set
    __delay_cycles(27);
    WriteCommand(0x14); //cursor/display shift
    __delay_cycles(27);
    WriteCommand(0x0c); //display on/off
    __delay_cycles(27);
    WriteCommand(0x06); //entry mode set
    __delay_cycles(27);
    WriteCommand(0x39); //function set (2 lines, instruction table 1)
    __delay_cycles(27);
    ClearHome(); //clear
    WriteCommand(0x57); //power/ICON control/contrast set upper bits
    __delay_cycles(27);
    WriteCommand(0x6b); //follower control
    __delay_cycles(27);
    WriteCommand(0x72); //contrast set lower bits
    __delay_cycles(1000);
}
unsigned int WriteCommand(unsigned int cmd){
    if (UC0IFG & UCB0TXIFG){  //ready for new data?
        P2OUT &= ~(EBP_RS + EBP_CS); // need to clear _SS and RS LOW for command
        __delay_cycles(10);
        UCB0TXBUF = cmd; //begin transaction
        while(UCB0STAT & UCBUSY); //wait for transfer to finish
        __delay_cycles(AFTER_BUSY_DELAY);
        P2OUT |= EBP_RS + EBP_CS;
    }
    __delay_cycles(5);
    return 1;
}
void ClearHome(void){
    unsigned int wait = WriteCommand(0x01);
    if (wait == 1){
        WriteCommand(0x02);
    }
}
void WriteData(void){
    ClearHome();
    SetRowLine(0,0);
    char *ptr_lcdUp = charsToLCD;
    char *ptr_lcdLow = charsToLCD + 16;
    unsigned int i;
    for(i = 0; i < 16 && *ptr_lcdUp != '\0'; ++i, ++ptr_lcdUp){
        if (UC0IFG & UCB0TXIFG){  //ready for new data?
            P2OUT &= ~EBP_CS;
            __delay_cycles(10);
            UCB0TXBUF = *ptr_lcdUp;    //load shift register for transfer
            while(UCB0STAT & UCBUSY); //wait for transfer to finish
            __delay_cycles(AFTER_BUSY_DELAY);
            P2OUT |= EBP_CS; // need to set _SS HIGH
        }
    }
    SetRowLine(0,1);
    for(i = 0; i < 16 && *ptr_lcdLow != '\0'; ++i, ++ptr_lcdLow){
        if (UC0IFG & UCB0TXIFG){  //ready for new data?
            P2OUT &= ~EBP_CS;
            __delay_cycles(10);
            UCB0TXBUF = *ptr_lcdLow;    //load shift register for transfer
            while(UCB0STAT & UCBUSY); //wait for transfer to finish
            __delay_cycles(AFTER_BUSY_DELAY);
            P2OUT |= EBP_CS; // need to set _SS HIGH
        }
    }
}
void SetRowLine(unsigned int row, unsigned int line){
    //NewHaven LCD with 2 lines 16 rows, expect line (0,1) row (0,15)
    if ((row < 16) && (line < 2))
        WriteCommand(0x80 | (line * 0x40) | row);
}
void InitSPI(void){
    P2OUT |= (EBP_CS | EBP_RS); //start off high (
    P1SEL |= (EBP_CLK | EBP_MOSI);   //select primary peripheral USCI_B
    P1SEL2 = (EBP_CLK | EBP_MOSI);
    //SPI mode 3 needs CPOL=CKPL=1, CPHA=1 -> CKPH=0; msb first, master,
    //8 bit (default), 3-wire (default, mode 0), synchronous
    UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCMODE_0 | UCSYNC;
    UCB0CTL1 = UCSSEL1 | UCSWRST;  //clock from SMCLK; hold in reset
    UCB0BR1 = 0; //upper byte of divider word
    UCB0BR0 = 60; //Clock = SMCLK/60 = 100KHz
    UCB0STAT = UCLISTEN;  //Internal loopback; try this since no MISO pin
    UCB0CTL1 &= ~UCSWRST; //release from reset
}
void InitPorts(void){
    P1OUT = 0;
    P1DIR = 0xFF;
    P2OUT = 0;
    P2DIR = 0xFF;
}
void InitHallSensor(void){
    P2DIR &= ~SENSOR_PIN; //Set pin as input
    P2SEL |= SENSOR_PIN; //Set pin for Timer1_A CCI1A capture
}
void itoa(long unsigned int value, char* result, unsigned int base){
    // check that the base is legit
    if (base < 2 || base > 36) { *result = '\0';}

    char *ptr = result, *ptr1 = result, tmp_char;

    unsigned int tmp_value;

    do{
        tmp_value = value;
        value /= base;
        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    } while (value);

    //Apply negative sign
    if(tmp_value < 0) *ptr++ = '-';
    *ptr-- = '\0';
    while(ptr1 < ptr){
        tmp_char = *ptr;
        *ptr-- = *ptr1;
        *ptr1++ = tmp_char;
    }
}

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

    我不熟悉这个 Booster Pack。 您知道它是什么类型的 LCD 吗? 加电后启动可能需要一些时间-我看不到任何延迟。 (20-50ms 也不会令人惊讶。)

    更笼统地说:如果您仍然可以使用 P1.0 LED、您可以尝试在 HOME 环路中对其进行闪烁、以便您能够区分 LCD 未运行和 MCU 未运行。

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

    感谢您关注 Bruce。 该 LCD 是一款 Sitronix ST7032、我在教学日有一些这类 CircuitCo BoosterPack、我希望以某种方式进行使用。

    恰好在设置 Timer1A 后、我再施加第三个延迟。 您可以看到、在与该 LCD 的设置相关的主例程的开始位置已经存在另外两个。 添加这个额外的延迟并没有改变该行为。 当调试器处于活动状态时、系统行为正常、在上一行打印 TA1CCR2中两个定时器值的差值(主轴速度的倒数)。 当我退出调试器时、显示屏会显示退出前的最新情况、并且不会更新主轴速度。 如果我单击重置按钮、将显示初始屏幕("0123456789012345testing!") 即使主轴转动并在 P2.5上生成信号时、该情况仍然存在。

    按照您的建议、我在 timerA 溢出 ISR 中放了一个 P1.0 LED 切换开关、它表明当电路板被调试时、它闪烁、但当我退出调试器时、不再有 LED 闪烁、并且当我点击复位时、LED 从不闪烁(即使 LCD 如先前所述显示初始启动界面)。 我可以将示波器放置在手表晶振上(引脚18、19 XOUT、XIN)或者在运行 ACLK 时将它弄乱吗?

    我欢迎任何其他建议。 再次感谢、

    Nick

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

    在您的描述中、我阅读了两个可分离的症状:(1)调试器会话断开时程序(经常/始终)挂起(2)程序在上电时无法正常启动、需要单独的复位。 我不知道答案(1);我已经看到它很多次、但它没有打扰到我进行调查。 我一直专注于(2)、因为这确实需要发挥作用。 (复位也无法修复的情况(1)。)

    A)我的示波器探测晶体电路的结果有好有坏(结果可能模糊不清、但不会伤害任何东西)。 您可以在 P1.0上获得 ACLK、但我知道您已经在使用它了。 如果没有捕获、溢出发生将需要8*2=16秒、这有点乏味。 作为一个实验、您可以尝试设置 SCS=0、这样即使计时器未运行(类似于 GPIO 中断)也会允许捕获。  

    B) ST7032数据表(v1.4)似乎建议在上电后等待40ms、然后再尝试通信。 这对于情况(2)通常很重要。

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

    关注 LCD 是正确的。 我通过移除与应用相关的任何代码、简化了应用、并移除了 BoosterPack。 其余电路板和代码按预期工作。 在调试时、寄存器和变量会发生适当变化、调试器终止后、P1.0上的检测信号 LED 每16秒继续闪烁一次

    我还尝试了您的建议、即从 timerA 配置中删除 SCS、并将 LED 切换从检测信号 TA1IV 翻转移到 TA1IV_TACCR2 ISP 中。 确实有效。 随着主轴旋转、LED 会进行切换。 在我退出调试器后好像时钟没有运行、而且在单独为电路板加电时也不会启动。

    现在、请思考一下有关 ST7032的 BoosterPack 的想法。 当包含 BP 器件和 LCD 代码时、时钟运行速度会慢得多。 TA1IV 翻转更像是120秒(调试器运行时、未暂停)。 我认为这不是因为与 LCD 相关的任何内容导致调试器不运行。

    关于该 BoosterPack 还有一点。 设计该器件的工程师相信、他们可以让 SPI 芯片选择引脚悬空、在大多数情况下、该引脚是正常工作的。 那就是 ST7032数据表中的引脚2 (见下方)。 偶尔、但它不会同步。 我看到人们重新连接这个引脚的某个地方、这个黑客确实可靠地工作(我正在使用不同的电路板进行其他项目)。

    只要 LCD 连接可用。

    9     |   8    |    7    |  6  |   5    |   4  |  3 |    2 |   1  | 0       ST7032 LCD 引脚

                              ST7032数据表中的 C1-| C1+| VOUT | VDD | G | SI | SCK | CSB | RS | RST

    NC |  NC |   NC  | VCC |  GND |  P1.7 | P1.5 | P2.0     | P2.3 | NC  电流配置

    我注意到、我已在 InitSPI 例程中将 P1SEL2设置为(EBP_CLK | EBP_MOSI)、并将其更改为|=、而行为没有变化。

    再次感谢他们的任何想法,他们真的很有帮助。

    Nick

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

    我忽略了提一下、在这个不设置 SCS 的新配置中、当我退出调试器或用外部电源为电路板供电(并将仿真器从电路中取出)时、LCD 确实会报告 timerDiff 的值为0、如主函数的 for 循环中所述。 LCD 确实接受相应的值。 此外、正如我之前提到的、给电路板上电会显示空白屏幕、我必须点击复位按钮才能看到启动界面并获取 timerDiff printed 的值。

    N

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

    另一个实验:尝试设置

    > BCSCTL3 |= LFXT1S_2;// ACLK=VLOCLK

    VLOCLK 的运行频率有点类似于12kHz、因此计时会偏离为~3倍、但如果系统行为合理、则该点非常接近于晶体振荡器。

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

    将振荡器替换为 VLO 确实会使电路板正常工作。 我可以使用不太准确的时钟来完成、并且很乐意继续(关闭此主题)、除非对我而言有助于其他人深入探究此问题。 当我需要一个更准确的时钟(如果有)时、我可以再次访问它。 您是否认为尝试使用不同的32kHz 手表晶振来开发不同的电路板是解决此问题的良好下一步操作?

    N

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

    您可以考虑调整 BCSCTL3中的驱动强度(XCAP)。 这是一个很长的距离,但只有4种可能性。  

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

    好的、我给了其他的帽子设置一个试--没有喜悦。 我将这个线程保持打开状态一会儿、然后看看我能否想出导致 ACLK 在调试模式下与手表晶体一同工作的原因、但不能确定其他原因、如果我什么都不能想出、请关闭这个线程。 至少此项目将与 VLO 配合使用! 感谢你的帮助。 最后一个问题、您可以推荐一个可与 SPI 一起使用的小型 LCD、MSP430微控制器社区中更常用该 LCD 吗?

    谢谢、

    Nick

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

    正如我所理解的那样(?)、您拥有(a) G2 ("旧") Launchpad、Rev 1.4或1.5 (b)教育 Booster Pack (Mki、尽管他们不是这样称呼)、其中包含2x16字符 LCD。

    我想我找到了(b)[Doc "BP-EDUC-01"]的原理图、其中显示 P2.6 (XIN)连接到蜂鸣器(FET)、且没有跳线断开。 它是否仍然连接?

    [编辑:对于考古学家:这里有一个 Github 存储库:

    https://github.com/CircuitCo/Educational-BoosterPack-RevA2

    ]