2025-03-29 9:43 AM
Hi,
I am very new to the whole STM32 environment.
I recently ordered an STM32WL-Board with which I wanted to create a bare-metal code for an I2C Master transmission via DMA. I was able to get it to work without DMA but I struggle with setting up the whole DMA stuff. My code is following:
#include "main.h"
#include "stdbool.h"
void I2C1_write_byte_data(uint8_t add, uint8_t reg, uint8_t data){
bool transmissionstate = false; //define transmission state
uint8_t buffer[2] = {reg,data}; //define buffer data
DMA1_Channel6->CMAR = (uint32_t)buffer; //set the memory address for the data to transmit
DMA1_Channel6->CPAR = (uint32_t)&I2C1->TXDR; //set peripheral address for the data to transmit
DMA1_Channel6->CNDTR = 2; //set the number of bytes to be received
DMA1_Channel6->CCR |= (1 << 0); //enable DMA
I2C1->CR2 |= (add << 1); //set the I2C address (shifted, 7-bit address)
I2C1->CR2 &= ~ (1 << 11); //set the addressing mode to 7-bit
I2C1->CR2 |= (2 << 16); //set the data to be transmitted to 2 bytes
I2C1->CR2|= (1<< 25); //generate stop condition automatically
I2C1->CR2 |= (1 << 13); //start the transmission
}
void I2C1_init() {
RCC->AHB2ENR |= (1 << 1); //Enable GPIOB Peripheral clock
GPIOB->MODER &= ~(3 << 12); //Reset alternate function for PB6
GPIOB->MODER &= ~(3 << 14); //Reset alternate function for PB7
GPIOB->MODER |= (2 << 12); //Set alternate function for PB6
GPIOB->MODER |= (2 << 14); //Set alternate function for PB7
GPIOB->AFR[0] &= ~(15 << 24); //Reset AF4 (I2C1_SCL) for PB6
GPIOB->AFR[0] &= ~(15 << 28); //Reset AF4 (I2C1_SDA) for PB7
GPIOB->AFR[0] |= (4 << 24); //Set AF4 (I2C1_SCL) for PB6
GPIOB->AFR[0] |= (4 << 28); //Set AF4 (I2C1_SDA) for PB7
GPIOB->OTYPER |= (1 << 6); //Set PB6 to open drain
GPIOB->OTYPER |= (1 << 7); //Set PB7 to open drain
RCC->APB1ENR1 |= (1 << 21); //Enable I2C1 clock
I2C1->CR1 &= ~(1 << 0); //Disable peripheral
I2C1->CR1 |= (1 << 14); //Enable transmission via DMA
RCC->CCIPR |= (1 << 12); //Set clock source of I2C1 to SYSCLK (16MHz from high speed internal)
I2C1->TIMINGR |= (1 << 28); //set PRESC of I2C1
I2C1->TIMINGR |= (4 << 20); //set SCLDEL of I2C1
I2C1->TIMINGR |= (2 << 16); //set SDADEL if I2C1
I2C1->TIMINGR |= (195 << 8); //set SCLH of I2C1
I2C1->TIMINGR |= (199 << 0); //set SCLL of I2C1
I2C1->CR1 |= (1 << 0); //Enable peripheral
RCC->AHB1ENR |= (1 << 0); //Enable DMA-Mux1
DMA1_Channel6->CCR &= ~(1 << 0); //disable DMA
DMA1_Channel6->CCR |= (1 << 7); //Enable memory address increment
DMA1_Channel6->CCR |= (1 << 4); // Memory -> Peripheral Mode
}
int main(void)
{
I2C1_init();
I2C1_write_byte_data(0x70,0,170); //address,register,data
while (1)
{
/* USER CODE END WHILE */
}
}
When I analyze the output, I can see that only the address is being transmitted. According to my code, there should be sent one more byte named "register" and one more named as "data". Since the address transmission does still take place without DMA, I highly assume that my DMA configuration is wrong/incomplete.
I could not find much information on the internet related to this series of uC. Since the I²C configuration differs from other, more popular boards, I was unable to find some useful documentation regarding my problem.
Can someone give me any advice?
Thanks in advance
2025-03-29 1:29 PM
HAL_I2C_* functions work correctly. Maybe use those instead.