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.

[参考译文] CCS/MSP430F5529:使用 MSP430F5529读取 SparkFun ADXL335加速计

Guru**** 2589280 points
Other Parts Discussed in Thread: MSP430F5529

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/956204/ccs-msp430f5529-reading-sparkfun-adxl335-accelerometer-with-msp430f5529

器件型号:MSP430F5529

工具/软件:Code Composer Studio

大家好、

我尝试使用 MSP430F5529连接标准 ADXL335加速计、但我卡在了。  在分享代码之前、我应该解释如何连接代码:

P3.3和 P3.4跳转到 launchpad USB 侧的 TXD/RXD 引脚。

S1旁边的5V 和 GND 引脚连接到 ADXL335 VCC 和 GND。

ADXL335的 X、Y 和 Z 引脚分别连接到 P6.0 (A0)、P6.1 (A1)和 P6.2 (A2)。

我打开了串行应用程序、并将其设置为38400波特、8位、无奇偶校验、1个停止位(当然在正确的 COM 端口上)。

我以前用这个电路板做过一些类似的串行功能、使用端子输入/输出、但是我从未尝试使用这个加速计。  我没有获得串行应用程序的任何输出。

以下是我的代码:

#include 
#include 

void turn off ();
void sendData ();
void UART_putchar (char);
void 初始化 eUART ();

volatile long int adval、ADCYval、ADCZval;
volatile float X、YCX3 Zoil-;
volatile float NetG;
void main (void)
{
int i;

WDTCTL = WDTPW +WDTHOLD; //停止 WDT
初始化 UART(); //为 RS-232设置 UART

P6DIR &=~(BIT0+BIT1 + BIT2); //将 P6.0、P6.1、P6.2配置为输入引脚
P6SEL |=(BIT0+BIT1 + BIT2); //将 P6.0 (X)、P6.1 (Y)和 P6.2 (Z)配置为模拟引脚

//设置计时器每100ms 向 PC 发送一次 ADC 信息
TA0CCR0 = 6554; // 6554 / 32768 Hz = 0.2s =>每秒触发5个计时器
TA0CTL = tassel_1 + MC_1; // ACLK、向上计数模式
TA0CCTL0 = CCIE; //启用中断

//设置 ADC 12.
ADC12CTL0 = ADC12ON + ADC12SHT0_6 + ADC12MSC;//配置 ADC 转换器
ADC12CTL1 = ADC12SHP+ADC12CONSEQ_1; //使用重复采样计时器
ADC12MCTL0 = ADC12INCH_3; // ADC A0引脚- X 轴
ADC12MCTL1 = ADC12INCH_4; // ADC A1引脚- Y 轴
ADC12MCTL2 = ADC12INCH_5 + ADC12EOS; // ADC A2引脚- Z 轴
// EOS -转换序列结束
ADC12IE |= 0x02; //启用 ADC12IFG.8
对于(I = 0;I < 0x3600;I++); //基准启动延迟
ADC12CTL0 |= ADC12ENC; //启用转换

_EINT();

while (1){
ADC12CTL0 |= ADC12SC; //开始转换
_bis_SR_register (LPM0_Bits + GIE);//输入 LPM0
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//用户定义的函数定义
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void UART_putchar (char c)
{
while (!(UCA0IFG&UCTXIFG)); //等待前一个字符被发送
UCA0TXBUF = c; //将字节发送到缓冲区以进行
传输}

//初始化用于传输数据的 UART 控制寄存器,以及波特率
void 初始化 UART (void)
{
P3SEL |= BIT3 + BIT4; //设置 Rx 和 Tx 位
UCA0CTL0 = 0; //设置默认 RS-232协议
UCA0CTL1 |= BIT0 + UCSSEL_2; //禁用设备,设置时钟
UCA0BR0 = 27; // 1048576 Hz / 38400 = 54.5
UCA0BR1=0;
UCA0MCTL = 0x94;
UCA0CTL1 &=~BIT0; //启动 UART 设备
}

void sendData (void)
{
int i;
XINL =((ADCXval*3.0/4095.0)-1.5)/0.3; //计算 x 的 g
YL8 =((ADCYval*3.0/4095.0)-1.5)/0.3; //计算 y 的 g
ZL8 =((ADCZval* 3.0/4095.0)-1.5)/0.3; //计算 z 的 g
NetG = sqrt (((((oirl*x)+(Yo*l)+(Zo*))+(Zo)Zo)Zo)Zo;Zo;
//通过 RS-232发送数据包
UART_putchar (0x55); //发送标头

//使用字符指针一次发送一个字节的浮点 X 和 Y 值
char *XPointer=(char *)&Xan3;
char *ypointer=(char *)&Yan3;
char *zpointer=(char *)&Z3;

//发送 x 百分比浮点一次一个字节
for (i=0;i<4;i++){
UART_putchar (XPointer[i]);
}

//发送 y 百分比浮点一次一个字节
for (i=0;i<4;i++){
UART_putchar (ypointer[i]);
}

//发送 z 百分比浮点一次一个字节
对于(i=0;i<4;i++){
UART_putchar (zpointer[i]);

}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//中断服务例程
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma vector=ADC12_vector
_interrupt void ADC12ISR (void)
{
ADCXval = ADC12MEM0; //移动结果,IFG 被清除
ADCYval = ADC12MEM1;
ADCZval = ADC12MEM2;
_BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0

if (NetG >= 2.0)
{

P3DIR |= BIT5;//设置蜂鸣器的方向
P3SEL |= BIT5;//将蜂鸣器设置为 I/O 的特殊功能
TB0CCTL4 = OUTMOD_4;// TB0输出处于切换模式
TB0CTL = TBSSEL_2 + MC_1;// SMCLK 是时钟源、上行模式
TB0CCR0=852; //CCrO=1MHz/2 (852)
}
其他
{
P3DIR &=~BIT4;
}
}

#pragma vector = TIMERRA0_vector
__interrupt void timerA_ISR ()
{
sendData(); //将数据发送到串行应用程序
_BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
}

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

    ' S1旁边的5V 和 GND 引脚连接到 ADXL335 VCC 和 GND。'

    这将是一个问题、因为绝对最大 Vcc 为3.6V。

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

    如果您在调试器中暂停、您在执行什么操作? 我猜它在 ISR_TRAP 中、因此:

    #pragma vector = TIMERA0_vector

    应该是什么

    >#pragma vector = TIMER0_A0_vector

    -------- 这些不会导致无输出、但会为您提供不正确的输出:

    >    ADC12MCTL0 = ADC12INCH_3;                       // ADC A0 pin - X-axis
    >    ADC12MCTL1 = ADC12INCH_4;                       // ADC A1 pin - Y-axis
    >    ADC12MCTL2 = ADC12INCH_5 + ADC12EOS;            // ADC A2 pin - Z-axis

    These refer to A3/A4/A5. I suspect you meant:

    >    ADC12MCTL0 = ADC12INCH_0;                       // ADC A0 pin - X-axis
    >    ADC12MCTL1 = ADC12INCH_1;                       // ADC A1 pin - Y-axis
    >    ADC12MCTL2 = ADC12INCH_2 + ADC12EOS;            // ADC A2 pin - Z-axis

    --------

    >    ADC12IE |= 0x02;                    // Enable ADC12IFG.8
    这将启用 ADC12IFG1。 我怀疑您的意思是:
    >    ADC12IE |= 0x04;                    // Enable ADC12IFG.2
     

     

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

    谢谢 David、我不确定我在哪里得到5V 电压。  谢谢您、Bruce、我阅读的数据表中有关这些 ADC 引脚的错误信息。  我现在已经更新了我的代码(对 UART 设置进行了另一个细微的更改)、我正在获取输出、但这是垃圾。  我打开了一个终端会话、只是为了查看它的外观、我会得到一些胡说的字符:

    ▒U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒▒▒ U▒▒▒▒

    如果我不得不猜测、我认为我的数字转换有问题。

    以下是更新后的代码:

    #include 
    #include 
    
    void turn off ();
    void sendData ();
    void UART_putchar (char);
    void 初始化 eUART ();
    
    volatile long int adval、ADCYval、ADCZval;
    volatile float X、YCX3 Zoil-;
    volatile float NetG;
    void main (void)
    {
    int i;
    
    WDTCTL = WDTPW +WDTHOLD; //停止 WDT
    初始化 UART(); //为 RS-232设置 UART
    
    P6DIR &=~(BIT0+BIT1 + BIT2); //将 P6.0、P6.1、P6.2配置为输入引脚
    P6SEL |=(BIT0+BIT1 + BIT2); //将 P6.0 (X)、P6.1 (Y)和 P6.2 (Z)配置为模拟引脚
    
    //设置计时器每100ms 向 PC 发送一次 ADC 信息
    TA0CCR0 = 6554; // 6554 / 32768 Hz = 0.2s =>每秒触发5个计时器
    TA0CTL = tassel_1 + MC_1; // ACLK、向上计数模式
    TA0CCTL0 = CCIE; //启用中断
    
    //设置 ADC 12.
    ADC12CTL0 = ADC12ON + ADC12SHT0_6 + ADC12MSC;//配置 ADC 转换器
    ADC12CTL1 = ADC12SHP+ADC12CONSEQ_1; //使用重复采样计时器
    ADC12MCTL0 = ADC12INCH_0; // ADC A0引脚- X 轴
    ADC12MCTL1 = ADC12INCH_1; // ADC A1引脚- Y 轴
    ADC12MCTL2 = ADC12INCH_2 + ADC12EOS; // ADC A2引脚- Z 轴
    // EOS -转换序列结束
    ADC12IE |= 0x02; //启用 ADC12IFG.8
    对于(I = 0;I < 0x3600;I++); //基准启动延迟
    ADC12IE |= 0x04; //启用 ADC12IFG.2
    
    _EINT();
    
    while (1)
    {
    ADC12CTL0 |= ADC12SC; //开始转换
    _bis_SR_register (LPM0_Bits + GIE);//输入 LPM0
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    //用户定义的函数定义
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    void UART_putchar (char c)
    {
    while (!(UCA0IFG&UCTXIFG)); //等待前一个字符被发送
    UCA0TXBUF = c; //将字节发送到缓冲区以进行
    传输}
    
    //初始化用于传输数据的 UART 控制寄存器,以及波特率
    void 初始化 UART (void)
    {
    P3SEL |= BIT3 + BIT4; //将 USCI_A0 RXD/TXD 设置为接收/发送数据
    UCA0CTL1 |= UCSWRST; //设置初始化期间的软件复位
    UCA0CTL0 = 0; // USCI_A0控制寄存器
    UCA0CTL1 |= UCSSEL_2; //时钟源 SMCLK
    UCA0BR0 = 0x09; // 1048576 Hz / 115200低位字节
    UCA0BR1 = 0x00; //高位字节
    UCA0MCTL |= UCBRS0; //调制(UCBRS0=0x01、UCOS16=0)
    UCA0CTL1 &=~UCSWRST; //清除软件复位以初始化 USCI 状态机
    }
    
    void sendData (void)
    {
    int i;
    XINL =((ADCXval*3.0/4095.0)-1.5)/0.3; //计算 x 的 g
    YL8 =((ADCYval*3.0/4095.0)-1.5)/0.3; //计算 y 的 g
    ZL8 =((ADCZval* 3.0/4095.0)-1.5)/0.3; //计算 z 的 g
    NetG = sqrt (((((oirl*x)+(Yo*l)+(Zo*))+(Zo)Zo)Zo)Zo;Zo;
    //通过 RS-232发送数据包
    UART_putchar (0x55); //发送标头
    
    //使用字符指针一次发送一个字节的浮点 X 和 Y 值
    char *XPointer=(char *)&Xan3;
    char *ypointer=(char *)&Yan3;
    char *zpointer=(char *)&Z3;
    
    //发送 x 百分比浮点一次一个字节
    for (i=0;i<4;i++){
    UART_putchar (XPointer[i]);
    }
    
    //发送 y 百分比浮点一次一个字节
    for (i=0;i<4;i++){
    UART_putchar (ypointer[i]);
    }
    
    //发送 z 百分比浮点一次一个字节
    对于(i=0;i<4;i++){
    UART_putchar (zpointer[i]);
    
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    //中断服务例程
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    #pragma vector=ADC12_vector
    _interrupt void ADC12ISR (void)
    {
    ADCXval = ADC12MEM0; //移动结果,IFG 被清除
    ADCYval = ADC12MEM1;
    ADCZval = ADC12MEM2;
    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
    
    if (NetG >= 2.0)
    {
    
    P3DIR |= BIT5;//设置蜂鸣器的方向
    P3SEL |= BIT5;//将蜂鸣器设置为 I/O 的特殊功能
    TB0CCTL4 = OUTMOD_4;// TB0输出处于切换模式
    TB0CTL = TBSSEL_2 + MC_1;// SMCLK 是时钟源、上行模式
    TB0CCR0=852; //CCrO=1MHz/2 (852)
    }
    其他
    {
    P3DIR &=~BIT4;
    }
    }
    
    #pragma vector = TIMER0_A0_vector
    __interrupt void timerA_ISR ()
    {
    sendData(); //将数据发送到串行应用程序
    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
    }
    

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

    我在那里粘贴了一条错误的行。  第34-36行实际上是:

    ADC12IE |= 0x04;//启用 ADC12IFG.2
    对于(I = 0;I < 0x3600;I++);//基准启动延迟
    ADC12CTL0 |= ADC12ENC;//启用转换

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

    您正在发送非 ASCII、因此我不确定如何读取跟踪。 您的终端程序可能具有十六进制显示吗?

    或者您是否打算发送 ASCII (即人类可读)? snprintf()可能会对此有所帮助。

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

    这款串行应用程序看起来都是图形显示。  我根本看不到任何十六进制显示。  我用于向其发送数据的代码段在示例中提供、但老实说、此应用程序非常简单。

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

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

    等待、您必须手动将通道添加到图形中...DOH

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

    最后一个问题是:

    如果我启用32ms 间隔的 WDT、代码将不起作用、因为 WDT 间隔发生得太快、ADC 中断无法得到响应。  我可以触发 ADC ISR 内部的 WDT 中断、但我不确定是否可以手动设置 WDTIFG 标志、并让它在不启用 WDT 的情况下实际进入 WDT ISR。  这是可行的吗?

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

    我没有尝试过这个特定的组合、但是通常情况下、软件可以设置一个 IFG (及其 IE)并且中断将被触发。

    我想我错过了几个步骤--你的数据现在还可以吗?

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

    是的、现在看起来还可以。  我只是想了解是否有手动设置/清除 WDTIFG 的命令。  我已经使用如下引脚完成了此操作:

    P2IFG |= BIT1;

    然后在进入该 ISR 时通过执行相反的操作将其清除:

    P2IFG &=~BIT1;

    但是、我不确定如何为 WDTIFG 执行此操作。  为了设置标志、我将其设置为等于什么?

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

    我有一个想法、但我不确定它是否起作用。

    #pragma vector=ADC12_vector
    _interrupt void ADC12ISR (void)
    {
    ADCXval = ADC12MEM0; //移动结果,IFG 被清除
    ADCYval = ADC12MEM1;
    ADCZval = ADC12MEM2;
    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
    
    if (NetG >= 2.0)
    {
    //将 WDTIFG 设置为进入 WDT_ISR;
    }
    }
    
    #pragma vector = TIMER0_A0_vector
    __interrupt void timerA_ISR ()
    {
    sendData(); //将数据发送到串行应用程序
    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
    }
    
    #pragma vector = WDT_vector // WDT ISR
    __interrupt void watchdog_timer (void)
    {
    while (1)
    {
    __DELAY_CYCLES (50000);//DELAY 0.5s -- 0.5s 导通/0.5s 关断--> 1Hz
    P1OUT ^= BIT0;
    P4OUT ^= BIT7;
    }
    } 

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

    正如我说过的、我没有尝试过这种方法、但我希望您能这么做  

    WDTCTL = WDTPW | WDTTMSEL | WDTHOLD;//请求间隔定时器模式
    SFRIE1 |= WDTIE;
    SFRIFG1 |= WDTIFG;
    

    您最终会进入 WDT_Vector。 您可以在此处清除 WDTIFG。

    我仍然不确定您想要实现什么。

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

    哦、我只是好奇它是否可以实现。  非常感谢 Bruce、您总是非常乐于助人。