工具/软件: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
默认值:中断;
}
}