cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F401 I2C driver using register

AH25
Associate

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

 

 

2 REPLIES 2
SofLit
ST Employee

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!

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
PS:
1 - This is NOT an online support (https://ols.st.com) but a collaborative space.
2 - Please be polite in your reply. Otherwise, it will be reported as inappropriate and you will be permanently blacklisted from my help.

"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