How do you plan to solve it?
/* Arduino UNO R3 */
#include <SPI.h>
#include <Wire.h>
#include <string.h>
volatile byte receivedData;
unsigned long start, end, i2c_elapsed_time = 0;
const char data[] = "I2C (Inter-Integrated Circuit) & SPI (Serial Peripheral Interface ) are two common communication protocols used to connect devices like sensors and microcontrollers. I2C uses two lines: SDA (data) and SCL (clock), allowing multiple devices to communicate through unique addresses. It supports multi-master and multi-slave configurations but operates at a slower speed, typically 100kHz to 400 kHz, though it can reach higher speeds in fast modes. I2C is simple and requires fewer connections, but its clock stretching and overhead make it less efficient for high-speed data transfers. SPI, on the other hand, use four lines: MOSI (Master Out Slave In), MISO (Master In Slave Out), SCK (clock), and SS (Slave Select). SPI supports higher speeds (up to tens of MHz), making it better suited for fast data transfers. It's simpler in protocol, with no need for addressing, but it requires more wires and separate SS lines. While I2C is ideal for many devices, SPI excels in fast, reliable communication.";
void send_SPI_data(void)
{
// Send through SPI the data
start = millis();
digitalWrite(SS, LOW);
for(int i=0; i<100; i++)
{
for(int j=0; j<1000; j++)
{
receivedData = SPI.transfer(data[j]);
delayMicroseconds(100);
}
}
digitalWrite(SS, HIGH);
end = millis();
int spi_elapsed_time = end - start - 10000;
delay(1000);
Serial.print("SPI data transfer time consumed: ");
Serial.print(spi_elapsed_time);
Serial.println(" ms");
}
void setup() {
Serial.begin(9600);
// Initialize SPI
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV4);
pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
// Initialize I2C
Wire.begin();
delay(1000);
Serial.println("Sending I2C data...");
// Send through I2C the data
for(int i=0; i<100; i++)
{
for(int j=0; j<1000; j++)
{
start = millis();
Wire.beginTransmission(0x50);
Wire.write(data[j]);
int error = Wire.endTransmission();
end = millis();
if(!error)
i2c_elapsed_time += (end - start);
while(error)
{
Serial.println(error);
start = millis();
Wire.beginTransmission(0x50);
Wire.write(data[j]);
error = Wire.endTransmission();
end = millis();
if(!error)
i2c_elapsed_time += (end - start);
}
}
}
delay(1000);
Serial.print("I2C data transfer time consumed: ");
Serial.print(i2c_elapsed_time);
Serial.println(" ms");
Serial.println("Waiting for STM32 ready...");
byte ready = 0;
while (ready != 1) {
Serial.print("ready: ");
Serial.println(ready);
Wire.requestFrom(0x50, 1);
if (Wire.available()) {
ready = Wire.read();
Serial.print("ready: ");
Serial.println(ready);
}
delay(100);
}
Serial.println("Sending SPI data...");
send_SPI_data();
}
void loop() {
}/*
* my_main.c
*
* Created on: Mar 14, 2026
* Author: georgegio
*/
#include "my_main.h"
DMA_HandleTypeDef dma_usart2_tx;
UART_HandleTypeDef usart2;
SPI_HandleTypeDef spi1;
I2C_HandleTypeDef ic21;
GPIO_InitTypeDef button, sspin;
uint8_t change_val = 1;
uint32_t i2c_data = 0, spi_data = 0;
char data_buffer[100000] = { 0 };
uint8_t spi_rc_buffer, i2c_rc_buffer;
char buffer[50] = { 0 };
uint8_t i2c_received = 0, spi_received = 0;
int main(void)
{
/* Initializes low level hardware at the processor level */
HAL_Init();
// Sets other clock sources besides HSI
if( SystemClock_Config(HSI_16) != Execution_Succesfull)
return Execution_Failed;
// Configure the I2C module
if ( I2C_Config(&ic21, I2C1)!= Execution_Succesfull)
return Execution_Failed;
// Configure the SPI module.
if ( SPI_Config(&spi1, SPI1, SLAVE) != Execution_Succesfull )
return Execution_Failed;
// Configure the SS GPIO pin for SPI communication
if( SPI_SS_Config(&sspin) != Execution_Succesfull)
return Execution_Failed;
// Configure the DMA1 module
if( DMA_Config() != Execution_Succesfull )
return Execution_Failed;
// Configure the USART1 module
if( USART2_Config(&usart2) != Execution_Succesfull )
return Execution_Failed;
// Receive the I2C data
if( HAL_I2C_Slave_Receive_IT(&ic21, &i2c_rc_buffer, 1) != HAL_OK )
for(;;);
for(;;)
{
if(i2c_received)
{
sprintf(buffer, "I2C data received %lu B\n\r", i2c_data);
if( HAL_UART_Transmit_DMA(&usart2, (const uint8_t *)buffer, sizeof(buffer)) != HAL_OK )
for(;;);
// Receive the SPI data
if( HAL_SPI_Receive_IT(&spi1, &spi_rc_buffer, 1) != HAL_OK )
for(;;);
else
{
i2c_data = 0;
i2c_received = 0;
}
}
}
return Execution_Succesfull;
}
ReturnStatus SystemClock_Config(Clock_Source_t clk)
{
RCC_OscInitTypeDef osc_init;
RCC_ClkInitTypeDef clk_init;
memset(&osc_init, 0, sizeof(osc_init));
memset(&clk_init, 0, sizeof(clk_init));
switch (clk)
{
case HSI_16:
break;
case HSI_8:
osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSI;
osc_init.HSIState = RCC_HSI_ON;
if ( HAL_RCC_OscConfig(&osc_init) != HAL_OK )
return Execution_Failed;
clk_init.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
clk_init.AHBCLKDivider = RCC_SYSCLK_DIV2;
clk_init.APB1CLKDivider = RCC_HCLK_DIV2;
clk_init.APB2CLKDivider = RCC_HCLK_DIV1;
if ( HAL_RCC_ClockConfig(&clk_init, FLASH_ACR_LATENCY_0WS) != HAL_OK )
return Execution_Failed;
break;
case HSE_4:
osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE;
osc_init.HSEState = RCC_HSE_ON; // YOU HAVE TO CHECK ON THE SCHEMATIC WHETHER HSE IS BYPASSED OR NOT!!!
if ( HAL_RCC_OscConfig(&osc_init) != HAL_OK )
return Execution_Failed;
clk_init.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
clk_init.AHBCLKDivider = RCC_SYSCLK_DIV2;
clk_init.APB1CLKDivider = RCC_HCLK_DIV2;
clk_init.APB2CLKDivider = RCC_HCLK_DIV2;
if ( HAL_RCC_ClockConfig(&clk_init, FLASH_ACR_LATENCY_0WS) != HAL_OK )
return Execution_Failed;
__HAL_RCC_HSI_DISABLE(); //Disable HSI to reduce Power Consumption.
break;
case HSE_2:
osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE;
osc_init.HSEState = RCC_HSE_ON; // YOU HAVE TO CHECK ON THE SCHEMATIC WHETHER HSE IS BYPASSED OR NOT!!!
if ( HAL_RCC_OscConfig(&osc_init) != HAL_OK )
return Execution_Failed;
clk_init.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
clk_init.AHBCLKDivider = RCC_SYSCLK_DIV4;
clk_init.APB1CLKDivider = RCC_HCLK_DIV2;
clk_init.APB2CLKDivider = RCC_HCLK_DIV2;
if ( HAL_RCC_ClockConfig(&clk_init, FLASH_ACR_LATENCY_0WS) != HAL_OK )
return Execution_Failed;
__HAL_RCC_HSI_DISABLE(); //Disable HSI to reduce Power Consumption.
break;
case PLL_84:
#if !NO_PLL
osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE;
osc_init.HSEState = RCC_HSE_ON;
// Enable the clock to the power ccontroller.
__HAL_RCC_PWR_CLK_ENABLE();
// Set regulator voltage scale as 1.
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
// Turn on the over drive mode.
osc_init.PLL.PLLState = RCC_PLL_ON;
osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSE;
osc_init.PLL.PLLM = 16;
osc_init.PLL.PLLN = 336;
osc_init.PLL.PLLP = 2;
osc_init.PLL.PLLQ = 7;
if ( HAL_RCC_OscConfig(&osc_init) != HAL_OK )
return Execution_Failed;
clk_init.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
clk_init.AHBCLKDivider = RCC_SYSCLK_DIV2;
clk_init.APB1CLKDivider = RCC_HCLK_DIV2;
clk_init.APB2CLKDivider = RCC_HCLK_DIV2;
if ( HAL_RCC_ClockConfig(&clk_init, FLASH_ACR_LATENCY_0WS) != HAL_OK )
return Execution_Failed;
__HAL_RCC_HSI_DISABLE(); //Disable HSI to reduce Power Consumption.
break;
#endif
case PLL_42:
#if !NO_PLL
osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSE;
osc_init.HSEState = RCC_HSE_ON;
// Enable the clock to the power ccontroller.
__HAL_RCC_PWR_CLK_ENABLE();
// Set regulator voltage scale as 1.
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
// Turn on the over drive mode.
osc_init.PLL.PLLState = RCC_PLL_ON;
osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSE;
osc_init.PLL.PLLM = 16;
osc_init.PLL.PLLN = 336;
osc_init.PLL.PLLP = 2;
osc_init.PLL.PLLQ = 7;
if ( HAL_RCC_OscConfig(&osc_init) != HAL_OK )
return Execution_Failed;
clk_init.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
clk_init.AHBCLKDivider = RCC_SYSCLK_DIV4;
clk_init.APB1CLKDivider = RCC_HCLK_DIV2;
clk_init.APB2CLKDivider = RCC_HCLK_DIV2;
if ( HAL_RCC_ClockConfig(&clk_init, FLASH_ACR_LATENCY_0WS) != HAL_OK )
return Execution_Failed;
__HAL_RCC_HSI_DISABLE(); //Disable HSI to reduce Power Consumption.
break;
#endif
default:
}
return Execution_Succesfull;
}
ReturnStatus I2C_Config(I2C_HandleTypeDef *i2c, I2C_TypeDef *Instance)
{
memset(i2c, 0, sizeof(*i2c));
i2c->Instance = Instance;
i2c->Init.ClockSpeed = 100000;
i2c->Init.DutyCycle = I2C_DUTYCYCLE_2;
i2c->Init.OwnAddress1 = 0x50 << 1;
i2c->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
i2c->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
i2c->Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
i2c->Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if( HAL_I2C_Init(i2c) != HAL_OK )
return Execution_Failed;
return Execution_Succesfull;
}
ReturnStatus SPI_Config(SPI_HandleTypeDef *spi, SPI_TypeDef *Instance, PURPOSE role)
{
memset(spi, 0, sizeof(*spi));
spi->Instance = Instance;
spi->Init.Mode = (role == MASTER) ? SPI_MODE_MASTER : SPI_MODE_SLAVE;
spi->Init.Direction = SPI_DIRECTION_2LINES;
spi->Init.DataSize = SPI_DATASIZE_8BIT;
spi->Init.CLKPolarity = SPI_POLARITY_LOW;
spi->Init.CLKPhase = SPI_PHASE_1EDGE;
spi->Init.NSS = SPI_NSS_SOFT;
if(role == MASTER)
spi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
spi->Init.FirstBit = SPI_FIRSTBIT_MSB;
spi->Init.TIMode = SPI_TIMODE_DISABLE;
spi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
if( HAL_SPI_Init(spi) != HAL_OK )
return Execution_Failed;
return Execution_Succesfull;
}
ReturnStatus SPI_SS_Config(GPIO_InitTypeDef *sspin)
{
memset(sspin, 0, sizeof(*sspin));
// Enable the clock to GPIOA
__HAL_RCC_GPIOA_CLK_ENABLE();
sspin->Pin = GPIO_PIN_4;
sspin->Speed = GPIO_SPEED_FREQ_LOW;
sspin->Pull = GPIO_NOPULL;
sspin->Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOA, sspin);
return Execution_Succesfull;
}
ReturnStatus DMA_Config(void)
{
// Enable the clock for DMA1
__HAL_RCC_DMA1_CLK_ENABLE();
// Enable the interrupt of DMA1_Stream6 and set its priority
HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
return Execution_Succesfull;
}
ReturnStatus USART2_Config(UART_HandleTypeDef *uart_handle)
{
memset(uart_handle, 0, sizeof(*uart_handle));
uart_handle->Instance = USART2;
uart_handle->Init.BaudRate = 115200;
uart_handle->Init.HwFlowCtl = UART_HWCONTROL_NONE;
uart_handle->Init.Mode = UART_MODE_TX;
uart_handle->Init.OverSampling = UART_OVERSAMPLING_16;
uart_handle->Init.Parity = UART_PARITY_NONE;
uart_handle->Init.StopBits = UART_STOPBITS_1;
uart_handle->Init.WordLength = UART_WORDLENGTH_8B;
if( HAL_UART_Init(uart_handle) != HAL_OK )
return Execution_Failed;
return Execution_Succesfull;
}
void Delay(uint32_t ms)
{
DWT->CTRL |= (1 << 0); // Enable the DTW counter of the CortexM4
uint32_t start = DWT->CYCCNT;
uint32_t ticks = ms * (HAL_RCC_GetHCLKFreq() / 1000);
while ((DWT->CYCCNT - start) < ticks);
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (spi_data < 99999)
{
// Receive the SPI data
data_buffer[spi_data++] = spi_rc_buffer;
if( HAL_SPI_Receive_IT(&spi1, &spi_rc_buffer, 1) != HAL_OK )
for(;;);
}
else
{
data_buffer[spi_data++] = spi_rc_buffer;
sprintf(buffer, "SPI data received %lu B\n\r", spi_data);
if( HAL_UART_Transmit_DMA(&usart2, (const uint8_t *)buffer, sizeof(buffer)) != HAL_OK )
for(;;);
}
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if (i2c_data < 99999)
{
// Receive the I2C data
data_buffer[i2c_data++] = i2c_rc_buffer;
if( HAL_I2C_Slave_Receive_IT(&ic21, &i2c_rc_buffer, 1) != HAL_OK )
for(;;);
}
else
{
data_buffer[i2c_data++] = i2c_rc_buffer;
i2c_received = 1;
if( HAL_I2C_Slave_Transmit(&ic21, &i2c_received, 1, HAL_MAX_DELAY) != HAL_OK )
for(;;);
}
}
/*
* msp.c
*
* Created on: Mar 14, 2026
* Author: georgegio
*/
#include "my_main.h"
extern DMA_HandleTypeDef dma_usart2_tx;
void HAL_MspInit(void)
{
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
// Enable necessary IRQs
HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(MemoryManagement_IRQn);
HAL_NVIC_EnableIRQ(BusFault_IRQn);
HAL_NVIC_EnableIRQ(UsageFault_IRQn);
}
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
UNUSED(hi2c);
GPIO_InitTypeDef gpio_i2c;
memset(&gpio_i2c, 0, sizeof(gpio_i2c));
// Enable the I2C and GPIO PORT B clock.
__HAL_RCC_I2C1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
gpio_i2c.Pin = GPIO_PIN_6 | GPIO_PIN_7;
gpio_i2c.Mode = GPIO_MODE_AF_OD;
gpio_i2c.Pull = GPIO_NOPULL;
gpio_i2c.Speed = GPIO_SPEED_FREQ_LOW;
gpio_i2c.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &gpio_i2c);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
}
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
UNUSED(hspi);
GPIO_InitTypeDef gpio_spi;
memset(&gpio_spi, 0, sizeof(gpio_spi));
// Enable the SPI and GPIO PORT A clock.
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
gpio_spi.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
gpio_spi.Mode = GPIO_MODE_AF_PP;
gpio_spi.Pull = GPIO_NOPULL;
gpio_spi.Speed = GPIO_SPEED_FREQ_LOW;
gpio_spi.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &gpio_spi);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_uart;
memset(&gpio_uart, 0, sizeof(gpio_uart));
// Enable the UART and GPIO PORTB clock.
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
gpio_uart.Pin = GPIO_PIN_2 | GPIO_PIN_3;
gpio_uart.Speed = GPIO_SPEED_FREQ_LOW;
gpio_uart.Mode = GPIO_MODE_AF_PP;
gpio_uart.Alternate = GPIO_AF7_USART2;
gpio_uart.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &gpio_uart);
HAL_NVIC_EnableIRQ(USART2_IRQn);
HAL_NVIC_EnableIRQ(USART2_IRQn);
memset(&dma_usart2_tx, 0, sizeof(dma_usart2_tx));
dma_usart2_tx.Instance = DMA1_Stream6;
dma_usart2_tx.Init.Channel = DMA_CHANNEL_4;
dma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
dma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
dma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
dma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
dma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
dma_usart2_tx.Init.Mode = DMA_NORMAL;
dma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
dma_usart2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&dma_usart2_tx) != HAL_OK)
{
for(;;);
}
__HAL_LINKDMA(huart,hdmatx,dma_usart2_tx);
}
/*
* it.c
*
* Created on: Mar 14, 2026
* Author: georgegio
*/
#include "my_main.h"
extern DMA_HandleTypeDef dma_usart2_tx;
extern UART_HandleTypeDef usart2;
extern I2C_HandleTypeDef ic21;
extern SPI_HandleTypeDef spi1;
void SysTick_Handler(void)
{
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
}
void DMA1_Stream6_IRQHandler(void)
{
HAL_DMA_IRQHandler(&dma_usart2_tx);
}
void USART2_IRQHandler(void)
{
HAL_UART_IRQHandler(&usart2);
}
void SPI1_IRQHandler(void)
{
HAL_SPI_IRQHandler(&spi1);
}
void I2C1_EV_IRQHandler(void)
{
HAL_I2C_EV_IRQHandler(&ic21);
}
void I2C1_ER_IRQHandler(void)
{
HAL_I2C_ER_IRQHandler(&ic21);
}
void NMI_Handler(void)
{
for(;;);
}
void HardFault_Handler(void)
{
// Halt execution, when HardFault error occurs.
for(;;);
}
void MemManage_Handler(void)
{
// Halt execution, when MemManage error occurs.
for(;;);
}
void BusFault_Handler(void)
{
// Halt execution, when BusFault error occurs.
for(;;);
}
void UsageFault_Handler(void)
{
// Halt execution, when UsageFault error occurs.
for(;;);
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
for(;;);
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
for(;;);
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
for(;;);
}


Add a video of the output (know more)
Add a photo of your hardware showing the output.

Add a Screenshot of the serial terminal showing the output.