Skip to main content
Graduate II
December 10, 2024
Question

What am I missing in this attempt to make STM32F103 act as I2C Slave?

  • December 10, 2024
  • 0 replies
  • 668 views

This code, partially generated by Copilot, does only print "="

At the same time, I do see that the device PB6(SCL) and PB7(SDA) recieves packets adressed to it, requestng data.

 

#include <Arduino.h>

#define I2C_ADDRESS 0x0B

volatile int x = 0;
volatile int y = 0;
volatile int add = 0;

void setup() {
 Serial.begin(115200);

 // Initialize LED pin
 pinMode(PC13, OUTPUT);

 // Enable clock for I2C1
 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
 RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

 // Configure PB6 and PB7 as alternate function open-drain
 GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6 | GPIO_CRL_MODE7 | GPIO_CRL_CNF7);
 GPIOB->CRL |= (GPIO_CRL_CNF6_1 | GPIO_CRL_CNF6_0 | GPIO_CRL_CNF7_1 | GPIO_CRL_CNF7_0);

 // Reset I2C1
 I2C1->CR1 = I2C_CR1_SWRST;
 I2C1->CR1 = 0;

 // Configure I2C1
 I2C1->CR2 = 36; // APB1 clock frequency in MHz
 I2C1->CCR = 180; // Standard mode, 100kHz
 I2C1->TRISE = 37; // Maximum rise time

 // Set I2C address
 I2C1->OAR1 = (I2C_ADDRESS << 1) | I2C_OAR1_ADDMODE;

 // Enable I2C1
 I2C1->CR1 = I2C_CR1_PE;

 // Enable ACK and POS
 I2C1->CR1 |= I2C_CR1_ACK | I2C_CR1_POS;

 // Enable I2C1 interrupts
 I2C1->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN | I2C_CR2_ITERREN;

 // Enable I2C1 event interrupt in NVIC
 NVIC_EnableIRQ(I2C1_EV_IRQn); // Enable I2C1 event interrupt address mached etc
 NVIC_EnableIRQ(I2C1_ER_IRQn); // Enable I2C1 error interrupt.
}

void loop() {
 static unsigned long lastPrint = 0;
 if (millis() - lastPrint >= 1000) {
 lastPrint = millis();
 Serial.println("=");
 }


 if (add != 0) {
 Serial.print("U:0x");
 Serial.println(add, HEX);
 add = 0;
 digitalWrite(PC13, !digitalRead(PC13));
 }


 if (x != 0) {
 Serial.print("U:0x");
 Serial.println(x, HEX);
 x = 0;
 digitalWrite(PC13, !digitalRead(PC13));
 }

 if (y != 0) {
 Serial.println("V");
 y = 0;
 }
}

extern "C" void I2C1_EV_IRQHandler(void) {
 if (I2C1->SR1 & I2C_SR1_ADDR) {
 // Address matched
 (void)I2C1->SR1;
 (void)I2C1->SR2;
 add = 1;
 } else if (I2C1->SR1 & I2C_SR1_RXNE) {
 // Data received
 x = I2C1->DR;
 } else if (I2C1->SR1 & I2C_SR1_TXE) {
 // Data requested
 I2C1->DR = y;
 //Serial.println(y); // Print the value of y
 y = 1;
 } else if (I2C1->SR1 & I2C_SR1_STOPF) {
 // Stop condition detected
 (void)I2C1->SR1;
 I2C1->CR1 |= I2C_CR1_PE;
 }
}

extern "C" void I2C1_ER_IRQHandler(void) {
 // Handle I2C errors
 if (I2C1->SR1 & I2C_SR1_BERR) {
 I2C1->SR1 &= ~I2C_SR1_BERR;
 }
 if (I2C1->SR1 & I2C_SR1_ARLO) {
 I2C1->SR1 &= ~I2C_SR1_ARLO;
 }
 if (I2C1->SR1 & I2C_SR1_AF) {
 I2C1->SR1 &= ~I2C_SR1_AF;
 }
 if (I2C1->SR1 & I2C_SR1_OVR) {
 I2C1->SR1 &= ~I2C_SR1_OVR;
 }
 if (I2C1->SR1 & I2C_SR1_PECERR) {
 I2C1->SR1 &= ~I2C_SR1_PECERR;
 }
}
    This topic has been closed for replies.