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/MSP430FR2355:MSP430FR2355 I2C 我尝试发送单个字节、然后期望从器件进行响应。 I2C 发送字节一次、第二次迭代仅发送地址

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/925042/ccs-msp430fr2355-msp430fr2355-i2c-i-try-to-tx-a-single-byte-then-expect-the-slave-to-respond-the-i2c-tx-the-byte-once-on-the-second-iteration-only-the-address-it-sent

器件型号:MSP430FR2355

工具/软件:Code Composer Studio

MSP430FR2355

Code Composer Studio
 版本:8.3.1.00004

从器件:MPU6050 (Accel / Gyro)模块

我可以顺利启动 MPU6050。

但是、当我开始数据收集(TX 和 RX 部分)时、它应该会看到  

主器件:I2C 作为 TX

TX 地址+代码+重新启动或停止 (0x68 + 0x3B + S)

主器件:I2C 作为 RX

TX 地址、然后是 NACK。  (0x68 || 数据字节 || NACK)则主器件期望通过 NACK 进行确认以结束传输

这应该重复;

我得到的是

TX 地址+停止 (0x68 + S)

RX 地址|| 0x00 + 0x00 || NACK

逻辑分析仪中的以下示例

真的不知道为什么会发生这种情况、为什么主器件 MSP430FR2355仅发送地址而不是数据?

尝试在不同位置设置延迟、   尝试当前设置为/8的不同时钟速度  (尝试从/2到/20不幸运)

这是示波器跟踪黄色是数据线蓝色是 P3 BIT4 (我放置一个 P3位4以在中断例程中变为高电平和低电平、它在 I2C 协议的地址部分捕获此干扰

主设备


#include 
#include "stdint.h"



/**
* MPU-6050 I2C = 0x68
*

**/

void I2C_BUSY (void);
void 延迟(void);

const unsigned int MPU_address = 0x68;// MPU-6050 i2c 地址

const unsigned int Accel_XOUT_H = 0x003B;
const unsigned
int Accel_L = 0x003C_int 执行;unsigned int Accel = 0x003C_int Accel;unsigned int Accel
= 0x003c
const unsigned int Accel_Zout_H = 0x003F;
const unsigned int Accel_Zout_L = 0x0040;

const unsigned int Gyro_XOUT_H = 0x0043;
const unsigned int Gyro_XOUT_L = 0x0044;
const unsigned int Gyro_Conout_H = 0x0045;
const unsigned

int Gyro_ZOUT_L = 0x0046;unsigned int Gyout_L = 0x0047;unsigned g_g_gyout_L

unsigned int RXData = 0;
unsigned int TXByteCtr = 0;
unsigned int SlaveFlag = 0;
unsigned int RXcnt = 0;
volatile unsigned int
stop = 0;
volatile unsigned int read = 0;

signed int TXData[]={0x6B、0x00、0x1A、0x04、0x1B、 0x00、0x1C、0x00};
unsigned int RX[4];
unsigned int RX1[0x0100];
unsigned int RX1cnt = 0;
signed int x_acc = 0;
signed int y_acc = 0;
signed int z_acc = 0;
signed int x_gyr =
0;signed
int z_gyr = 0;
unsigned int valid = 0;
signed int acc_led = 0;


int main (void)
{
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

P1SEL0 |= BIT2 | BIT3; // I2C 引脚
P5DIR |= BIT0 | BIT1 | BIT2 | BIT3 | BIT4;//步进驱动器0=DIR、1=步进、3-4-5步进值
P5OUT = 0x00;
P3DIR = 0xFF;
P3OUT = 0x00;
//禁用 GPIO 上电默认高阻抗模式以激活
//先前配置的端口设置
PM5CTL0 &=~LOCKLPM5;

//将 USCI_B0配置为 I2C 模式
UCB0CTLW0 |= UCSWRST; //软件复位被启用
UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;// I2C 模式、主控模式、同步
UCB0CTLW1 |= UCASTP_0; //未生成自动停止
//到达 UCB0TBCNT 后
UCB0BRW = 0x0008; //波特率= SMCLK /8 ------ 32岁以上
UCB0TBCNT = 0x0000; //禁用字节 cntr
UCB0I2CSA = MPU_ADDRESS; // MPU-6050的从器件地址
UCB0CTL1 &=~UCSWRST;
UCB0IE |= UCRXIE | UCTXIE0 | UCNACKIE | UCTXSTP;// EN INT TX、RX、NACK

__bis_SR_register (GIE); //启用中断

while (UCB0CTLW0 & UCTXSTP); //确保停止条件已发送
I2C_BUSY ();

TX_CNTR = 0x00;
TXByteCtr = 0x02;
UCB0CTLW0 |= UCTR | UCTXSTT; // TX 0x6B 0x00
I2C_BUSY ();

TXByteCtr = 0x02;
UCB0CTLW0 |= UCTR | UCTXSTT; // TX 0x1A 0x00
I2C_BUSY ();

TXByteCtr = 0x02;
UCB0CTLW0 |= UCTR | UCTXSTT; // TX 0x1B 0x00
I2C_BUSY ();

TXByteCtr = 0x02;
UCB0CTLW0 |= UCTR | UCTXSTT; // TX 0x1C 0x00
I2C_BUSY ();
//
* MPU6050初始化完成
*/

TX_CNTr = 0x0000;
TXData[0]= 0x3B;
TXData[1]= 0x3C;
TXData[2]= 0x3D;
TXData[3]= 0x3E;
TXData[4]= 0x3F;
TXData[5]= 0x40;

TXData[6]= 0x00;
TXData[7]= 0x00;
RXcnt = 0x00;

// RX 数据
//主|S|AD+W||RA||S|AD+R|||ack|
//从设备 |ack||ack|||ack|Data||
while (UCB0CTLW0和 UCTXSTP); //确保发送了停止条件
I2C_BUSY();

while (1)
{
P3OUT = 0x00;
TX_CNTr = 0x00;
TXByteCtr = 0x01;
// UCB0CTLW0 |= UCSWRST; //软件复位被启用
UCB0CTLW0 |= UCTR; // INTx 模式
UCB0CTLW1 |= UCASTP0;
// UCB0TBCNT = 0x03;// TX 2字节
// UCB0CTLW0 &=~UCSWRST; //软件复位被启用
UCB0CTLW0 |= UCTXSTT; // I2C 启动条件
I2C_BUSY();
P3OUT |= BIT0;


// UCB0CTLW0 |= UCSWRST; //软件复位被启用
UCB0CTLW0 &=~UCTR; //接收模式
UCB0CTLW1 |= UCASTP1;
UCB0TBCNT = 0x01;// Rx 1字节
// UCB0CTLW0 &=~UCSWRST; //软件复位被启用

UCB0CTLW0 |= UCTXSTT; // I2C 启动条件 INTx 模式
I2C_BUSY();
while (read)_no_operation ();
P3OUT |= BIT1;
if (有效)
{
RX1[RX1cnt+]= x_ACC;
if (RX1cnt > 0x00FF) RX1cnt = 0x0000;
ACC_LED = x_ACC >>8;
// P3OUT = ACC_LEed;//希望实时查看结果

if (acc_led > 128)
{
P5OUT |= BIT0;
P5OUT |= BIT1;
delay();//步进电机延迟脉冲太快
P5OUT &= BIT1;
delay();//步进电机延迟脉冲太快
}
如果(z_gyr <-128)则为其他值
{
P5OUT &=~BIT0;
P5OUT |= BIT1;
delay();//步进电机延迟脉冲太快
P5OUT &= BIT1;
delay();//步进电机延迟脉冲太快
}
P3OUT |= BIT2;
}
}


void I2C_BUSY (void)
{
unsigned int wait;
while (UCB0STATW 和 UCBBUSY)
{
for (Wait = 0xFFFF;wait = 0;wait--)_no_operation ();
}


}

void delay (void)
{
unsigned int ***;
for (STEPER_PULSE_DELAY = 0xFFFF;STEPER_PULSE_DELAY = 0;STEPER_PULSE_DELAY--)__NO_OPERATION ();
}



#pragma vector = USCI_B0_Vector
__INTERRUPT void USCIB0_ISR (void)
{

volatile unsigned int I2C_int;
I2C_int = UCB0IV;

if (I2C_int =UCIV__UCTXIFG0)// TX 缓冲区为空
{
IF (TXByteCtr) //检查 TX 字节计数器
{
P3OUT |= BIT4;
TXByteCtr --;
UCB0TXBUF = TXData[TX_CNTR]; //加载 TX 缓冲区
TX_CNTR++;
STOP = 0x01; //测量 TX 字节计数器
P3OUT &=~BIT4;
}
其他
{
STOP = 0x00;
UCB0CTLW0 |= UCTXSTP; // I2C 停止条件
}

}
否则、如果(I2C_int = UCIV_UCRXIFG0)// RX 数据存在
{
UCB0CTLW0 |= UCTXSTP;
RXData = UCB0RXBUF;
RX[RXcnT]= RXData;
RXcnt++;
if (RXcnt > 0x0001)
{
RXcnt = 0;
X_ACC = RX[1]|(RX[0]<<8);
有效= 0x0001;
}
有效= 0x0001;
读取= 0x0000;
P3OUT |= BIT5;
}
否则、如果(I2C_int = UCIV_UCNACKIFG)//接收到 NACK
{
STOP = 0x00;
读取= 0x0000;
UCB0CTLW0 |= UCTXSTP; // I2C 停止条件
}
否则,如果(I2C_int =UCIV_UCSTPIFG)//停止接收
{
停止= 0x00;
}
} 

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

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    由于序列会一直重复、因此我不确定我们要查看的是哪种事务。 但我猜这不是第一个。
    >            UCB0CTLW1 |= UCASTP0;
    [...]
    >            UCB0CTLW1 |= UCASTP1;
    在第一个循环之后、这些结果会导致"保留"的 UCASTP=3。 我不知道该设置的实际作用是什么、但如果它的行为与 UCASTP=2类似、它会在 SLA (地址)字节后发出停止、因为 UCB0TBCNT=0、这就是您看到的情况。 当 UCSWRST 被置位时、只能置位 UCB0TBCNT、所以在整个程序中它=0。
    如果您尝试使用 UCASTP=2进行读取:
    1) 1)在 UCB0TBCNT 设置周围设置和清除 UCSWRST
    2) 2)预清零 UCASTP、类似于:
    >            UCB0CTLW1 = (UCB0CTLW1 & ~UCASTP) | UCASTP_2;
     
    Unsolicited:
        UCB0IE |= UCRXIE | UCTXIE0 | UCNACKIE | UCTXSTP;  // EN INT TX, RX, NACK
    这将启用 UCSTTIE。 我怀疑您的意思是:
    >    UCB0IE |= UCRXIE | UCTXIE0 | UCNACKIE | UCSTPIE;  // EN INT TX, RX, NACK
     
    [编辑:少量澄清]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Bruce McKenney47378您好

    有关自动停止生成的好收获

     

    已添加

    UCB0CTLW1 &= ~UCASTP1;  // clear auto stop

    UCB0CTLW1 |= UCASTP0;

    此外:

    interrupt: UCSTPIE

    谢谢、我不再拔出头发