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