cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F401 I2C driver using register in Proteus simulation

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 }
View more

 

 

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; }
View more

 

 

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
mÆŽALLEm
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.
Andrew Neil
Super User

"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

 

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.