AT32官方BSP里面提供了I2C的使用例程,极大的方便了我们使用I2C,代码位置:BSP里面的project\at_start_f403a\examples\i2c,该路径下有以下四个demo:
communication_dma -- 使用DMA进行传输
communication_int -- 使用中断进行传输
communication_poll -- 使用轮寻的方式传输
eeprom -- eeprom 使用示例
关于I2C传输数据的流程,官方已经封装了一个应用层,用户无需再关心数据传输流程,只需要调用相关接口初始化I2C,然后再调用相关接口传输数据即可,在以下两个文件中:
i2c_application.c
i2c_application.h
i2c_config -- 调用此函数初始化I2C
i2c_lowlevel_init -- 用户实现这个函数,完成I2C底层初始化,例如初始化GPIO、时钟、中断、DMA等
i2c_master_transmit -- 主机发送数据-轮询方式
i2c_master_receive -- 主机接收数据-轮询方式
i2c_slave_transmit -- 从机发送数据-轮询方式
i2c_slave_receive -- 从机接收数据-轮询方式
i2c_master_transmit_int -- 主机发送数据-中断方式
i2c_master_receive_int -- 主机接收数据-中断方式
i2c_slave_transmit_int -- 从机发送数据-中断方式
i2c_slave_receive_int -- 从机接收数据-中断方式
i2c_master_transmit_dma -- 主机发送数据-DMA方式
i2c_master_receive_dma -- 主机接收数据-DMA方式
i2c_slave_transmit_dma -- 从机发送数据-DMA方式
i2c_slave_receive_dma -- 从机接收数据-DMA方式
i2c_memory_write -- 写数据到EEPROM-轮询方式
i2c_memory_write_int -- 写数据到EEPROM-中断方式
i2c_memory_write_dma -- 写数据到EEPROM-DMA方式
i2c_memory_read -- 从EEPROM读数据-轮询方式
i2c_memory_read_int -- 从EEPROM读数据-中断方式
i2c_memory_read_dma -- 从EEPROM读数据-DMA方式
我们对communication_dma例程代码进行举例分析
1. 首先实现i2c_lowlevel_init函数,实现I2C的底层初始化
void i2c_lowlevel_init(i2c_handle_type* hi2c)
{
gpio_init_type gpio_initstructure;
if(hi2c->i2cx == I2Cx_PORT)
{
/* i2c periph clock enable */
crm_periph_clock_enable(I2Cx_CLK, TRUE);
crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE);
crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);
/* gpio configuration */
gpio_initstructure.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
gpio_initstructure.gpio_pull = GPIO_PULL_UP;
gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
/* configure i2c pins: scl */
gpio_initstructure.gpio_pins = I2Cx_SCL_PIN;
gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_initstructure);
/* configure i2c pins: sda */
gpio_initstructure.gpio_pins = I2Cx_SDA_PIN;
gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_initstructure);
/* configure and enable i2c dma channel interrupt */
nvic_irq_enable(I2Cx_DMA_TX_IRQn, 0, 0);
nvic_irq_enable(I2Cx_DMA_RX_IRQn, 0, 0);
/* i2c dma tx and rx channels configuration */
/* enable the dma clock */
crm_periph_clock_enable(I2Cx_DMA_CLK, TRUE);
/* i2c dma channel configuration */
dma_reset(hi2c->dma_tx_channel);
dma_reset(hi2c->dma_rx_channel);
hi2c->dma_tx_channel = I2Cx_DMA_TX_CHANNEL;
hi2c->dma_rx_channel = I2Cx_DMA_RX_CHANNEL;
dma_default_para_init(&hi2c->dma_init_struct);
hi2c->dma_init_struct.peripheral_inc_enable = FALSE;
hi2c->dma_init_struct.memory_inc_enable = TRUE;
hi2c->dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
hi2c->dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
hi2c->dma_init_struct.loop_mode_enable = FALSE;
hi2c->dma_init_struct.priority = DMA_PRIORITY_LOW;
hi2c->dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
dma_init(hi2c->dma_tx_channel, &hi2c->dma_init_struct);
dma_init(hi2c->dma_rx_channel, &hi2c->dma_init_struct);
i2c_init(hi2c->i2cx, I2C_FSMODE_DUTY_2_1, I2Cx_SPEED);
i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, I2Cx_ADDRESS);
}
}
2. 实现中断函数
void I2Cx_DMA_RX_IRQHandler(void)
{
i2c_dma_rx_irq_handler(&hi2cx);
}
void I2Cx_DMA_TX_IRQHandler(void)
{
i2c_dma_tx_irq_handler(&hi2cx);
}
3.调用i2c_config初始化i2c,调用i2c_master_transmit_dma、i2c_slave_receive_dma进行数据收发
int main(void)
{
i2c_status_type i2c_status;
/* config nvic priority group */
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
system_clock_config();
at32_board_init();
hi2cx.i2cx = I2Cx_PORT;
i2c_config(&hi2cx);
while(1)
{
#if defined (MASTER_BOARD)
/* wait for key USER_BUTTON press before starting the communication */
while(at32_button_press() != USER_BUTTON)
{
}
/* start the request reception process */
if((i2c_status = i2c_master_transmit_dma(&hi2cx, I2Cx_ADDRESS, tx_buf, BUF_SIZE, I2C_TIMEOUT)) != I2C_OK)
{
error_handler(i2c_status);
}
/* wait for the communication to end */
if(i2c_wait_end(&hi2cx, I2C_TIMEOUT) != I2C_OK)
{
error_handler(i2c_status);
}
delay_ms(10);
/* start the request reception process */
if((i2c_status = i2c_master_receive_dma(&hi2cx, I2Cx_ADDRESS, rx_buf, BUF_SIZE, I2C_TIMEOUT)) != I2C_OK)
{
error_handler(i2c_status);
}
/* wait for the communication to end */
if(i2c_wait_end(&hi2cx, I2C_TIMEOUT) != I2C_OK)
{
error_handler(i2c_status);
}
if(buffer_compare(tx_buf, rx_buf, BUF_SIZE) == 0)
{
at32_led_on(LED3);
}
else
{
error_handler(i2c_status);
}
#else
/* wait for key USER_BUTTON press before starting the communication */
while(at32_button_press() != USER_BUTTON)
{
}
/* start the transmission process */
if((i2c_status = i2c_slave_receive_dma(&hi2cx, rx_buf, BUF_SIZE, I2C_TIMEOUT)) != I2C_OK)
{
error_handler(i2c_status);
}
/* wait for the communication to end */
if(i2c_wait_end(&hi2cx, I2C_TIMEOUT) != I2C_OK)
{
error_handler(i2c_status);
}
if((i2c_status = i2c_slave_transmit_dma(&hi2cx, tx_buf, BUF_SIZE, I2C_TIMEOUT)) != I2C_OK)
{
error_handler(i2c_status);
}
/* wait for the communication to end */
if(i2c_wait_end(&hi2cx, I2C_TIMEOUT) != I2C_OK)
{
error_handler(i2c_status);
}
if(buffer_compare(tx_buf, rx_buf, BUF_SIZE) == 0)
{
at32_led_on(LED3);
}
else
{
error_handler(i2c_status);
}
#endif
}
}
|