大家好!
我希望在 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);
}
