2014-08-13 08:46 AM
I am trying to transmit multiple bytes on I2C bus using dma. In the sample code I am trying to send 3 bytes. I see on my scope that three bytes are being sent but the problem is that the first byte gets sent three times. I am also able to recive three bytes without any problem but agian nothing gets written in the location of the second and third byte.
I generated the code using CubeMX but modified the main file to send/recieve at the right time. My master transmitter code looks like this:#define
i2c_buffer_size 3
uint8_t
i2c_data_buffer[i2c_buffer_size] = {0x03,0x10,
0xFF};
uint16_t slaveAddress =
0x05;
....
void
cmd_send_i2c(
){
HAL_I2C_Master_Transmit_DMA(&hi2c1, slaveAddress,i2c_data_buffer, i2c_buffer_size);
}
My slave receiver code looks like this
</p>
int
</b>
main(
void
){
/* Reset of all peripherals, Initializes the Flash interface and the
Systick
. */
HAL_Init();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
while
(1)
{
if
(HAL_I2C_GetState(&hi2c1)==
HAL_I2C_STATE_READY
)
HAL_I2C_Slave_Receive_DMA(&hi2c1,(
uint8_t
*) i2c_data_buffer,i2c_buffer_size);
}
return
0;}
and the receive call back function is
void
HAL_I2C_SlaveRxCpltCallback(
I2C_HandleTypeDef
*hi2c){
LED_RED_TOGGLE;
if
(i2c_data_buffer[0] == 0x03)
LED_BLUE_TOGGLE;
if
(i2c_data_buffer[1] == 0x10)
LED_GREEN_TOGGLE;
return
;
}
I am checking the i2c_data_buffer using a debugger and the value for i2c_data_buffer[0] is correct but i2c_data_buffer[1] is not correct.
Thanks in advance for the help!
2014-08-13 08:57 AM
Can you show the contents of the HAL_DMA_Init() method? I'm assuming the DMA is not configured to auto increment the memory location or your data width is perhaps incorrect.
2014-08-13 08:58 AM
MX_I2C1_Init as well please
2014-08-13 10:01 AM
Please see below functions HAL_DMA_Init, MX_I2C1_Init and MX_DMA_Init. I am also adding the code snippet for the DMA peripheral initialization from the function HAL_I2C_MspInit.
Thanks a lot for looking at this code!HAL_StatusTypeDef
HAL_DMA_Init(
DMA_HandleTypeDef
*hdma) {uint32_t
tmp = 0;/* Check the DMA handle allocation */
if
(hdma == NULL)
{return
HAL_ERROR
;
}/* Check the parameters */
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance
)); assert_param(IS_DMA_DIRECTION(hdma->Init
.Direction
)); assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init
.PeriphInc
)); assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init
.MemInc
)); assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init
.PeriphDataAlignment
)); assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init
.MemDataAlignment
)); assert_param(IS_DMA_MODE(hdma->Init
.Mode
)); assert_param(IS_DMA_PRIORITY(hdma->Init
.Priority
));/* Change DMA peripheral state */
hdma->State
=HAL_DMA_STATE_BUSY
;
/* Get the CR register value */
tmp = hdma->Instance
->CCR
;/* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR bits */
tmp &= ((uint32_t
)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \ DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \ DMA_CCR_DIR));/* Prepare the DMA Channel configuration */
tmp |= hdma->Init
.Direction
| hdma->Init
.PeriphInc
| hdma->Init
.MemInc
| hdma->Init
.PeriphDataAlignment
| hdma->Init
.MemDataAlignment
| hdma->Init
.Mode
| hdma->Init
.Priority
;/* Write to DMA Channel CR register */
hdma->Instance
->CCR
= tmp;/*
Initialise
the error code */ hdma->ErrorCode
= HAL_DMA_ERROR_NONE;/* Initialize the DMA state*/
hdma->State
=HAL_DMA_STATE_READY
;
return
HAL_OK
;
}/* I2C1
init
function */void
MX_I2C1_Init(
void
)
{ hi2c1.Instance
= I2C1; hi2c1.Init
.Timing
= 0x2000090E; hi2c1.Init
.OwnAddress1
= 0x05; hi2c1.Init
.AddressingMode
= I2C_ADDRESSINGMODE_7BIT; hi2c1.Init
.DualAddressMode
= I2C_DUALADDRESS_DISABLED; hi2c1.Init
.OwnAddress2
= 0; hi2c1.Init
.OwnAddress2Masks
= I2C_OA2_NOMASK; hi2c1.Init
.GeneralCallMode
= I2C_GENERALCALL_DISABLED; hi2c1.Init
.NoStretchMode
= I2C_NOSTRETCH_DISABLED; HAL_I2C_Init(&hi2c1);/**Configure
Analogue
filter */ HAL_I2CEx_AnalogFilter_Config(&hi2c1, I2C_ANALOGFILTER_ENABLED); }void
MX_DMA_Init(
void
)
{/* DMA controller clock enable */
__DMA1_CLK_ENABLE();
/* DMA interrupt
init
*//* Sets the priority grouping field */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
HAL_NVIC_SetPriority(DMA1_Channel6_IRQn
, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn
);
/* Sets the priority grouping field */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
HAL_NVIC_SetPriority(DMA1_Channel7_IRQn
, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn
); } From HAL_I2C_MspInithdma_i2c1_tx.
Instance
= DMA1_Channel6;
hdma_i2c1_tx.Init
.
Direction
= DMA_MEMORY_TO_PERIPH;
hdma_i2c1_tx.Init
.
PeriphInc
= DMA_PINC_DISABLE;
hdma_i2c1_tx.Init
.
MemInc
= DMA_MINC_DISABLE;
hdma_i2c1_tx.Init
.
PeriphDataAlignment
= DMA_PDATAALIGN_BYTE;
hdma_i2c1_tx.Init
.
MemDataAlignment
= DMA_MDATAALIGN_BYTE;
hdma_i2c1_tx.Init
.
Mode
= DMA_NORMAL;
hdma_i2c1_tx.Init
.
Priority
= DMA_PRIORITY_LOW;
HAL_DMA_Init(&hdma_i2c1_tx);2014-08-13 10:09 AM
As I thought, the DMA is not configured to increment the memory location. Change
hdma_i2c1_tx.Init.MemInc = DMA_MINC_DISABLE;
To:
hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
And you should be good.
2014-08-13 10:16 AM
Thanks a lot for the help. It is working fine now!