cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WLE I2C-Master unable to get DMA to work

manuelambaum
Associate

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

1 REPLY 1
TDK
Guru

HAL_I2C_* functions work correctly. Maybe use those instead.

If you feel a post has answered your question, please click "Accept as Solution".