Skip to main content
Graduate
December 29, 2023
Question

How to use I2C with DMA - Touch Sensor

  • December 29, 2023
  • 2 replies
  • 1990 views

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?

 

 

    This topic has been closed for replies.

    2 replies

    Super User
    December 29, 2023

    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.

     

    LinkpadAuthor
    Graduate
    December 30, 2023

    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...

     

    Super User
    December 30, 2023

    > 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.

    LinkpadAuthor
    Graduate
    December 31, 2023

    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.