打印
[应用相关]

AT32 I2C程序使用讲解

[复制链接]
1934|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
LEDyyds|  楼主 | 2024-1-12 17:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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
  
  }   
}

使用特权

评论回复
沙发
tpgf| | 2024-2-1 13:44 | 只看该作者
为什么所有型号的单片机都提倡使用io模拟iIC通讯呢

使用特权

评论回复
板凳
zljiu| | 2024-2-1 14:36 | 只看该作者
所有的方式都已经做好了  用起来是非常方便的

使用特权

评论回复
地板
tfqi| | 2024-2-1 18:38 | 只看该作者
在初始化阶段 不同的模块之间的初始化有先后顺序吗

使用特权

评论回复
5
gwsan| | 2024-2-1 19:09 | 只看该作者
为什么感觉整个程序的结构都是松松垮垮的呢

使用特权

评论回复
6
nawu| | 2024-2-1 20:17 | 只看该作者
tpgf 发表于 2024-2-1 13:44
为什么所有型号的单片机都提倡使用io模拟iIC通讯呢

是不是因为使用io模拟的iic更加稳定呢

使用特权

评论回复
7
wongjy| | 2024-7-2 16:10 | 只看该作者
tpgf 发表于 2024-2-1 13:44
为什么所有型号的单片机都提倡使用io模拟iIC通讯呢

好像是因为I2C的外设有问题,具体的没有尝试过

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

122

主题

867

帖子

1

粉丝