STM32F103C8与PCA9685通信时I2C_DR寄存器无法自动清除问题
STM32F103C8 操作I2C_DR寄存器发送数据时数据残留问题
我用STM32F103C8搭配PCA9685,通过直接操作I2C_DR寄存器的方式在I2C总线上发送数据。现在遇到的问题是:写入数据后,I2C_DR寄存器里的数据会残留——按协议本该在数据发送完成后自动清除,但我的代码里没实现这个自动清除的逻辑,不知道问题出在哪。
逻辑分析仪捕获的I2C信号如下:
我的代码如下:
#include "stm32f10x.h" void I2C_Write_Single(int device_address, int mem_address, int data); void I2C_Restart(int device_address, int data); uint32_t temp = 0; int main(){ /*********STEPS FOLLOWED********* 1. Enable the I2C Clock and GPIO Clock 2. Configure I2C Pins for alternate function 3. Reset I2C 4. Program the peripheral input clock in I2C_CR2 Register in order to generate correct timing 5. configure the clock control register 6. Configure the rise time register 7. Program the I2C_CR1 register to enable the peripheral */ I2C1->CR1 |= (1<<15); I2C1->CR1 &=~ (1<<15); //GPIO Port B enabled RCC->APB2ENR |= (1<<3); //I2C enabled RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //timer enable TIM2 (general timer) RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //TIM2 config TIM4->PSC |= 0; TIM4->ARR |= 71; TIM4->CR1 |= TIM_CR1_URS; TIM4->DIER |= TIM_DIER_UIE; TIM4->EGR |= TIM_EGR_UG; NVIC_EnableIRQ(TIM4_IRQn); //Mode register set for 50MHz (B7 and B6) GPIOB->CRL |= (1<<25) | (1<<24); GPIOB->CRL |= (1<<29) | (1<<28); //GPIO B7 and B6 pin registers (alternate function open drain) GPIOB->CRL |= (1<<27) | (1<<26); GPIOB->CRL |= GPIO_CRL_CNF7_1 | (1<<30); //Peripheral frequency (APB1) 36MHz (its written in datasheet) I2C1->CR2 |= 36 ; //I2C clock control register /* to calculate CCR (Clock Control Register) CCR= [((I2C_Period)/2)/(APB1_Period)] I2C period is 400KHz(from user manual page 781) Ti2c= 1/100K = 10us APB1 Period = 1/36 = 27.7 ns CCR = [(5000ns)/(27.7ns)]= 180 */ I2C1->CCR |= 180; I2C1->TRISE |= 37 ; // TRise = CR2+1 (from datasheet page 783) I2C1->CR1 |= I2C_CR1_ACK; I2C1->CR1 |= I2C_CR1_PE; I2C_Restart(0x00, 0x06); I2C_Write_Single( 0x80, 0x00, 0x08); //SLEEP bit gets cleared so we can get PWM signal I2C_Write_Single( 0x40, 0x00, 1<<6); //EXTERNAL CLOCK bit gets cleared so we can get PWM signal I2C_Write_Single( 0x40, 0xFE, 0XB0); // PRE_SCALE registers set to 0xB0 that way PWM Frequency will be 50 MHz (PCA9685 Datasheet page 9) // PWM delay %0 so LED0_ON_L and LED0_ON_H registers set to 0 I2C_Write_Single( 0x40, 0x06, 0X01); I2C_Write_Single( 0x40, 0x07, 0X99); // 1.5ms PWM will be given (1,5/20)*4096=307 LED0_OFF_H= 3 (decimal) LED0_OFF_H= 07 (decimal) I2C_Write_Single( 0x41, 0x09, 0X08); I2C_Write_Single( 0x41, 0x08, 0X00); return 0; } void I2C_Write_Single(int device_address, int mem_address, int data) { I2C1->CR1 |= I2C_CR1_START; //generate start condition while (!(I2C1->SR1 & I2C_SR1_SB)); // we check the SB flag if start bit didn't sent master device will stay in this loop I2C1->DR |= device_address ; // device address is 0x00 while (!(I2C1->SR1 & I2C_SR1_ADDR)); // we check ADDR flag. Once there is address mach device will exit the loop temp = I2C1->SR1 | I2C_SR2; // we need to clear ADDR bit after we checked the flags. To reset SR1 and SR2 registers we just read them while (!(I2C1->SR1 & I2C_SR1_TXE)); // wait for the byte transfer I2C1->DR |= mem_address ; // MODE1 register (PCA9685 datasheet page 9) while (!(I2C1->SR1 & I2C_SR1_BTF));//wait for transmit while (!(I2C1->SR1 & I2C_SR1_TXE)); // wait for the byte transfer I2C1->DR |= data << 1 ; // to set PWM frequency we set SLEEP bit 1 (PCA9685 datasheet page 24) while (!(I2C1->SR1 & I2C_SR1_BTF));//wait for transmit I2C1->CR1 |= I2C_CR1_STOP; //generate stop condition } void I2C_Restart(int device_address, int data) { I2C1->CR1 |= I2C_CR1_START; //generate start condition while (!(I2C1->SR1 & I2C_SR1_SB)); // we check the SB flag if start bit didn't sent master device will stay in this loop I2C1->DR |= device_address; // device address is 0x00 while (!(I2C1->SR1 & I2C_SR1_ADDR)); // we check ADDR flag. Once there is address mach device will exit the loop temp = I2C1->SR1 | I2C_SR2; // we need to clear ADDR bit after we checked the flags. To reset SR1 and SR2 registers we just read them while (!(I2C1->SR1 & I2C_SR1_TXE)); // wait for the byte transfer I2C1->DR |= data; // MODE1 register (PCA9685 datasheet page 9) while (!(I2C1->SR1 & I2C_SR1_BTF));//wait for transmit while (!(I2C1->SR1 & I2C_SR1_TXE)); // wait for the byte transfer I2C1->CR1 |= I2C_CR1_STOP; //generate stop condition }
我尝试过手动清除寄存器,但执行I2C1->DR &=~ 0xFF时,主设备会立即向从设备发送0x00数据。
内容的提问来源于stack exchange,提问作者Clyde Xander
相关产品推荐
相关产品推荐

