
In the previous guide (here), we saw how to configure the I2C in STM32L053 to write to slave address using DMA. Now, we shall read from a slave device using DMA.
In this guide, we shall cover the following:
- DMA initializing.
- I2C Read using DMA function.
- Code.
- Demo.
5. DMA Initializing:
We shall continue from the previous topic and we start from the i2c_init function.
Since the DMA1_Channel6 is used for I2C1_TX, we need to find another channel for the RX part.
From the reference manual of STM32L053, we can find that DMA1_Channel7 is for I2C1_RX:

Since the clock is already enabled, we shall configure the DMA.
The DMA has the following configuration:
- Memory increment mode.
- Read from peripheral (DIR=0).
- Transfer complete interrupt.

DMA1_Channel7->CCR |=DMA_CCR_MINC|DMA_CCR_TCIE;
Set the peripheral address to be RXDR of the I2C1:
DMA1_Channel7->CPAR= (uint32_t)&I2C1->RXDR;
Set CxS of Channel7 to 6 which is I2C1.
DMA_CSELR|=(0x06<<24);
Thats all for the initializing for the DMA mode.
6. I2C Read Function:
void i2_read_dma(uint8_t slav_add, uint8_t memadd, uint8_t *data, uint8_t length )
{
(slav_add=slav_add<<1);
/*Enable I2C*/
I2C1->CR1 |=I2C_CR1_PE;
/*Set slave address*/
I2C1->CR2=(slav_add<<I2C_CR2_SADD_Pos);
/*7-bit addressing*/
I2C1->CR2&=~I2C_CR2_ADD10;
/*Set number to transfer to 1 for write operation*/
I2C1->CR2|=(1<<I2C_CR2_NBYTES_Pos);
/*Set the mode to write mode*/
I2C1->CR2&=~I2C_CR2_RD_WRN;
/*Software end*/
I2C1->CR2&=~I2C_CR2_AUTOEND;
/*Generate start*/
I2C1->CR2|=I2C_CR2_START;
/*Wait until transfer is completed*/
while(!(I2C1->ISR & I2C_ISR_TC)){
/*Check if TX buffer is empty*/
if(I2C1->ISR & I2C_ISR_TXE)
{
/*send memory address*/
I2C1->TXDR = (memadd);
}
}
/*Reset I2C*/
I2C1->CR1 &=~I2C_CR1_PE;
I2C1->CR1 |=I2C_CR1_PE;
/*Enable DMA RX*/
I2C1->CR1|=I2C_CR1_RXDMAEN;
/*Set slave address*/
I2C1->CR2=(slav_add<<I2C_CR2_SADD_Pos);
/*Set mode to read operation*/
I2C1->CR2|=I2C_CR2_RD_WRN;
/*Set length to the required length*/
I2C1->CR2|=((length)<<I2C_CR2_NBYTES_Pos);
/*auto generate stop after transfer completed*/
I2C1->CR2|=I2C_CR2_AUTOEND;
DMA1_Channel7->CCR&=~DMA_CCR_EN;
while(DMA1_Channel7->CCR &DMA_CCR_EN);
DMA1_Channel7->CNDTR=length;
DMA1_Channel7->CMAR=data;
DMA1_Channel7->CCR|=DMA_CCR_EN;
I2C1->CR2|=I2C_CR2_START;
while(rx_done==0);
rx_done=0;
}
7. Code:
You may download the code from here:
8. Demo:
After uploading the code to the STM32L053, open serial terminal and set the baud to 9600 and you should get something similar to this:
Happy coding 🙂
Add Comment