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.

[参考译文] MSP 和 AD5933之间的 I2C 通信

Guru**** 2482225 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1240117/i2c-communication-between-msp-and-ad5933

大家好!
我希望在 MSP432和 AD5933之间建立 I2C 通信、以进行 AD5933级别的读写操作。 MSP432是主器件、AD5933是外频器件。 我写了我的代码与 你分享,但没有发生任何。 我不知道问题在哪里、因为我没有示波器。 可以帮帮我。

#include <msp432p401r.h>
#include <stdint.h>
#include <stdio.h>

#define SLAVE_ADDRESS 0x0D

#define PCMKEY_value 0x695A0000
#define CS_KEY_value 0x0000695A


#define CTRL_1                  0x81       // Registre control 1
uint8_t RXData;

// Delay function
void delay(int n)
{
    int i, j;
    for (j = 0; j < n; j++)
        for (i = 0; i < 1000; i++);
}

void DCO_clock(int clock_speed) {
    CS->KEY = CS_KEY_value;
    switch (clock_speed) {
        case 0: {
            CS->CTL0 = CS_CTL0_DCORSEL_0; // 1.5MHz
            break;
        }
        case 1: {
            CS->CTL0 = CS_CTL0_DCORSEL_1; // 3MHz
            break;
        }
        case 2: {
            CS->CTL0 = CS_CTL0_DCORSEL_2; // 6MHz
            break;
        }
        case 3: {
            CS->CTL0 = CS_CTL0_DCORSEL_3; // 12MHz
            break;
        }
        case 4: {
            CS->CTL0 = CS_CTL0_DCORSEL_4; // 24MHz
            break;
        }
        case 5: {
            PCM->CTL0 = PCMKEY_value + PCM_CTL0_AMR_1; // LDO_Vcore1 choice
            while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY) != 0);
            PCM->CTL0 = PCMKEY_value + PCM_CTL0_AMR_5; // DCDC_Vcore1 choice
            while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY) != 0);
            FLCTL->BANK0_RDCTL = FLCTL_BANK0_RDCTL_WAIT_3; // wait state = 3 for read in RAM bank0
            FLCTL->BANK1_RDCTL = FLCTL_BANK1_RDCTL_WAIT_3; // wait state = 3 for read in RAM bank1
            CS->CTL0 = CS_CTL0_DCORSEL_5; // 48MHz
            break;
        }
    }
    CS->KEY = 0;
}

void clock(void) {
    CS->KEY = CS_KEY_value;
    CS->CTL1 = CS_CTL1_SELA_3 + CS_CTL1_SELS_3 + CS_CTL1_SELM_3;
    CS->KEY = 0;
}

void I2C_Init(void)
{
  UCB0CTLW0 |= UCSWRST;                  //reset the l'I2C for modification registers
  P1->SEL0 |= BIT6 + BIT7;    //SDA = P1.6 et SCL = P1.7
  P1->SEL1 &= ~(BIT6 + BIT7);
  P1->REN |= BIT6 | BIT7;  // Activation of internal pull-up resistors
  P1->OUT |= BIT6 | BIT7;  // Configuration of pull-up resistors
  EUSCI_B0->CTLW0 = UCMST + UCMODE_3 + UCSYNC + UCSSEL_2 + UCSWRST; //I2C type communication in master mode + synchro, SMCLK, and maintained reset
  EUSCI_B0->CTLW0 = 30;                         //fSCL = SMCLK/30 = 100kHz
  EUSCI_B0->CTLW0 &= ~UCSWRST;                 //fonctionnement normal
  EUSCI_B0->IE |= UCRXIE | UCNACKIE | UCBCNTIE;

}
/*
 * FUNCTION THAT MANAGES INTERRUPTIONS
 *
 * The interest of this function is to process the different sources of interruptions that can occur during I2C operations, such as:

UCNACKIFG: This flag is set when the I2C module receives a NACK (Not Acknowledge) during a data transmission. In the corrected code, it is used to reset the UCNACKIFG flag, enable sleep-on-exit mode (SCB_SCR_SLEEPONEXIT), and restart transmission by setting the UCTXSTT bit to 1.

UCRXIFG0: This flag is set when data is successfully received by the I2C module. In the corrected code, it is used to reset the UCRXIFG0 flag, disable sleep-on-exit mode (SCB_SCR_SLEEPONEXIT), and store received data in the RXData variable.

UCBCNTIFG: This flag is set when the number of bytes expected during an I2C operation is reached. In the corrected code, it is used to reset the UCBCNTIFG flag, enable sleep-on-output mode (SCB_SCR_SLEEPONEXIT), and invert the state of pin P1.0 (P1OUT ^= BIT0).
 */
void EUSCIB0_IRQHandler(void)
{
    if (UCB0IFG & UCNACKIFG)
    {
        UCB0IFG &= ~UCNACKIFG;
        SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
        UCB0CTLW0 |= UCTXSTT;
    }

    if (UCB0IFG & UCRXIFG0)
    {
        UCB0IFG &= ~UCRXIFG0;
        SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
        RXData = UCB0RXBUF;
    }

    if (UCB0IFG & UCBCNTIFG)
    {
        UCB0IFG &= ~UCBCNTIFG;
        SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
        P1OUT ^= BIT0;
    }
}


/*
 * Writing a byte (Write Byte/Command Byte):

1.The master device sends a start condition (START) on SDA.
2.The master sends the 7-bit slave address followed by the write bit (0).
3. The addressed slave device sends an ACK on SDA.
4.The master sends a register address.
5.The slave sends an ACK on SDA.
6.The master sends a data byte.
7.The slave sends an ACK on SDA.
8.The master sends an end condition (STOP) on SDA to terminate the transaction.
 */
// Function to write a byte in an AD5933 register via the I2C interface

void I2C_writeRegister(uint8_t reg, int data)
{
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TR;   // Transmission
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;    // Start signal generation
    while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0));   // Waiting for start signal to be sent
    EUSCI_B0->I2CSA = SLAVE_ADDRESS; // Send AD5933 address
    while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // Waiting for start signal to be sent
    EUSCI_B0->TXBUF = reg;    // Send register address
    while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // Waiting for register address to be sent
    EUSCI_B0->TXBUF = data; // Sending data
    while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // Waiting for data to be sent
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;    // Waiting for data to be sent
    while (EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTP); // Waiting for the end of the transmission
    // Handwriting verification
    if (EUSCI_B0->IFG & EUSCI_B_IFG_NACKIFG)
    {
        // Failed to write
        // Handle the error accordingly
        printf("Write failed");
    }
    else
    {
        // The write was successful
        printf("Number %u write operation completed successfully", data);
    }
}

/*
  * Reading a byte (Receive Byte):

1.The master device sends a start condition (START) on SDA.
2.The master sends the 7-bit slave address followed by the read bit (1).
3. The addressed slave device sends an ACK on SDA.
4.The master receives a data byte.
5.The master sends a NO ACK on SDA (the slave must verify that the master has received the data).
6.The master sends an end condition (STOP) on SDA and the transaction ends.
  */


// Function to read a register from the AD5933 via the I2C interface


// Function to write a byte in an AD5933 register via the I2C interface


uint8_t I2C_readRegister(uint8_t reg)
{
    uint8_t AD5933_address = (SLAVE_ADDRESS << 1) | 0x01; // Combination of slave address and read bit

    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TR;   // Transmission
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;    // // Generate the start signal
    EUSCI_B0->I2CSA = AD5933_address; // Send the address of the register to write
    while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0));  // Wait for start signal to be sent
    EUSCI_B0->TXBUF = reg; // // Send register address
    while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // // Wait for register address to be sent
    EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_TR;  // Reception
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;    // // Generate a repetition of the start signal
    while (EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTT); // Wait for the end of the start signal repetition
    EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;    // Generation of the stop signal
    while (!(EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG0)); // // Wait for the reception of the data
    // Verification of the reading
    if (EUSCI_B0->IFG & EUSCI_B_IFG_NACKIFG)
    {
        // Failed to read
        printf("Failed to read register %u", reg);
    }
    else
    {
        // The write was successful
        printf("%u register read operation completed successfully", reg);
    }
    RXData = EUSCI_B0->RXBUF;      // Lecture de la donnée reçue
    return RXData;
}

/**
 * main.c
 */
void main(void)
{
    WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;     // stop watchdog timer
    clock();
    DCO_clock(1);
    I2C_Init();
    // Exemple d'écriture et de lecture d'un registre de l'AD5933
    delay(100);                     // Délai de stabilisation de l'AD5933
    I2C_writeRegister(CTRL_1, 2); // Écriture dans le registre de contrôle 1
    uint8_t data = I2C_readRegister(CTRL_1); // Lecture du registre de contrôle 1
    printf("Data read from register: %u\n", data);

}


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

    一方面、您可能需要使延迟变量具有易失性、这样它们就不会被优化掉。

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

    > EUSCI_B0->IE |= UCRXIE | UCNACKIE | UCBCNTIE;

    您的读取/写入寄存器函数不需要中断、因此在此处启用它们将进行干扰。 我建议删除此行。

    ----------------

    > EUSCI_B0->I2CSA = SLAVE_ADDRESS;//发送 AD5933地址

    这必须在设置 TXSTT 前完成。 您应该将该行上移几行。 (ReadRegister 也是如此。)

    ----------------

    > uint8_t AD5933_address =(slave_address << 1)| 0x01;//从器件地址和读取位的组合

    I2CSA 寄存器不包括 R/W 位(这是由基于 TR 位的 EUSCI 插入的)。 请尝试改用:

    > uint8_t AD5933_address = slave_address;//从器件地址  

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

    早上好!
    我已考虑到您的建议。 我在设置 TXSTT 之前使 delay 函数变量变为易失性、删除了 I2C_Init ()函数中的中断、偏移行 EUSCI_B0->I2CSA=slave_address、并在 I2C_readRegister ()函数中更改了 uint8_t AD5933_address=slave_address。
    但我仍然没有得到答案。 不显示任何内容

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

    我之前错过了:

    > EUSCI_B0->CTLW0 = 30;//fSCL = SMCLK/30 = 100kHz

    这应该是

    > EUSCI_B0->BRW = 30;//fSCL = SMCLK/30 = 100kHz

    ----------------

    如果您在调试器中暂停程序、(1)要在哪里执行? (2) UCB0STATW 和 UCB0IFG 的值是什么?

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

    如果您有两个 LaunchPad、则可以使用 Resource Explorer 中的示例代码来验证您是否可以在具有已知良好软件的电路板之间实现 IIC 通信。 然后您可以对其进行修改、使其适用于您的芯片。

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

    我设法沟通、但仍然有问题。 当我在 CTRL_1寄存器(0x81)中写入1时、在寄存器中读取时、我得到的值为255。 终端显示的内容如下:

    [Cortex_M4_0]寄存器129中的第1个写入操作成功完成
    129寄存器读取操作成功完成
    从寄存器129读取的数据为:255

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

    AD5933没有响应。 255是你得到的,因为上拉。

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

    请您对此有任何解决方案

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

    您挑选了我见过的最复杂的 I2C 芯片之一。

    我认为您将需要一个示波器。

    该芯片甚至没有错误标志、您可以通过监测来独立确认通信。

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

    Keith 的评论是:查看数据表(修订版 F)的表16以及图33和31、发现按照通常的"先写寄存器号、然后读"序列、似乎无法读取寄存器。 相反、您需要发送命令代码来设置寄存器编号("地址指针")。

    我想您可以将序列[图31]想象成使用所需的寄存器编号(0x81)写入寄存器0xB0 [请参阅表16]。 之后您可以读取[参考图33]。

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

    感谢您的回答、但您的意思是地址指针只用于写入

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

    我建议您阅读从数据表第28页开始的"写入/读取 AD5933"。 正如 Keith 指出的那样、该方法与其他器件有些不同。

    写入字节不需要设置地址指针[请参阅图30]、但读取字节和块读取/写入需要设置地址指针。 如果你只想写/读字节,所需的代码更改(在 readRegister 中)是相当小的--只是开始发送{0xB0, reg}而不是仅仅是{reg}(之后你可能还需要做一个 Stop )。 是否要执行块读取/写入? [写入0x81不能通过块写入来完成。]

    未经请求:看起来您正在尝试将0x02写入寄存器0x81、但根据表11、位 D1已"保留"。

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

    "我知道你在胡说什么。" 我设法写入寄存器0x81、并使用地址指针读取相同的值。 现在我的问题是、我写入寄存器0x82、0x83和0x84 (频率启动寄存器)。 对于这三个寄存器、当我读取时、我不会获得相同的值。 这是频率启动寄存器的功能。 我在终端处得到以下输出  

    (我必须使 w = 0!
    Y=125!
    Z = 2!° 
    #include <math.h>
    
    // Les registres de la fréquence de démarrage. C'est un registre lecture-écriture de 3 bites
    #define FREQ_0   (0x82)
    #define FREQ_1    (0x83)
    #define FREQ_2    (0x84)
    
    #define MCLK 16776000.0 // Source d'horloge interne de l'AD5933. Elle est de 16.776 MHz
    
    int reussit;
    
    
    // Function to read a pointer register from the AD5933 via the I2C interface
    
    uint8_t I2C_readRegister(uint8_t reg)
    {
        //uint8_t AD5933_address = (SLAVE_ADDRESS << 1) | 0x01; // Combination of slave address and read bit
    
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TR;   // Transmission
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;    // // Generate the start signal
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // Waiting for register address to be sent
        EUSCI_B0->TXBUF = Adress_pointer;    // Send register address
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0));  // Wait for start signal to be sent
        EUSCI_B0->TXBUF = reg; // // Send register address
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // // Wait for register address to be sent
        EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_TR;  // Reception
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;    // // Generate a repetition of the start signal
        while (EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTT); // Wait for the end of the start signal repetition
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;    // Generation of the stop signal
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG0)); // // Wait for the reception of the data
        // Verification of the reading
        if (EUSCI_B0->IFG & EUSCI_B_IFG_NACKIFG)
        {
            // Failed to read
            printf("Failed to read register %u\n", reg);
        }
        else
        {
            // The write was successful
            printf("%u register read operation completed successfully\n", reg);
        }
        RXData = EUSCI_B0->RXBUF;      // Lecture de la donnée reçue
        return RXData;
    }
    
    int Start_Frequency(unsigned long x) {
        // Check that MCLK is not zero to avoid a division by zero
        if (MCLK == 0) {
            printf("Error: MCLK sucks\n");
            return -1;
        }
    
        // Check that the value of x is valid
        if (x <= 0) {
            printf("Error: The value of x is invalid\n");
            return -1;
        }
    
        // Calculate the start frequency
        long freq = (x / (MCLK / 4.0)) * pow(2, 27);
    
        // Extract the bytes from the frequency
        uint8_t freq_high = 0;
        uint8_t freq_mid = 0;
        uint8_t freq_low = 0;
    
        freq_high = (uint8_t)((freq >> 16) & 0xFF);
        freq_mid = (uint8_t)((freq >> 8) & 0xFF);
        freq_low = (uint8_t)(freq & 0xFF);
    
        // Write the data in the concerned registers
        I2C_writeRegister(FREQ_0, 0);
        I2C_writeRegister(FREQ_1, 125);
        I2C_writeRegister(FREQ_2, 2);
    
      // Checking for write success
        reussit = (I2C_readRegister(FREQ_0) == freq_high) &&
                  (I2C_readRegister(FREQ_1) == freq_mid) &&
                  (I2C_readRegister(FREQ_2) == freq_low);
        // Read again in the frequency registers
        uint8_t w = I2C_readRegister(FREQ_0);
        uint8_t y = I2C_readRegister(FREQ_1);
        uint8_t z = I2C_readRegister(FREQ_2);
        delay(100);
        printf("freq_high = %u !\n", freq_high);
        printf("freq_mid = %u !\n", freq_mid);
        printf("freq_low = %u !\n", freq_low);
        delay(100);
        printf("w = %u !\n", x);
        printf("y = %u !\n", y);
        printf("z = %u !\n", z);
    
        printf("The start frequency has been set with %s !\n", reussit ? "succès" : "échec");
    
        return reussit ? 0 : -1;
    }
    
    
    /**
     * main.c
     */
    void main(void)
    {
        WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;     // stop watchdog timer
        clock();
        DCO_clock(5);
        delay(100);
        I2C_Init();
        delay(100);
    
        // Exemple d'écriture et de lecture d'un registre de l'AD5933
    
        I2C_writeRegister(CTRL_1, 2); // Écriture dans le registre de contrôle 1
        delay(100);
       // I2C_write_Adress_Pointer(CTRL_1);
        uint8_t data = I2C_readRegister(CTRL_1); // Lecture du registre de contrôle 1
        printf("Data read from register %u is: %u\n", CTRL_1, data);
        delay(1000);
        Start_Frequency(1000);
    
    }
    
    
    

    [Cortex_M4_0]寄存器129中的第2个数字写入操作成功完成
    129寄存器读取操作成功完成
    从寄存器129读取的数据为:2
    寄存器130中的数字0写入操作成功完成
    寄存器131中的第125次写入操作成功完成
    寄存器132中的第二个写入操作成功完成
    130寄存器读取操作成功完成
    130寄存器读取操作成功完成
    131寄存器读取操作成功完成
    132寄存器读取操作成功完成
    FREQ_HIGH = 0!
    FREQ_MID = 125!
    FREQ_LOW = 2!
    W = 1000!
    Y=243!
    Z = 249!
    开始频率已设置为电子检查!

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

    [我在这里应该提到的是,我对这个设备没有任何经验-我甚至不知道它做什么。]

    但这看起来可疑、因为 w 是 uint8_t:

    w = 1000!

    我建议您替换:  

    > printf ("w =%u!\n"、x);

    实现

    > printf ("w =%u!\n"、(unsigned) w);

    [编辑:固定变量引用。]

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

    此外、图31显示了地址指针设置之后的停止条件、而不是重复启动条件。 这可能是必需的。

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

    此时、由于 MSP430工作正常、您可能需要切换到 AD 论坛、该论坛中应该有更了解此芯片的人。

    社区|模拟器件

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

    大家好!
    对于这个问题、

    #include <msp432p401r.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <math.h>
    
    #define SLAVE_ADDRESS 0x0D
    #define Adress_pointer 0xB0
    
    #define PCMKEY_value 0x695A0000
    #define CS_KEY_value 0x0000695A
    
    #define MCLK 16776000.0 // Source d'horloge interne de l'AD5933. Elle est de 16.776 MHz
    
    
    uint8_t RXData;
    
    // Delay function
    void delay(int n)
    {
        volatile int i, j;
        for (j = 0; j < n; j++)
            for (i = 0; i < 1000; i++);
    }
    
    void DCO_clock(int clock_speed) {
        CS->KEY = CS_KEY_value;
        switch (clock_speed) {
            case 0: {
                CS->CTL0 = CS_CTL0_DCORSEL_0; // 1.5MHz
                break;
            }
            case 1: {
                CS->CTL0 = CS_CTL0_DCORSEL_1; // 3MHz
                break;
            }
            case 2: {
                CS->CTL0 = CS_CTL0_DCORSEL_2; // 6MHz
                break;
            }
            case 3: {
                CS->CTL0 = CS_CTL0_DCORSEL_3; // 12MHz
                break;
            }
            case 4: {
                CS->CTL0 = CS_CTL0_DCORSEL_4; // 24MHz
                break;
            }
            case 5: {
                PCM->CTL0 = PCMKEY_value + PCM_CTL0_AMR_1; // LDO_Vcore1 choice
                while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY) != 0);
                PCM->CTL0 = PCMKEY_value + PCM_CTL0_AMR_5; // DCDC_Vcore1 choice
                while ((PCM->CTL1 & PCM_CTL1_PMR_BUSY) != 0);
                FLCTL->BANK0_RDCTL = FLCTL_BANK0_RDCTL_WAIT_3; // wait state = 3 for read in RAM bank0
                FLCTL->BANK1_RDCTL = FLCTL_BANK1_RDCTL_WAIT_3; // wait state = 3 for read in RAM bank1
                CS->CTL0 = CS_CTL0_DCORSEL_5; // 48MHz
                break;
            }
        }
        CS->KEY = 0;
    }
    
    void clock(void) {
        CS->KEY = CS_KEY_value;
        CS->CTL1 = CS_CTL1_SELA_3 + CS_CTL1_SELS_3 + CS_CTL1_SELM_3;
        CS->KEY = 0;
    }
    
    void I2C_Init(void)
    {
      UCB0CTLW0 |= UCSWRST;                  //reset the l'I2C for modification registers
      P1->SEL0 |= BIT6 + BIT7;    //SDA = P1.6 et SCL = P1.7
      P1->SEL1 &= ~(BIT6 + BIT7);
      P1->REN |= BIT6 | BIT7;  // Activation of internal pull-up resistors
      P1->OUT |= BIT6 | BIT7;  // Configuration of pull-up resistors
      //EUSCI_B0->CTLW0 = UCMST + UCMODE_3 + UCSYNC + UCSSEL_2 + UCSWRST; //I2C type communication in master mode + synchro, SMCLK, and maintained reset
      EUSCI_B0->CTLW0 = EUSCI_A_CTLW0_SWRST |
                        EUSCI_B_CTLW0_MODE_3|
                        EUSCI_B_CTLW0_MST   |
                        EUSCI_B_CTLW0_SYNC  |
                        EUSCI_B_CTLW0_SSEL__SMCLK;
      EUSCI_B0->BRW = 30; //fSCL = SMCLK/30 = 100kHz
      EUSCI_B0->I2CSA = SLAVE_ADDRESS; // Send AD5933 address
      EUSCI_B0->CTLW0 &= ~UCSWRST;                 //fonctionnement normal
      //EUSCI_B0->IE |= UCRXIE | UCNACKIE | UCBCNTIE;
    
    }
    
    /*
     * FUNCTION THAT MANAGES INTERRUPTIONS
     *
     * The interest of this function is to process the different sources of interruptions that can occur during I2C operations, such as:
    
    UCNACKIFG: This flag is set when the I2C module receives a NACK (Not Acknowledge) during a data transmission. In the corrected code, it is used to reset the UCNACKIFG flag, enable sleep-on-exit mode (SCB_SCR_SLEEPONEXIT), and restart transmission by setting the UCTXSTT bit to 1.
    
    UCRXIFG0: This flag is set when data is successfully received by the I2C module. In the corrected code, it is used to reset the UCRXIFG0 flag, disable sleep-on-exit mode (SCB_SCR_SLEEPONEXIT), and store received data in the RXData variable.
    
    UCBCNTIFG: This flag is set when the number of bytes expected during an I2C operation is reached. In the corrected code, it is used to reset the UCBCNTIFG flag, enable sleep-on-output mode (SCB_SCR_SLEEPONEXIT), and invert the state of pin P1.0 (P1OUT ^= BIT0).
     */
    void EUSCIB0_IRQHandler(void)
    {
        if (UCB0IFG & UCNACKIFG)
        {
            UCB0IFG &= ~UCNACKIFG;
            SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
            UCB0CTLW0 |= UCTXSTT;
        }
    
        if (UCB0IFG & UCRXIFG0)
        {
            UCB0IFG &= ~UCRXIFG0;
            SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
            RXData = UCB0RXBUF;
        }
    
        if (UCB0IFG & UCBCNTIFG)
        {
            UCB0IFG &= ~UCBCNTIFG;
            SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
            P1OUT ^= BIT0;
        }
    }
    
    /*
     * BLOCK WRITE 
    In this operation, the master device writes a block of data to a slave device (see Figure 32). The start address
     for a block write must previously have been set. In the case of the AD5933 this is done by setting a pointer to 
     set the register address. 
    1. The master device asserts a start condition on SDA. 
    2. The master sends the 7-bit slave address followed by the write bit (low). 
    3. The addressed slave device asserts an acknowledge on SDA. 
    4. The master sends an 8-bit command code (1010 0000) that tells the slave device to expect a block write. 
    5. The slave asserts an acknowledge on SDA. 
    6. The master sends a data byte that tells the slave device the number of data bytes to be sent to it. 
    7. The slave asserts an acknowledge on SDA. 
    8. The master sends the data bytes. 
    9. The slave asserts an acknowledge on SDA after each data byte. 
    10. The master asserts a stop condition on SDA to end the transaction. 
     */
    
    void I2C_blockWrite(uint8_t reg_Address, uint8_t *data, uint8_t byte_number) {
    
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TR;   // Transmission
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;    // // Generate the start signal
    
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // Wait for start signal to be sent
        EUSCI_B0->TXBUF = reg_Address; // Send register address
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // Waiting for register address to be sent
        EUSCI_B0->TXBUF = 0xA0; // Send Command pointer
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // // Wait for address pointer to be sent
        // Envoi du nombre de bytes à écrire
        EUSCI_B0->TXBUF = byte_number; // Send register number of byte
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // // Wait for number of byte to be sent
        int i;
        // Envoi des données
        for (i = 0; i < byte_number; i++) {
            EUSCI_B0->TXBUF = data[i];
            while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0));
        }
    
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;    // Waiting for data to be sent
        while (EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTP); // Waiting for the end of the transmission
    }
    
    /*
     * Block Read 
    In this operation, the master device reads a block of data from a slave device (see Figure 34). The start address 
    for a block read must previously have been set by setting the address pointer. 
    1. The master device asserts a start condition on SDA. 
    2. The master sends the 7-bit slave address followed by the write bit (low). 
    3. The addressed slave device asserts an acknowledge on SDA. 
    4. The master sends a command code (1010 0001) that tells the slave device to expect a block read. 
    5. The slave asserts an acknowledge on SDA. 
    6. The master sends a byte-count data byte that tells the slave how many data bytes to expect. 
    7. The slave asserts an acknowledge on SDA. 
    8. The master asserts a repeat start condition on SDA. This is required to set the read bit high. 
    9. The master sends the 7-bit slave address followed by the read bit (high). 
    10. The slave asserts an acknowledge on SDA. 
    11. The master receives the data bytes. 
    12. The master asserts an acknowledge on SDA after each data byte. 
    13. A no acknowledge is generated after the last byte to signal the end of the read. 
    14. The master asserts a stop condition on SDA to end the transaction. 
     */
    
    void I2C_blockRead(uint8_t reg_Address, uint8_t *data, uint8_t byte_number) {
        //
    
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TR;   // Transmission
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;    // // Generate the start signal
    
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // Wait for start signal to be sent
        EUSCI_B0->TXBUF = reg_Address; // Send register address
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // Waiting for register address to be sent
        EUSCI_B0->TXBUF = 0xA1; // Send Command pointer
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // // Wait for address pointer to be sent
        EUSCI_B0->TXBUF = byte_number; // Send register number of byte
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)); // // Wait for number of byte to be sent
        EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_TR;  // Reception
        EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;    // // Generate a repetition of the start signal
        while (EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTT); // Wait for the end of the start signal repetition
        while (!(EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG0)); // // Wait for the reception of the data
        int i;
        // Reading data
        for (i = 0; i < byte_number; i++) {
            data[i] = EUSCI_B0->RXBUF;
            while (!(EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG0)); // // Wait for the reception of the data
    
            // Si c'est le dernier byte, envoyer NACK pour signaler la fin de la lecture
            if (i == byte_number - 1) {
                EUSCI_B0->CTLW0 |= UCTXNACK;
            } else {
                EUSCI_B0->CTLW0 &= ~UCTXNACK;
            }
        }
    
        // Arrêt de la transmission
       EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTT; // Wait for the end of the start signal repetition
    }
    
    void Test_Block_()
    {
        // Écrire les données dans les registres concernés
         uint8_t regAddress = 0x82;
         uint8_t data[] = {0x12, 0x03, 0x11};
         uint8_t dataSize = 3;
    
        I2C_blockWrite(regAddress, data, dataSize);
    
         // Exemple d'utilisation du Block Read
         uint8_t readDataSize = 3;
         uint8_t readData[readDataSize];
    
         I2C_blockRead(regAddress, readData, readDataSize);
    
         // Stockage des données lues dans trois variables distinctes
         uint8_t byte0 = readData[0];
         uint8_t byte1 = readData[1];
         uint8_t byte2 = readData[2];
    
        printf("La valeur de byte0 est : %u\n", byte0);
        printf("La valeur de byte1 est : %u\n", byte1);
        printf("La valeur de byte2 est : %u\n", byte2);
    }
    /**
     * main.c
     */
    void main(void)
    {
        WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;     // stop watchdog timer
        clock();
        DCO_clock(5);
        delay(100);
        I2C_Init();
        delay(100);
        Test_Block_();
    
    }
    
    
    
    我尝试编写两个函数、一个是块中写入、另一个是块中读取。 当我运行代码时、我在输出上什么也没有得到。 以下是代码

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

    当您在调试器中暂停时、您的程序在哪里执行?

    ----------------

    > DCO_CLOCK (5);

    我尚未审查此情况的代码、但注释表明这以48MHz 的频率运行 CPU (和 SMCLK)。 如果是这样、BRW=30会以48MHz/30=1.6MHz 的频率运行 I2C、这 太快了。 我建议您坚持使用 DCO_CLOCK (1)、直到其他一切都起作用、但如果不是、您应该设置 BRW=(48MHz/100kHz)=480。

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

    我尝试过这种方法、但它不起作用。 我完全卡住了

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

    当您在调试器中暂停时、您的程序在哪里执行?

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

    嗯、目前我不知道 CCS 如何知道程序在哪里执行、  

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

    程序运行时,单击带有两个垂直条的按钮("||"表示"暂停")。

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

    blockWrite 函数发送{reg、0xA0、N、bytes..}、但图32显示了{0xA0、N、bytes..} [I2C 自动发送"从器件地址"]。 我不确定 AD5933将会如何处理它。

    blockWrite 寄存器编号来自设置地址指针的单独操作[图31]、您可能需要一个单独的 C 函数。

    我认为 blockRead 有一个类似的缺陷。

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

    这是程序执行中断

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

    查看是否可以找到"Registers"视图["Window->Show View->Registers"或某些类似的视图]。 其中特别重要的是 UCB0IFG 和 UCB0STATW。

    有关第28页(ff)的部分未提及它将提供 NACK 的条件。 AD5933可将您的序列解释为字节写入、并在您发送过多字节时提供一个 NACK。

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

    这可能是因为我提供了{reg、0xA0、N、bytes..} 而不是{0xA0、N、字节...}。 但是、在窗口部分中、我没有看到寄存器选项

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

    仅当您在调试器中暂停时、Registers 视图才有用。 它通常在您启动调试器时自动打开。

    [我没有启动调试器,我通过 Window->Show View->Other->Debug->Registers 进入调试器,但首先你需要回到你之前暂停的位置,并朝窗口的右上方看。]

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

    早上好!
    我尝试过这么做、但仍然什么都没有

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

    我不确定我是否理解。

    您尝试了什么、结果如何?

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

    早上好!
    我刚开始使用 MSP432和 AD5933。 两个器件之间的通信通过 I2C 协议完成。 我编写了可读取和写入 AD5933寄存器的函数。 不过、有些寄存器在我写入一个字节的数据时并不会读取我写入的值。 另一方面、还有其他寄存器、在我写入字节时、我会读取与我写入的值相同的值。

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

    您可能无法获得写入的内容、具体取决于器件和寄存器。 例如、某些位可能是只读的、对它们的写入将被忽略。 您需要*非常*熟悉数据表。

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

    是的、我很好地使用了数据表。 以控制寄存器的地址为例、我们对该寄存器进行写入和读取。 对于这些寄存器、我设法读取写入的内容、而不会出现任何问题。 另一方面、如果我们以起始频率的寄存器为例、数据表中指明了我们可以在那里进行写入和读取、但当我在这些寄存器中进行写入并在这些相同的寄存器中再次读取时、 我得到的字节与之前写入的字节不同、

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

    同样、我建议您前往 AD 板获取有关此芯片的帮助。

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

    您可能需要的另一个工具是 I2C 监听器、它将监控流量并告诉您正在发送和接收的确切内容。 我从未使用过一个、因此我没有建议、但谷歌 I2C 监听器有很多选项。

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

    在您之前的报告中、似乎是(a)您没有为块读取/写入发送正确的序列(b)您没有设置地址指针(读取时需要)。 这是否改变了?