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 I2C的问题

Guru**** 2188815 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/663884/ccs-msp430f5529-problem-with-msp430f5529-i2c

部件号:MSP430F5529

工具/软件:Code Composer Studio

尊敬的TI:我正在尝试让MSP430F5529上的I2C与Arduino 加速计 GY-521配合使用。 我设法让它在Arduino uno上工作,但我绝对不能让它在MSP430F5529上工作,即使在修改了TI资源浏览器上I2C的示例代码以只获得一个寄存器值之后也是如此。 我将在下面发布我的Arduino代码以及我的MSP430F5529代码,这些代码是从GY-521资源管理器上的示例标准主控I2C修改而来的。  

Arduino代码  

#include<Wire.h>
const int MPU_addr=0x68;// MPU-6050的I2C地址
int16_t acx,acy,acz,tmp,gyx,gyy,gyz;
void setup()
Wire.begin();
Wire.beginTransmission(MPU_addr);
wire.write (0x6B);// PWR_Mgmt_1寄存器
wire.write(0);//设置为零(唤醒MPU-6050)
wire.endTransmission (TRUE);
Serial.begin(9600);
}
void loop(){
Wire.beginTransmission(MPU_addr);
wire.write (0x3B);//从寄存器0x3B开始(ACCEL_XOUT_H)
wire.endTransmission (假);
wire.requestFrom (mpu_addr,14,true);//请求总共14个寄存器
ACX=Wire.Read()<<8|Wire.Read();// 0x3B (ACCEL_XOUT_H)和0x3C (ACCEL_XOUT_L)
acy=Wire.Read()<8|Wire.Read();// 0x3D (ACCEL_UTED_H)& 0x3E (ACCEL_UTED_L)
ACZ=Wire.Read()<<8|Wire.Read();// 0x3F (ACCEL_ZOUT_H)和0x40 (ACCEL_ZOUT_L)
TMP=Wire.Read()<8|Wire.Read();// 0x41 (TEMP_OUT _H)& 0x42 (TEMP_OUT _L)
GyX=Wire.Read()<8|Wire.Read();// 0x43 (Gyro_XOUT_H)和0x44 (Gyro_XOUT_L)
GyY=Wire.Read()<8|Wire.Read();// 0x45 (gyro_outy_H)和0x46 (gyro_outy_L)
Gyz=Wire.Read()<8|Wire.Read();// 0x47 (Gyro_ZOUT_H3)& 0x48 (Gyro_ZOUT_L)
serial.print ("ACX =");Serial.print (ACX);
serial.print ("| acy =");Serial.print (acy);
serial.print ("| ACZ =");serial.print (ACZ);
serial.print ("| tmp =");Serial.print (340.00 36.53);
//Serial.print ("| tmp =");Serial.print (tmp);//数据表中温度的公式(以摄氏度为单位)
serial.print ("| GyX =");Serial.print (GyX);
serial.print ("| GyY =");Serial.print (GyY);
serial.print ("| GyZ =");Serial.println (GyZ);
延迟(333);
}

MSP430F5529为GY-521修改的标准主代码

#include <MSP4S.h>
#include <stdint.h>
#include <stdbool.h>


//************************************************************************************************
//命令示例******************************************************************************
//************************************************************************************************

#define slaver_ADDR 0x68

/* CMD_TYPE_X_SLAVE是主服务器发送给从属服务器的命令示例。
*从属设备将发送示例SlaveTypeX缓冲区作为响应。
*
* CMD_TYPE_X_MASTER是主机发送给从属设备的命令示例。
*从属设备将初始化自身以接收MasterTypeX示例缓冲区。
***/

//#定义CMD_TYPE_0_SLAVE 0x41
#define CMD_TYPE_1_SLAVE 0x41
//#定义CMD_TYPE_2_SLAVE 2.

#define CMD_TYPE_0_MASTER 0x6b
#define CMD_TYPE_1_MASTER 0x3B
//#定义CMD_TYPE_2_MASTER 5.

#define type_0_length 1.
#define type_1_length 14.
//#定义type_2_length 6.

#define MAX_BUFFER_SIZE 20

/* MasterTypeX是在主控中初始化的示例缓冲区,它们将是
*由主设备发送至从属设备。
* SlaveTypeX是在从属设备中初始化的示例缓冲区
*由从属设备发送给主设备。
***/

//uint8_t MasterType2 [type_2_length]={'F','4','1','9','2', 'b'};
UINT8_t MasterType1 [TYPE_1_Length]={0};
UINT8_t MasterType0 [type_0_length]={0};


//uint8_t SlaveType2 [type_2_length]={0};
UINT8_t SlaveType1 [type_1_length]={0};
//uint8_t SlaveType0 [type_0_length]={0};

//uint16_t温度= 0;
int16_t acx,acy,acz,tmp,gyx,gyy,gyz;
浮动温度;

//************************************************************************************************
//通用I2C状态机*******************************************************************
//************************************************************************************************

typedef enum I2C_ModeEnum{
IDLE_MODE,
nack_mode,
TX_REG_ADDRESS_MODE,
RX_REG_ADDRESS_MODE,
TX_DATA_MODE,
RX_DATA_MODE,
Switch_to_RX_mode,
SWITHC_TO_TX_MODE,
timeout_mode
} I2C_Mode;

/*用于跟踪软件状态机的状态*/
I2C_Mode MasterMode = IDE_MODE;

/*要使用的注册地址/命令*/
UINT8_t TransmitRegAddr =0;

/* ReceiveBuffer:用于在ISR中接收数据的缓冲区
* RXByteCtr:接收的剩余字节数
* ReceiveIndex:ReceiveBuffer中要接收的下一个字节的索引
*传输缓冲区:用于在ISR中传输数据的缓冲区
* TXByteCtr:要传输的剩余字节数
* TransmitIndex:要在TransmitBuffer中传输的下一个字节的索引
***/
UINT8_t接收缓冲器[MAX_BUFFER_SIZE]={0};
UINT8_t RXByteCtr = 0;
UINT8_t接收索引=0;
UINT8_t传输缓冲器[MAX_BUFFER_SIZE]={0};
UINT8_t TXByteCtr = 0;
UINT8_t传输索引=0;

/* I2C写入和读取功能*/

/*对于带有dev_addr的从属设备,写入在*reg_data中指定的数据
*
* dev_addr:从属设备地址。
*示例:Slaver_ADDR
* reg_addr:发送到从属设备的寄存器或命令。
*示例:cmd_type_0_master
**REG_DATA:要写入的缓冲区
*示例:MasterType0
* count:*reg_data的长度
*示例:type_0_length
***/
I2C_Mode I2C_Master_WriteReg (uint8_t dev_addr,uint8_t reg_addr,uint8_t *reg_data,uint8_t count);

/*对于带有dev_addr的从属设备,读取从属设备reg_addr中指定的数据。
*接收的数据在ReceiveBuffer中可用
*
* dev_addr:从属设备地址。
*示例:Slaver_ADDR
* reg_addr:发送到从属设备的寄存器或命令。
*示例:cmd_type_0_slave
* count:要读取的数据长度
*示例:type_0_length
***/
I2C_Mode I2C_Master_ReadReg (uint8_t dev_addr,uint8_t reg_addr,uint8_t count);
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);
void initSensor();

I2C_Mode I2C_Master_ReadReg (uint8_t dev_addr,uint8_t reg_addr,uint8_t count)

/*初始化状态机*/
主模式= TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
RXByteCtr =计数;
TXByteCtr = 0;
ReceiveIndex =0;
TransmitIndex = 0;

/*初始化从属地址并中断*/
UCB0I2CSA = dev_addr;
UCB0IFG &=~(UCTXIFG + UCRXIFG);//清除所有挂起的中断
UCB0IE &=~UCRXIE;//禁用RX中断
UCB0IE |= UCTXIE;//启用TX中断

UCB0CTL1 || UCTR + UCTXSTT;// I2C TX,启动条件

__bis_sr_register(LPM0_bits + GIE);//输入带中断的LPM0
//__bis_sr_register (GIE);
返回主模式;

}


I2C_Mode I2C_Master_WriteReg (uint8_t dev_addr,uint8_t reg_addr,uint8_t *reg_data,uint8_t count)

/*初始化状态机*/
主模式= TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;

//将寄存器数据复制到TransmitBuffer
CopyArray(reg_data, TransmitBuffer, count);

TXByteCtr =计数;
RXByteCtr = 0;
ReceiveIndex =0;
TransmitIndex = 0;

/*初始化从属地址并中断*/
UCB0I2CSA = dev_addr;
UCB0IFG &=~(UCTXIFG + UCRXIFG);//清除所有挂起的中断
UCB0IE &=~UCRXIE;//禁用RX中断
UCB0IE |= UCTXIE;//启用TX中断

UCB0CTL1 || UCTR + UCTXSTT;// I2C TX,启动条件
__bis_sr_register(LPM0_bits + GIE);//输入带中断的LPM0
//__bis_sr_register (GIE);

返回主模式;
}

void CopyArray (uint8_t *source,uint8_t *dest, uint8_t count)

UINT8_t copyIndex = 0;
对于(copyIndex = 0;copyIndex < count;copyIndex++)

Dest[copyIndex]=源[copyIndex];
}
}

//************************************************************************************************
//设备初始化***************************************************************
//************************************************************************************************

void initClockTo16MHz()

UCSCTL3 |= SELREF_2;//设置DCO FLL参考= REFO
UCSCTL4 |=拉美经济体系2;//设置ACLK = REFO
__bis_sr_register(SCG0);//禁用FLL控制回路
UCSCTL0 = 0x0000;//设置可能的最低DCOx,MODx
UCSCTL1 = DCORSEL_5;//选择DCO范围16MHz操作
UCSCTL2 = FLLD_0 + 487;//设置16MHz的DCO乘数
//(N + 1)* FLLRef = Fdco
//(487 + 1)* 3.2768万 = 16MHz
//设置FLL Div = fDCOCLK
__BIC_SR_REGISTER(SCG0);//启用FLL控制回路

//当DCO范围位已存在时,DCO的最坏情况下稳定时间
//更改的是n x 32 x 32 x f_MCLK / f_FLL_reference。 请参阅5xx中的UCS章节
// UG进行优化。
// 32 x 32 x 16 MHz / 3.2768万 Hz = 50万 = MCLK周期,以便DCO稳定下来
__DELAY周期(50万);//
//循环,直到XT1,XT2和DCO故障标志被清除


UCSCTL7 &=~(XT2OFFG + XT1LFOFFG + DCOFFG);//清除XT2,XT1,DCO故障标志
SFRIFG1 &=~OFIFG;//清除故障标志
} While (SFRIFG1&OFIFG);//测试振荡器故障标志
}

UINT16_t setVCoreUp (uint8_t级别){
UINT32_t PMMRIE_BACKUP,SVSMHCTL_BACKUP,SVSMLCTL_BACKUP;

//用于增加Vcore的代码流已被更改以解决问题
//错误FLASH37。
//请参阅勘误表,了解特定设备是否受到影响
//请勿更改此功能

//打开PMM寄存器以进行写入访问
PMMCTL0_H = 0xA5;

//禁用专用中断
//备份所有寄存器
PMMRIE_BACKUP = PMMRIE;
PMMRIE &=~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
SVSLPE | SVMHVLRIE | SVMHIE |
SVSMHDLYIE | SVMLVLRIE | SVMLIE |
SVSMLDLYIE
);
SVSMHCTL_BACKUP = SVSMHCTL;
SVSMLCTL_BACKUP = SVSMLCTL;

//清除标记
PMMIFG = 0;

//将SVM Highside设置为新级别,并检查是否可以增加VCORE
SVSMHCTL = SVMHE | SVSHE |(SVSMHRRL0 *级别);

//等待SVM高端解决
while ((PMMIFG和SVSMHDLYIFG)== 0)


}

//清除标志
PMMIFG &=~SVSMHDLYIFG;

//检查是否可以增加VCORE
IF ((PMMIFG和SVMHIFG)== SVMHIFG)

//-> Vcc对于Vcore增加来说太低
//恢复以前的设置
PMMIFG &=~SVSMHDLYIFG;
SVSMHCTL = SVSMHCTL_BACKUP;

//等待SVM高端解决
while ((PMMIFG和SVSMHDLYIFG)== 0)


}

//清除所有标志
PMMIFG &=~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
SVMLVLRIFG | SVMLIFG |
SVSMLDLYIFG
);

//恢复PMM中断启用寄存器
PMMRIE = PMMRIE_BACKUP;
//锁定PMM寄存器以进行写入访问
PMMCTL0_H = 0x00;
//返回:电压未设置
返回false;
}

//还将SVS高端设置为新级别
//Vcc足够高,可以增加Vcore
SVSMHCTL ||(SVSHRVL0 *级别);

//等待SVM高端解决
while ((PMMIFG和SVSMHDLYIFG)== 0)


}

//清除标志
PMMIFG &=~SVSMHDLYIFG;

//将VCORE设置为新级别
PMMCTL0_L = PMMCOREV0 *级别;

//将SVM,SVS低端设置为新级别
SVSMLCTL = SVMLE |(SVSMLRRL0 *级别)|
SVSLE |(SVSLRVL0 *级别);

//等待SVM,SVS低侧稳定下来
while ((PMMIFG和SVSMLDLYIFG)== 0)


}

//清除标志
PMMIFG &=~SVSMLDLYIFG;
//SVS,SVM核心和高端现在设置为针对新的核心级别进行保护

//恢复低边设置
//清除除级别设置以外的所有其他位
SVSMLCTL &=(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +
SVSMLRRL1 + SVSMLRRL2
);

//清除备份寄存器中的级别设置,保留所有其他位
SVSMLCTL_BACKUP &=
~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);

//恢复低侧SVS监护仪设置
SVSMLCTL || SVSMLCTL_BACKUP;

//恢复高侧设置
//清除除级别设置之外的所有其他位
SVSMHCTL &=(SVSHRVL0 + SVSHRVL1 +
SVSMHRRL0 + SVSMHRRL1 +
SVSMHRRL2
);

//清除备份寄存器中的级别设置,保留所有其他位
SVSMHCTL_BACKUP &=
~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);

//恢复备份
SVSMHCTL || SVSMHCTL_BACKUP;

//等待高侧,低侧稳定下来
while ((((PMMIFG和SVSMLDLYIFG)== 0)&&
((PMMIFG和SVSMHDLYIFG)== 0)))


}

//清除所有标志
PMMIFG &=~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
);

//恢复PMM中断启用寄存器
PMMRIE = PMMRIE_BACKUP;

//锁定PMM寄存器以进行写入访问
PMMCTL0_H = 0x00;

返回true;
}

Bool incaizeVCoreToLevel2()

UINT8_t级别= 2;
UINT8_t活动级别;
布尔状态=真;

//为最大级别设置掩码
级别&= PMMCOREV_3;

//获取实际VCORE
actlevel = PMMCTL0和PMMCOREV_3;

//逐步增加或减少
while ((level!= actlevel)&&(status == true))

IF (LEVEL > actlevel)

状态= setVCoreUp(++actleval);
}
}

返回(状态);
}

void initGPIO ()

// LED
P1OUT = 0x00;// P1 LED设置和重置输出
P1DIR || BIT0;

P4DIR |= BIT7;
P4OUT &=~(BIT7);

//I2C引脚
P3SEL || BIT0 + BIT1;// WFP 3.0 ,1个选项选择

}

void initI2I2()

UCB0CTL1 || UCSWRST;//启用软件重置
UCB0CTL0 = UCMST + UCMODE_3 + UCSNC;// I2C主控,同步模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用SMCLK,保持SW重置
//UCB0BR0 = 160;// fSCL = SMCLK/160 =~100kHz
UCB0BR0 = 40;//fsck = SMCLK/40 =~400kHz
UCB0BR1 = 0;
UCB0I2CSA = SLAVE_ADDR;//从属地址为048h
UCB0CTL1 &=~UCSWRST;//清除软件重置,恢复操作
UCB0IE |= UCNACKIE;
}

//void initSensor()
//{
// I2C_Master_WriteReg (SLAN_ADDR,CMD_PWR_1,MasterAccel,TYPE_0_LENGTH);
//
//}
//************************************************************************************************
//主页****************************************************************
//发送和接收包含示例命令*************的三条消息
//************************************************************************************************

内部主(无效)

WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

initClockTo16MHz();
initGPIO ();
initI2I22();


I2C_Master_WriteReg (SLAN_ADDR,CMD_TYPE_0_MASTER,MasterType0,TYPE_0_LENGTH);

而(1){


//I2C_Master_WriteReg (SLAN_ADDR,CMD_TYPE_1_MASTER,MasterType0,TYPE_0_LENGTH);

//I2C_Master_ReadReg (SLAN_ADDR,CMD_TYPE_1_SLAVE,TYPE_0_LENGTH);
I2C_Master_ReadReg (SLAN_ADDR,CMD_TYPE_1_SLAVE,TYPE_1_Length);
//CopyArray (ReceiveBuffer,SlaveType1,type_0_length);
CopyArray (ReceiveBuffer,SlaveType1,type_1_length);


ACX = SlaveType1[1]<<8|SlaveType1[0];
acy = SlaveType1[3]<<8|SlaveType1[2];
ACZ = SlaveType1[5]<<8|SlaveType1[4];
tmp = SlaveType1[7]<8|SlaveType1[6];
GyX = SlaveType1[9]<<8|SlaveType1[8];
GyY = SlaveType1[11]<<8|SlaveType1[10];
GyZ = SlaveType1[13]<<8|SlaveType1[12];


TEMP = 340.00 36.53 ;
}

__bis_sr_register (LPM0_bits + GIE);
返回0;
}

//************************************************************************************************
// I2C中断***********************************************************************
//************************************************************************************************

#if defined(__TI_Compiler_version__)|| defined(__IAR_SYSTEMS _ICC__)
#pragma vector=USI_B0_vector
__interrupt void USI_B0_ISR(void)
#Elif已定义(__GMNU__)
void __attribute__((interrupt (USI_B0_vector)) USI_B0_ISR (void)
#否则
错误编译器不受支持!
#endif

//必须从UCB0RXBUF读取
UINT8_t Rx_val = 0;

Switch(__偶 数_in_range(UCB0IV,0xC))

案例USI_NONE:break;//矢量0-无中断
案例USI_I2C_UCALIFG:中断;//中断向量:I2C模式:UCALIFG
案例USI_I2C_UCNACKIFG:中断;//中断向量:I2C模式:UCNACKIFG
案例USI_I2C_UCSTIFG:中断;//中断向量:I2C模式:UCSTIFG
案例USI_I2C_UCSTPIFG:中断;//中断向量:I2C模式:UCSTPIFG
案例USI_I2C_UCRXIFG:
RX_val = UCB0RXBUF;
IF (RXByteCtr)

ReceiveBuffer[ReceiveIndex+]= Rx_val;
RXByteCtr --;
}

IF (RXByteCtr == 1)

UCB0CTL1 || UCTXSTP;
}
否则,如果(RXByteCtr == 0)

UCB0IE &=~UCRXIE;
MasterMode = IDE_MODE;
__BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出LPM0
}
中断;//中断向量:I2C模式:UCRXIFG
案例USI_I2C_UCTXIFG:
开关(主模式)

案例TX_REG_ADDRESS_MODE:
UCB0TXBUF = TransmitRegAddr;
IF (RXByteCtr)
MasterMode = switch_to_RX_mode;//现在需要开始接收
否则
MasterMode = TX_DATA_mode;//继续传输数据至传输缓冲区
中断;

CASE SWITCH_to_RX_MODE (案例切换至RX_模式):
UCB0IE |= UCRXIE;//启用RX中断
UCB0IE &=~UCTXIE;//禁用TX中断
UCB0CTL1 &=~UCTR;//切换至接收器
MasterMode = RX_DATA_mode;//状态是接收数据
UCB0CTL1 || UCTXSTT;//发送重复启动
IF (RXByteCtr == 1)

//必须发送stop,因为这是N-1字节
while ((UCB0CTL1和UCTXSTT));
UCB0CTL1 || UCTXSTP;//发送停止条件
}
中断;

案例TX_DATA_MODE:
IF (TXByteCtr)

UCB0TXBUF = TransmitBuffer[TransmitIndex+];
TXByteCtr
}
否则

//完成传输
UCB0CTL1 || UCTXSTP;//发送停止条件
MasterMode = IDE_MODE;
UCB0IE &=~UCTXIE;//禁用TX中断
__BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出LPM0
}
中断;

默认:
__no_operation();
中断;
}
中断;//中断向量:I2C模式:UCTXIFG
默认值:中断;
}
}

 

 

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

    您好,

    您是否使用上拉电阻器(例如 4.7kOhm)? 我建议参考 MSP430TmMCU 应用报告中常见eUSCI和USCI串行通信问题解决方案中的常见I2C通信问题部分。

    此外,我看到此线程与下面的线程相关。

    此致,

    詹姆斯

    MSP客户应用程序

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

    通过查看原理图,我发现GY-521 ALR 具有4.7K的内部上拉电阻。 我浏览了代码, 不知道代码有什么问题,应该可以用,有人能给我建议代码有什么问题吗?

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

    我建议从我们的I2C代码示例开始,然后以增量方式添加您的代码。 您是否通读了上面链接的申请报告?

    此致,

    詹姆斯

    MSP客户应用程序