cancel
Showing results for 
Search instead for 
Did you mean: 

I2C1 is not working in STM32 after initialization of all Clocks(CCR ,TRISE )?Please Help.

Nchun.1
Senior

Hi i am unable to see SCL,SDA signals in logic analyser. Connected Pullup resistors to Scl,Sda pins. Interfaced with PCF8574 IC (I/O Expander) ,Hardware Connections are fine but

i am not getting even clock(scl) in STM32F401RE

#include<main.h>

#include<stdarg.h>

void SystemInit();

void delay(int val);

void I2C_Config();

void I2C_Start();

void I2C_Write(uint8_t data);

void I2C_Address(uint8_t Address);

void I2C_Stop();

void Uart1_config();

void uart_printf(const char *fmt, ...);

void SystemInit()

{

RCC->CR|=RCC_HSION;

  RCC->APB1ENR|=RCC_PWREN;

  PWR->CR|=PWR_VOS;

  RCC->CFGR|=RCC_SW;

}

void I2C_Config()

{

  /* Master transmitter in standard mode*/

  RCC->AHB1ENR |=2;   /* Enabling clock for GPIOB port*/

  RCC->APB1ENR |=1<<21; /*Enabling clock for I2C1 */

  GPIOB->MODER |=2<<16; /*Alternative function in PB8 SCL pORT*/

  GPIOB->MODER |=2<<18; /*General Purpose output function in PB9 SDA Port*/

  GPIOB->OTYPER |=1<<8; /*1: Output open-drain */

  GPIOB->OTYPER |=1<<9; /*1: Output open-drain */

  GPIOB->PUPDR |=1<<16; /*Pullup */

  GPIOB->PUPDR |=1<<18; /* pullup */

  GPIOA->AFR[1]|=4<<0; /* Alternate function low register is AF4 is I2C1 SCL */

  GPIOA->AFR[1]|=4<<4; /* Alternate function low register is AF4 is I2C1 SDA */

  GPIOA->OSPEEDR|=3<<16; /*High speed */

  GPIOA->OSPEEDR|=3<<18; /*High speed */

  I2C1->CR1 |=(1<<15);

  I2C1->CR1 &=~(1<<15);

  I2C1->CR2 |=16<<0;   /*setting 16 Mhz peripheral input clock */

  I2C1->CCR |=80<<0;   /*setting clock control register */

  I2C1->TRISE|=17<<0;  /*Setting rise time */

  I2C1->CR1|= 1<<0;   /*Enable Periperal Enable */

}

char buf[512];

void uart_printf(const char *fmt, ...)

{

int ret;

va_list args;

va_start(args, fmt);

ret = vsnprintf(buf, 512, fmt, args);

va_end(args);

if (ret > 0)

{

for (int i =0; i < ret; i++)

{

USART1->SR = 0;

USART1->DR = buf[i];

while(!(USART1->SR & (1<<6)) );

}

}

}

void Uart1_config()

{

RCC->APB2ENR |=USART1_CLK;

RCC->AHB1ENR |=1;

GPIOA->MODER |=2<<18;/* Enabling Mode of PA9 */

GPIOA->MODER |=2<<20;/*Enabling Mode of PA9 */

GPIOA->OSPEEDR |=3<<18;/* Enabling High speed of PA9*/

GPIOA->OSPEEDR |=3<<20;/* Enabling High speed of PA10*/

GPIOA->AFR[1] |=7<<4;/*Enabling AFR7 of PA9 */

  GPIOA->AFR[1] |=7<<8;/*Enabling AFR8 of PA10 */

USART1->CR1 |=USART1_EN;

  USART1->BRR =((3<<0) | (0x68<<4)); /*9600 Baud Rate*/

USART1->CR1 |=USART1_RE;

USART1->CR1 |=USART1_TE;

}

void I2C_Start()

{

  I2C1->CR1 |=1<<8; /*Enable Start condition*/

  while(!(I2C1->SR1 & (1<<0)));/*Wait for SB bit to set */

}

void I2C_Write(uint8_t data)

{

while(!(I2C1->SR1 & (1<<7))) ;/* Wait for Bit 7 TxE: Data register empty */

I2C1->DR=data;

while(!(I2C1->SR1 & (1<<2)));/*Wait for the byte Tranfer */

}

void I2C_Address(uint8_t Address)

{

I2C1->DR=Address;

while(!(I2C1->SR1 & 1<<1));/* wait for ADDR Bit 1 ADDR: Address sent*/

uint8_t temp =(I2C1->SR1 | I2C1->SR2);

}

void I2C_Stop()

{

I2C1->CR1 |=(1<<9);/*Bit 9 STOP: Stop generation*/

}

void delay(int val)

{

 RCC->APB1ENR |=1<<0; /* TIM2 clock enabled*/

 TIM2->CNT=0;

 TIM2->PSC=1;

 TIM2->CR1 |=1;

 while(TIM2->CNT < val);

 TIM2->SR=0;

}

int main()

{

  SystemInit();

  Uart1_config();

  I2C_Config();

  uart_printf("CR1 value is %d \n", I2C1->CR1);

  uart_printf("CR2 value is %d \n", I2C1->CR2 );

  uart_printf("Ccr value is %d \n", I2C1->CCR );

  uart_printf("TRISE value is %d \n", I2C1->TRISE );

  uart_printf("Moder value is %d \n", GPIOB->MODER);

  uart_printf("afr value is %d \n", GPIOB->AFR[1]);

  uart_printf("otyper value is %d \n", GPIOB->OTYPER );

  I2C_Start();

  I2C_Address(0x4e);

  uart_printf("DR value is %d \n", I2C1->DR);

  I2C_Write(0x06);

  I2C_Write(0x08);

  I2C_Stop();

  while(1);

}

4 REPLIES 4
Danish1
Lead II

There's a lot you don't tell us, which could help us find out what's wrong.

You don't tell us what is printed out when you run your program. And compare it with what you expect if the program is working as you intend.

My first thought is: Is it hardware or software?

Hardware I2C needs pull-up resistors on its SCL and SDA lines. Without those it cannot work.

It is helpful, when first starting with I2C and it isn't working as you expect, to be able to look at the SCL and SDA lines on an oscilloscope,

But on the other hand, if you have another program that successfully works on I2C on that board, it is more likely to be a software problem.

Help us to help you,

Danish

Thank you .

Now it is Edited.

Unable to see SCL,SDA signals in logic analyser. Connected Pullup resistors to Scl,Sda pins

and Interfaced with PCF8574 IC (I/O Expander) ,Hardware Connections are fine but

i am not getting even clock(scl) in LA. May be it is software problem.

I see you have now made a certain pert of you code bold:

Is that the extent of your edit, or are there other changes?

Unable to see those signals:

You don't make it easy for us. Are the lines high or low?

(Or is it that you haven't wired them up to the Logic Analyser, or not turned the logic analyser on?

Why do we ask this? There was a notorious case in computer support where someone phoned up to complain that the computer wasn't working. The IT support person asked what was on the screen, and the person responded that the screen was dark, as was the whole room. It turned out there was a power failure in the building the person was phoning from...)

And - please - what do you get from all those uart_printf statements. It does help.

As to a comments on your code

1) you refer to the bits in a lot of these peripheral registers by number.

e.g. I2C1->CR1 |=(1<<9);/*Bit 9 STOP: Stop generation*/

I don't know about you, but as someone who spends a *lot* of time coding for stm32 at low-level, I can never remember which bit is the right one in the different registers. While it is helpful that you comment, sometimes people make mistakes. Wherever possible, do use the #defines e.g. I2C_CR1_STOP

2) When you set e.g. the GPIO pin mode, you want e.g. the bit pattern 10 to be programmed.

You currently set the mode just by OR-ing

e.g. GPIOB->MODER |=2<<16; /*Alternative function in PB8 SCL pORT*/

You assume that the pair of MODE bits are zero beforehand. How strongly do you know this for every case?

It is safer to do

GPIOB->MODER = (GPIOB->MODER & ~GPIO_MODER_MODER8_Msk) | (2 * GPIO_MODER_MODER8_0)

Note in particular the Tilde "~" before GPIO_MODER_MODER8_Msk to invert the bit-pattern.

Hope this helps,

Danish

Thank you ! I2C Communication is getting established