STM32F4上I2C(在PROTEUS中模拟)调试不通的问题

2022-10-13 09:30发布

大家好,

许多天来,我一直在努力让I2C在STM32F401CE上工作(在PROTEUS中模拟)。

USART工作得很好,但I2C还没有!我使用默认值,HSI 16MHz作为源时钟,没有预分频器。

我需要你的帮助

我初始化I2C1并发送启动条件的代码是:

void i2c1_init(){ 

// Enable clocks to the peripherals RCC -> APB1ENR |= 1<<21;    // Enable I2C1 clock RCC -> AHB1ENR |= 1<<1;    // Enable GPIOB clock // set pins B6=SCL and B7=SDA to Alternate Function, Pull-up enabled, Open-Drain and high speed GPIOB -> MODER  = 2<<2*7 | 2<<2*6;  //MODER7/6[1:0] = 10 => Alternate function mode GPIOB -> OTYPER = 1<<1*7| 1<<1*6;   // B6/7 = 1 => Output open-drain GPIOB -> OSPEEDR = 3<<2*7 | 3<<2*6;   // OSPEEDR7/6[1:0] = 11 => High speed GPIOB -> PUPDR = 1<<2*7 | 1<<2*6;  // PUPDR7/6[1:0] = 01 => Pull-up GPIOB -> AFRL = (4 << 4*7) | (4 << 4*6); //AFRL7/6[3:0] = 0100 => AF4  (I2C1) // initialization steps: I2C1 -> CR1 |= 1<<15;   // SWRST (bit15) = 1 => Enable the software reset I2C1 -> CR1 &= ~(1<<15);  // then immediately resetting the SWRST bit. I2C1 -> CR2 = 16;    // FREQ[5:0] (Bits 5:0) = 16 => Peripheral clock frequency = 16 MHz// other bits  = 0 => Interrupts and DMA disabled //I2C1 -> OAR1 = 0x30;   // Own address in slave mode only // set SCL clock: Thigh = Tlow = CCR * TPCLK1 (here TPCLK1 = 1/16 MHz) // For 100kHz, Thigh = Tlow = 5uS => CCR = (5/0.0625) = 80 I2C1 -> CCR = 80;    // F/S (Bit 15) = 0 => standard master mode// CCR[11:0] (Bits 11:0) =  80 => SCL clock = 100kHz I2C1 -> TRISE |= 11;                 // TRISE[5:0] (Bits 5:0) = 9 => Maximum rise time in standard mode I2C1 -> CR1 |= 1;    // PE (bit0) = 1 => Enable the peripheral

}//  send a start condition and slave address

void I2C1_Start(char address)
{
uint16_t reg;   //I2C1->CR1 |= (1<<10>
 I2C1 -> CR1 |= 1<<8;   // START (Bit 8) = 1 => start generation (and enter master mode) 
 while(!(I2C1 -> SR1 & 1<<0)); // wait until SB (Bit 0) = 1 => Start condition generated
  
 reg = I2C1 -> SR1;     // MUST read SR1 reg first
 // then send the address to clear SB bit
 I2C1 -> DR = (address << 1) | 0x00; // write address in DR reg
 while(!(I2C1 -> SR1 & 1<<1));  // wait until ADDR (Bit 1) = 1 => End of address transmission
 // ADDR bit is cleared by software reading SR1 followed by reading SR2
 reg = I2C1 -> SR1;      
 reg = I2C1 -> SR2; //In datasheet p499: TxE is not set during address phase ?!
 //while(!(I2C1 -> SR1 & 1<<7 xss=removed> Data register empty }void main(){
 i2c1_init();
 I2C1_Start(0x60); for (;;) ;
}

附完整项目

请帮忙

编辑:

要构建代码,请在“periph.h”中去掉第33行的注释。

EDIT2(编辑2):

I2C.7z


6条回答
杨昭君
2023-09-02 17:03

怎么说呢?是人就会犯错。

举个例子:

你确定 1<<15 是 SWRST? 也许可能是 1<<14. Or 1<<13?


或者再过2个月,然后再次打开此项目。如果你长时间不再做这个项目,你会很难去查看出所有的东西。


现在它有问题了,你可以来小平头电子技术社区寻求帮助(没关系!)。


但是。。也许你的代码错了。。。还是其中一个错误了?

现在到处都有40个BIT位。

这不是寻求帮助,这几乎是一次大排查,要求任何人打开RM并检查每个BIT位以确保一切正常。。。

完全浪费时间

但使用CMSIS标头会更好:


I2C1 -> CR1 |= I2C1_CR1_SWRST;


I2C1_CR1_SWRST解释了一切:

-用于I2C1

-用于CR1

-这是SWRST位


因此,任何错误都很容易检测到:

I2C1 -> CR1 |= I2C2_CR1_SWRST;

I2C1 -> CR1 |= I2C1_CR1_POTATO;

I2C1 -> CR2 |= I2C1_CR1_SWRST;


CMSIS标头是由ARM自己制作的,它不是任何类型的库,您仍将在裸机级别进行编码。


一周热门 更多>