I2C ADXL345
I2C ADXL345示例实现了I2C驱动与I2C设备通信,通过I2C向ADXL345发送数据,并从ADXL345读取数据。
I2C ADXL345示例的源代码和工程文件位于SDK_Folder\projects\peripheral\i2c\i2c_master_adxl345,其中工程文件在文件夹Keil_5下。
代码理解
示例工程流程图如图 16所示:
- 配置I2C模块。
I2C详细配置参数请参考I2C DMA UART。此示例工程中,speed选择I2C_SPEED_400K,addressing_mode选择I2C_ADDRESSINGMODE_7BIT,general_call_mode选择I2C_GENERALCALL_DISABLE。
- I2C硬件初始化。
void hal_i2c_msp_init(i2c_handle_t *p_i2c) { gpio_init_t gpio_config = GPIO_DEFAULT_CONFIG; /*---------------------- Configure the I2C Pins -----------------------*/ gpio_config.mode = GPIO_MODE_MUX; gpio_config.pull = GPIO_PULLUP; gpio_config.mux = I2C_GPIO_MUX; gpio_config.pin = I2C_SCL_PIN | I2C_SDA_PIN; hal_gpio_init(I2C_GPIO_PORT, &gpio_config); (1) /*------------------- Configure the DMA for I2C ------------------*/ /* Configure the DMA handler for Transmission process */ s_dma_tx_handle.channel = DMA_Channel0; s_dma_tx_handle.init.src_request = DMA_REQUEST_MEM; s_dma_tx_handle.init.dst_request = p_i2c->p_instance == I2C0) ? DMA_REQUEST_I2C0_TX : DMA_REQUEST_I2C1_TX; s_dma_tx_handle.init.direction = DMA_MEMORY_TO_PERIPH; s_dma_tx_handle.init.src_increment = DMA_SRC_INCREMENT; (2) s_dma_tx_handle.init.dst_increment = DMA_DST_NO_CHANGE; (3) s_dma_tx_handle.init.src_data_alignment = DMA_SDATAALIGN_BYTE; (4) s_dma_tx_handle.init.dst_data_alignment = DMA_DDATAALIGN_BYTE; (5) s_dma_tx_handle.init.mode = DMA_NORMAL; s_dma_tx_handle.init.priority = DMA_PRIORITY_LOW; hal_dma_deinit(&s_dma_tx_handle); hal_dma_init(&s_dma_tx_handle); /* Associate the initialized DMA handle to the I2C handle */ __HAL_LINKDMA(p_i2c, p_dmatx, s_dma_tx_handle); (6) /* Configure the DMA handler for reception process */ s_dma_rx_handle.channel = DMA_Channel1; s_dma_rx_handle.init.src_request = (p_i2c->p_instance == I2C0) ? DMA_REQUEST_I2C0_RX : DMA_REQUEST_I2C1_RX; s_dma_rx_handle.init.dst_request = DMA_REQUEST_MEM; s_dma_rx_handle.init.direction = DMA_PERIPH_TO_MEMORY; s_dma_rx_handle.init.src_increment = DMA_SRC_NO_CHANGE; (7) s_dma_rx_handle.init.dst_increment = DMA_DST_INCREMENT; (8) s_dma_rx_handle.init.src_data_alignment = DMA_SDATAALIGN_BYTE; (9) s_dma_rx_handle.init.dst_data_alignment = DMA_DDATAALIGN_BYTE; (10) s_dma_rx_handle.init.mode = DMA_NORMAL; s_dma_rx_handle.init.priority = DMA_PRIORITY_LOW; hal_dma_deinit(&s_dma_rx_handle); hal_dma_init(&s_dma_rx_handle); /* Associate the initialized DMA handle to the the I2C handle */ __HAL_LINKDMA(p_i2c, p_dmarx, s_dma_rx_handle); (11) /* NVIC for DMA */ hal_nvic_set_priority(DMA_IRQn, 0, 1); hal_nvic_clear_pending_irq(DMA_IRQn); hal_nvic_enable_irq(DMA_IRQn); /* NVIC for I2C */ hal_nvic_set_priority(I2C_GET_IRQNUM(p_i2c->p_instance), 0, 1); hal_nvic_clear_pending_irq(I2C_GET_IRQNUM(p_i2c->p_instance)); hal_nvic_enable_irq(I2C_GET_IRQNUM(p_i2c->p_instance));}具体流程说明如下:
(1):硬件IO初始化,将I2C映射的引脚配置为I2C模式。
(2)~(5):配置TX DMA通道源和目标的地址增长模式和传输单元位宽。I2C TX通道源为RAM内数组,地址为自增模式;目标为I2C TX FIFO地址,地址不需要增长。I2C TX通道的传输单元位宽为8 bits。
(6):将TX DMA通道句柄注册进I2C实例句柄内。
(7)~(10):配置RX DMA通道源和目标的地址增长模式和传输单元位宽。I2C RX通道源为I2C RX FIFO地址,地址不需要增长;目标为RAM内数组,地址为自增模式。I2C RX通道的传输单元位宽为8 bits。
(11):将RX DMA通道句柄注册进I2C实例句柄内。
- 用户需根据不同I2C设备在I2C驱动中实现设备的读写操作。代码如下:
void i2c_write_adxl345(uint8_t reg_addr, uint8_t *buf, uint8_t size) { uint8_t wdata[256] = {0}; wdata[0] = reg_addr; memcpy(&wdata[1], buf, size); hal_i2c_master_transmit(&g_i2c_handle, SLAVE_DEV_ADDR, wdata, size + 1, 5000); } void i2c_read_adxl345(uint8_t reg_addr, uint8_t *buf, uint8_t size) { uint8_t wdata[1] = {0}; wdata[0] = reg_addr; hal_i2c_master_transmit(&g_i2c_handle, SLAVE_DEV_ADDR, wdata, 1, 5000); hal_i2c_master_receive(&g_i2c_handle, SLAVE_DEV_ADDR, buf, size, 5000); }
测试验证
- 用GProgrammer下载i2c_master_adxl345至开发板。
- 将开发板串口连接至PC端,打开并配置GRUart。
- 在GRUart的Receive Data窗口中将会显示通过I2C向ADXL345传感器发送数据,并从ADXL345传感器读取数据并打印ADXL345数据的执行过程。