我正在try 使用STM32G474RE的I2C与MCP4728 DAC芯片进行通信.我要发送到芯片的字节是{0xFF, 0x58, 0x04, 0x56},调试同意TX寄存器接收上述字节.然而,当我实际传输字节时,示波器上显示的是{0xFF, 0x58, 0xFF, 0xFF},每当我修改第一个字节时,第三个和第四个字节也会改变.

int main(void){
    SystemClock_Config();   //16MHz HSI16 Clock
    I2C2_Init();
    while (1){
        MCP4728_Transmit(SINGLE_WRITE, CHANNEL_A, 0x456);
    }
}

void MCP4728_Transmit(uint8_t tx_mode, uint8_t channel, uint16_t data){
    /*If data larger than 12 bits (0xFFF) return*/
    if (data > 0xFFF)
        return;
    
    int tx_buffer_index = 0;
    uint8_t tx_buffer[4];
    tx_buffer[0] = 0xFF;
    tx_buffer[1] = tx_mode | (channel << 1); 
    tx_buffer[2] = (uint8_t) (data >> 8) & 0x0F;
    tx_buffer[3] = (uint8_t) data & 0xFF;
    
    I2C2->CR2 |= 0x04 << I2C_CR2_NBYTES_Pos;
    I2C2->CR2 &= ~I2C_CR2_AUTOEND;
    I2C2->CR2 |= ((0x60<<1)<< I2C_CR2_SADD_Pos);
    I2C2->CR2 |= I2C_CR2_START;
    
    
    
    while(!(I2C2->ISR & I2C_ISR_TC)){
        if (I2C2->ISR & I2C_ISR_NACKF)
            return;
        if (!(I2C2->ISR & I2C_ISR_TXIS))
            return;
        else{
            I2C2->TXDR = tx_buffer[tx_buffer_index];
            tx_buffer_index++;
        }
    }
    I2C2->CR2 |= I2C_CR2_STOP;
}

void I2C2_Init(void){
    /*Enable I2C and GPIOA clock*/
    RCC->APB1ENR1 |= RCC_APB1ENR1_I2C2EN;
    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
    
    
    /*Config PA8 and PA9*/
    //PA8 and PA9 Alternate Function (AF4)
    GPIOA->MODER &= ~(GPIO_MODER_MODE8 | GPIO_MODER_MODE9);
    GPIOA->MODER |= (0x02 << GPIO_MODER_MODE8_Pos | 0x02 << GPIO_MODER_MODE9_Pos);
    GPIOA->AFR[1] |= (0x04 << GPIO_AFRH_AFSEL8_Pos | 0x04 <<GPIO_AFRH_AFSEL9_Pos);
    //Output type Open Drain
    GPIOA->OTYPER |= (GPIO_OTYPER_OT8 | GPIO_OTYPER_OT9);
    //High Speed
    GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED8 | GPIO_OSPEEDR_OSPEED9);
    GPIOA->OSPEEDR |= (0x02 << GPIO_OSPEEDR_OSPEED8_Pos | 0x02 << GPIO_OSPEEDR_OSPEED9_Pos);
    //Enable Pull Up
    GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD8 | GPIO_PUPDR_PUPD9);
    GPIOA->PUPDR |= (0x01 << GPIO_PUPDR_PUPD8_Pos | 0x01 << GPIO_PUPDR_PUPD9_Pos);
    
    
    /*Configure I2C2*/
    //Disable I2C
    I2C2->CR1 &= ~I2C_CR1_PE;
    //Default filter
    I2C2->CR1 &= ~I2C_CR1_ANFOFF;
    I2C2->CR1 &= ~I2C_CR1_DNF;
    //TIMINGR value for 16MHz taken from table in Reference Manual (page xxx)
    I2C2->TIMINGR |= (0x03 << I2C_TIMINGR_PRESC_Pos  | 0x04 << I2C_TIMINGR_SCLDEL_Pos | \
                      0x02 << I2C_TIMINGR_SDADEL_Pos | 0x0F << I2C_TIMINGR_SCLH_Pos   | \
                      0x13 << I2C_TIMINGR_SCLL_Pos);
    //Enable stretching
    I2C2->CR1 &= ~I2C_CR1_NOSTRETCH;
    //Enable I2C
    I2C2->CR1 |= I2C_CR1_PE;
}

推荐答案

I2C_ISR.TXIS表示发送缓冲区为空,即数据已移至移位寄存器.当移位寄存器仍然为空时,这可能几乎立即发生在第一个字节,但在写入第二个字节之后,需要传输整个前一个字节才能使TXIS再次变为1.但是,您不需要等待:

if (!(I2C2->ISR & I2C_ISR_TXIS))
            return;

这意味着,在第二个字节被写入而第三个字节不能被写入之后,您立即返回.因为在主循环中,你无条件地重复调用这个函数,一旦第一个字节被传输,第二个字节被传输到移位寄存器,TXIS再次变为1,这个函数再次存储第一个字节,并且不成功存储第二个字节,依此类推.这就是为什么你会看到模式第一个字节-第二个字节-第一个字节-第一个字节.

在循环中等待I2C_ISR.TXIS.

C++相关问答推荐

segfault在C中使用getline()函数

malloc实现:判断正确的分配对齐

将 typewriter LF打印到Windows终端,而不是隐含的CR+LF

为什么GCC C23中的关键字FALSE不是整数常量表达式?

为什么我从CSV文件中进行排序和搜索的代码没有显示数据的所有结果?

==284==错误:AddressSaniizer:堆栈缓冲区下溢

如何将C中的两个字符串与从文件接收的字符串中的字符数进行比较

链表删除 node 错误

C标准关于外部常量的说明

C++中PUTS函数的返回值

某些EAX值的不同调用方的CPUID结果不一致

即使我在C++中空闲,也肯定会丢失内存

RISC-V GCC编译器错误编译ASM代码

I';我试着从.txt文件中读取文本,并用c计算其中的单词数量

传递参数:C 和 C++ 中 array 与 *&array 和 &array[0] 的区别

无法在线程内用 C 打印?

int 与 size_t 与 long

窗口消息处理函数以某种方式更改了应保持不变的 int 变量的值

React Native Android C++ TurboModules 静态 C 库链接问题

假设函数调用返回的 string(char *) 上有 free() 是否安全?