cancel
Showing results for 
Search instead for 
Did you mean: 

How to use I2C with DMA - Touch Sensor

Linkpad
Associate III

Hi,

I have had partial success implementing DMA with I2C as below but the only way I can receive the data "val" is by adding a HAL_Delay of 1uS and the "val" is shown as an incorrect value. Is there anyway to both do the DMA send and receive without the HAL_Delay to give the correct value?

 

uint8_t CS816T_GetRegByte(uint8_t regAddr) {
	uint8_t val;
	if(HAL_I2C_GetState(CS816T_ui2c) == HAL_I2C_STATE_READY)
		HAL_I2C_Master_Transmit_DMA(CS816T_ui2c,CS816T_I2C_ADDR << 1, &regAddr, 1);
        HAL_Delay(1);
	    HAL_I2C_Master_Receive_DMA(CS816T_ui2c,CS816T_I2C_ADDR << 1, &val, 1);

	    return val;
}

 

 without the HAL_Delay(1) I just get a blank value returned?

 

 

4 REPLIES 4
TDK
Guru

DMA occurs in the background. Wait until the operation is complete and the I2C bus is free again before you continue.

 

Or since you're blocking execution here anyway, use blocking functions.

 

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

The nearest I got with my 0.75 brain is below which outputs a value but when there is no input on the i2c sensor the value doesn't go back to zero?

	if(HAL_I2C_GetState(CS816T_ui2c) == HAL_I2C_STATE_READY)
	HAL_I2C_Master_Transmit_DMA(CS816T_ui2c,CS816T_I2C_ADDR << 1, &regAddr, 1);

	 while (HAL_I2C_GetState(CS816T_ui2c) != HAL_I2C_STATE_READY)
	    {
	    }

	if(HAL_I2C_GetState(CS816T_ui2c) == HAL_I2C_STATE_READY)
	HAL_I2C_Master_Receive_DMA(CS816T_ui2c, CS816T_I2C_ADDR << 1, &val ,1);

	 while (HAL_I2C_GetState(CS816T_ui2c) != HAL_I2C_STATE_READY)
	    {
	    }

	return val;

I even tried replacing the 2 parts with this (Write & Read command in 1 command):-

HAL_I2C_Mem_Read(CS816T_ui2c, CS816T_I2C_ADDR<< 1,  &reg, 1, &val, sizeof(val), HAL_MAX_DELAY)

this returned a value but wasn't again correct as the binary values all seem to be out by 1 digit so I am at a loss as too how anyone is supposed to successfully implement the HAL I2C functions...

 

TDK
Guru

> this returned a value but wasn't again correct as the binary values all seem to be out by 1 digit

Be more specific.

Why do you think the values it returns are wrong? What values is it returning? What do you think it should be returning instead?

Get a logic analyzer and look at the values on the bus. Likely the HAL function is returning what it's seeing on the lines.

 

We have limited insight into what you are doing. The HAL_I2C_* functions work. Why they aren't working for you is likely something to do with your specific setup or situation, so it's best to provide enough detail to determine what the problem is if you want a solution.

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

Hi, I managed to successfully get the mem read function to work by blocking as shown below (for anyone else out there):-

uint8_t CS816T_GetRegByte(uint8_t regAddr) {

	uint16_t reg = regAddr;
	uint8_t val = 0;
  	if(HAL_I2C_GetState(CS816T_ui2c) == HAL_I2C_STATE_READY)
	if(HAL_I2C_Mem_Read(CS816T_ui2c, CS816T_I2C_ADDR<< 1, reg , I2C_MEMADD_SIZE_8BIT, &val, sizeof(val),100) == HAL_OK)
	if(HAL_I2C_GetState(CS816T_ui2c) != HAL_I2C_STATE_READY)
	val = 0;
	return val;

 This I tested with an i2c touch sensor and will give readings and zero the value when not in use, I found the use of initiating the variable 'val' with '0' ensured no corrupted values.