Skip to main content
Visitor II
December 14, 2023
Question

STM32F401 I2C driver using register in Proteus simulation

  • December 14, 2023
  • 2 replies
  • 2568 views

I want to use two STM32F401xx MCU in proteus. One of them is to be a master and the other is to be a slave.

This is my code for the master:

 

 

 #include <stdint.h>
 #include <stdio.h>
 uint8_t temp=0;
 void begin();
 void end(void);
 void Write (uint8_t);
 void star(void);
 void address(uint8_t addr);
 uint8_t value = 0x00 ;
void main() {
 begin();
 star();
 address(0x08);
 Write(0x01);
 end();
}
void begin(){
 //join I2C as a master mode
 RCC_APB1ENR |= (1<<21); // enable I2C CLOCK
 RCC_AHB1ENR |= (1<<1); // Enable GPIOB CLOCK
 // Configure the I2C PINs for ALternate Functions
 //PB8 and PB9 are connected to I2C1_SCL and I2C1_SDA
 GPIOB_MODER |= (1<<16)|(1<<18);
 GPIOB_OTYPER |= ((1<<8) | (1<<9));
 GPIOB_OSPEEDR |= ((3<<16) | (3<<18));
 GPIOB_PUPDR |= ((1<<16) | (1<<18));
 GPIOB_AFRH |= ((4<<0) | (4<<4));
 // Reset the I2C
 I2C1_CR1 |= (1<<15); //I2C Peripheral under reset state -->page.493 manual
 I2C1_CR1 &= ~(1<<15); //I2C Peripheral not under reset -->page.493 manual
 // Program the peripheral input clock in I2C_CR2 Register in order to generate correct timings
 I2C1_CR2 |= (42 <<0); // PCLK1 FREQUENCY in MHz
 I2C1_CCR |= (210<<0); // Configure the clock control registers
 I2C1_TRISE = 43; // Configure the rise time register
 I2C1_CR1 |= (1<<0); // Enable I2C

}
void star(void){
 //Generate a start condition
 I2C1_CR1 |= (1<<8); // Generate START
 while (!(I2C1_SR1 & (1<<0))); // Wait for SB bit to set to 1
}
void address(uint8_t addr){
 I2C1_DR = addr; // send the address
 while (!(I2C1_SR1 & (1<<1)));// wait until the address recieved success
 temp = I2C1_SR1 | I2C1_SR2; //clear ADDR
}

 void end(void) {

 I2C1_CR1 |= (1<<9);//stop generation
 // Wait until the STOP condition is complete
 while (I2C1_SR2 & (1<<0)); //Cleared by hardware after detecting a Stop condition on the bus
 // Clear the STOP bit
 I2C1_CR1 &= ~(1<<9);
 }

 void Write (uint8_t dat)
 {
 while (!(I2C1_SR1 & (1<<7))); // wait for TXE bit to set
 I2C1_DR = dat ; // wait for BTF bit to set
 while (!(I2C1_SR1 & (1<<2))); //waiting while BTF=0 but when BTF=1; Data byte transfer succeeded

 }

 

 

code for the slave:

 

 

 #include <stdint.h>
 #include <stdio.h>
 uint8_t temp=0;
 uint8_t state =0x00;
 void begin(uint8_t addr);
 void end(void);
 uint8_t Read ();
void main() {
 RCC_AHB1ENR |= (1<<0); // Enable GPIOA CLOCK
 GPIOA_MODER |=(1<<0);//set pin 0 as output
 begin(0x08);
 state = Read();
 end();
 
 if (state == 0x01){
 GPIOA_ODR |=(1<<0);//set 1 for pin 0
 }
}
void begin(uint8_t addr){
 RCC_APB1ENR |= (1<<21); // enable I2C CLOCK -
 RCC_AHB1ENR |= (1<<1); // Enable GPIOB CLOCK

 // Configure the I2C PINs for ALternate Functions
 //PB8 and PB9 are connected to I2C1_SCL and I2C1_SDA
 GPIOB_MODER |= (2<<16) | (2<<18);
 GPIOB_OTYPER |= (1<<8) | (1<<9);
 GPIOB_OSPEEDR |= (3<<16) | (3<<18);
 GPIOB_PUPDR |= (1<<16) | (1<<18);
 GPIOB_AFRH |= (4<<0) | (4<<4);

 I2C1_CR2 |= (42 <<0); // PCLK1 FREQUENCY in MHz
 I2C1_CCR |= (210<<0); // Configure the clock control registers
 I2C1_TRISE = 43; // Configure the rise time register
 I2C1_CR1 |= (1<<0); // Enable I2C
 //join I2C bus as a slave mode
 I2C1_OAR1 = addr;//own address interface
 I2C1_CR1 |= (1<<0); // Enable I2C
 I2C1_CR1 |= (1<<10); // Enable the ACK ,indicate that a byte is received
 
}
 void end(void) {
 I2C1_CR1 |= (1<<9);//stop generation
 // Wait until the STOP condition is complete
 while (I2C1_SR2 & (1<<0)); //Cleared by hardware after detecting a Stop condition on the bus
 // Clear the STOP bit
 I2C1_CR1 &= ~(1<<9)
 }
 uint8_t Read (){
 uint8_t receivedData = 0;
 I2C1_CR1 &= ~(1<<10); // clear the ACK bit
 temp = I2C1_SR1 | I2C1_SR2; // read SR1 and SR2 to clear the ADDR bit.... EV6 condition
 I2C1_CR1 |= (1<<9); // Stop I2C
 while (!(I2C1_SR1 & (1<<6))); // wait for RxNE to set
 receivedData = I2C1_DR; // Read the data from the DATA REGISTER
 return receivedData;
 }

 

 

when i run the simulation there is nothing happened , the LED still off and PB8 , PB9 haven`t change , i want to know , if there any problem in my provided code, I followed the datasheet and manual of STM32F401xx to write this simple driver. is this the correct address will be passed to begin(addr) ? 

address.PNG

and this is the simulation connection in proteus:

proteus.PNG

 

 

    This topic has been closed for replies.

    2 replies

    Technical Moderator
    December 14, 2023

    Hello,

    You can start with using HAL or LL then if all worked fine, inspire from it to access directly to the registers.

    And frankly, if I was you, I don't rely on this kind of simulation. 

    I suggest to run your tests on a real HW!

    Super User
    December 14, 2023

    "i want to know , if there any problem in my provided code"

    So what have you done to investigate & debug your code?

    You're using Proteus - so you have both software & hardware debug facilities available to you...

    AndrewNeil_1-1702557900138.png

     

    AndrewNeil_0-1702557784456.png

    https://www.labcenter.com/tutorials/ 

    https://www.youtube.com/@LabcenterElectronicsLtd