cancel
Showing results for 
Search instead for 
Did you mean: 

How do I configure MCU as I2C slave device?

KSchr.11
Associate II

I've been trying to set up MCU (STM32 L432KC) as an I2C slave device. I have previously tested it as a master device to interface with a port expander(MCP2307) and it works perfectly fine.

The following is the code I am running. The master sends 1,2,3 every 500 ms and the slave device is supposed to a glow a common anode RGB led (rgb led program works fine too, tested as SPI slave device before)

#include "stm32l4xx.h"                  // Device header
 
#define RED_ON (GPIOB->ODR &=~(1<<1))
#define RED_OFF (GPIOB->ODR |=1<<1)
 
#define BLUE_ON (GPIOB->ODR &=~(1<<6))
#define BLUE_OFF (GPIOB->ODR |= 1<<6)
 
#define GREEN_ON (GPIOB->ODR &=~(1<<7))
#define GREEN_OFF (GPIOB->ODR |= 1<<7);
 
 
void i2c1_init(void);
 
 
int main()
{
	i2c1_init();
	uint8_t c;
	
	RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
	
	GPIOB->MODER &=~(3<<2 | 3<<12 | 3<<14);
	GPIOB->MODER |= 1<<2 | 1<<12 | 1<<14;
	
	GPIOB->ODR |= (1<<1 | 1<<6 | 1<<7);
 
	NVIC_EnableIRQ(I2C1_EV_IRQn);
	
	while(1)
	{
	}
	
}
 
void i2c1_init(void)
{
	RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
	RCC->APB1ENR1 |= RCC_APB1ENR1_I2C1EN;
	
	GPIOA->MODER &=~(3<<18 | 3<<20);
	GPIOA->MODER |= 2<<18 | 2<<20;
	
	GPIOA->AFR[1] &=~(0xF<<4 | 0xF<<8);
	GPIOA->AFR[1] |= (4<<4 | 4<<8);				//PA9, PA10 - AF i2c
	
	GPIOA->OTYPER &=~(1<<9 | 1<<10);
	GPIOA->OTYPER |= (1<<9 | 1<<10);			//configure as Open Drain
	
 
	I2C1->CR1 &=~(I2C_CR1_PE);
	
	I2C1->TIMINGR = 0x00400D10;			//100khz, 1000ns tr, 100ns tf
	
	
	I2C1->OAR1 |= 0X40;		//own address
	I2C1->OAR1 |= 1<<15;	//enable own address
	
	I2C1->CR1 |= I2C_CR1_RXIE | I2C_CR1_ADDRIE;			//enable addr match and RXNE interrupts
	
	
	I2C1->CR1 |= I2C_CR1_PE;
	
}
 
 
 
void I2C1_EV_IRQHandler(void)
{
	uint8_t c;
	
	
	if(I2C1->ISR & I2C_ISR_RXNE)
	{
		c = I2C1->RXDR;
		
		switch(c)
		{
			case 1: GREEN_OFF;
			BLUE_OFF;
			RED_ON;
			break;
			
			case 2: RED_OFF;
			BLUE_OFF;
			GREEN_ON;
			break;
			
			case 3: RED_OFF;
			GREEN_OFF;
			BLUE_ON;
			break;
			
		}
			
		I2C1->ICR |= I2C_ICR_ADDRCF;
		
	}
		
	
}
 

I've tried configuring Slave Byte Control (SBC) in CR1 and NBytes in CR2 registers too, but it didn't change anything. From the reference manual, the only step to configure as slave is enable Own address. Are there any other steps or event interrupts I need to configure too?

By the way, I've tried using polling too instead of interrupt previously and had no luck either.

PS: TIMINGR value was generated through xls file by ST (and verified in cubemx) and I've tried different clock frequency and different timing values too, just in case that comes as a suspicion. And I'm using external pullups on SCL and SDA lines.

0 REPLIES 0