[原创] 【AT32WB415测评】04 软硬件IIC获取AHT20温湿度传感器数据及扩展测试界面

秦天qintian0303   2022-8-20 12:12 楼主

04 软硬件IIC获取AHT20温湿度传感器数据及扩展测试界面

前言

        为了多层次的测评该开发板,通过SPI驱动TFT以便将不同测评环节记录并通过液晶屏显示,到目前为止已体验时钟配置、IO口操作、SPI接口等部分。

目标

        设计开发板测试界面;

        完成IIC获取AHT20温湿度传感器数据,并在对应测试界面显示。

实现

1、测试界面设计

        在完成TFT初始化后基本会是一个单色的界面显示,最好是黑色,这个时候点亮背光后不会出现异常闪烁的现象。

        根据流程这个时候应该是一个欢迎界面;

        通过操作(欢迎界面中长按或者短按按键)进入菜单界面,这里是各测试模块的选择,通过短按进行各菜单切换,长按进入各子菜单;

        子菜单1把LED模式操作放在第一位,通过短按进行LED模式切换,长按返回菜单界面;

        子菜单2设计成温湿度大气压力显示界面,也是本章节要进行驱动设计的主要显示界面;

        子菜单3待定;

        等等;

 

        在LED操作章节已经实现了按键状态的采集(长按或者短按),实现界面操作本质就是按键状态在不同界面下的识别操作,以及各界面下的静态动态显示。

具体效果如下:

         WeChat_20220820115748.gif 点击上图查看Gif动图

 

2、模拟IIC获取AHT20

        硬件IIC之前先通过软件IIC来验证连接及传感器的状态,IIC其实就是两个引脚的IO状态来模拟时序,通过IO口的高低电平及上升下降沿来完美模拟时序。

官方提供的启动代码不用动,直接配置IO口就可以了,本开发板对应的IIC接口是PB7和PB6,注意PB7同时是红灯的控制引脚。

IO口配置配置代码:

#define IIC1_RCU_GPIOB_clock    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE)
#define IIC1_SDA_INITOut        IIC1_SDA_GPIO_OutConfig()
#define IIC1_SDA_INITIn         IIC1_SDA_GPIO_InConfig()
#define IIC1_SDA_SET            gpio_bits_set(GPIOB,GPIO_PINS_7)                  
#define IIC1_SDA_RESET          gpio_bits_reset(GPIOB,GPIO_PINS_7)
#define IIC1_ReadSDA            gpio_input_data_bit_read(GPIOB, GPIO_PINS_7)

#define IIC1_SCL_INITOut        IIC1_SCL_GPIO_OutConfig()
#define IIC1_SCL_SET            gpio_bits_set(GPIOB,GPIO_PINS_6)                  
#define IIC1_SCL_RESET          gpio_bits_reset(GPIOB,GPIO_PINS_6)

void IIC1_SDA_GPIO_OutConfig(void)
{
  gpio_init_type gpio_init_struct;
  IIC1_RCU_GPIOB_clock;

  gpio_default_para_init(&gpio_init_struct);
  gpio_init_struct.gpio_drive_strength  = GPIO_DRIVE_STRENGTH_MAXIMUM;
  gpio_init_struct.gpio_out_type        = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode            = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins            = GPIO_PINS_7;
  gpio_init_struct.gpio_pull            = GPIO_PULL_UP;
  gpio_init(GPIOB, &gpio_init_struct);
}

void IIC1_SDA_GPIO_InConfig(void)
{
  gpio_init_type gpio_init_struct;
  IIC1_RCU_GPIOB_clock;

  gpio_default_para_init(&gpio_init_struct);
  gpio_init_struct.gpio_mode            = GPIO_MODE_INPUT;
  gpio_init_struct.gpio_pins            = GPIO_PINS_7;
  gpio_init_struct.gpio_pull            = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);
}

void IIC1_IOInit(void)
{
  gpio_init_type gpio_init_struct;
  IIC1_RCU_GPIOB_clock;
  
  gpio_default_para_init(&gpio_init_struct);

  gpio_init_struct.gpio_drive_strength  = GPIO_DRIVE_STRENGTH_MAXIMUM;
  gpio_init_struct.gpio_out_type        = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode            = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins            = GPIO_PINS_6|GPIO_PINS_7;
  gpio_init_struct.gpio_pull            = GPIO_PULL_UP;
  gpio_init(GPIOB, &gpio_init_struct);
  
  IIC1_SDA_SET;
  IIC1_SCL_SET;

}

 

模拟IIC时序代码:

//******************************************************************************
//* 函数名称  : IIC1_IIC_Start()                                                     
//* 函数描述  : I2C1开始信号                                                      
//* 输入参数  :                                                                  
//* 参数描述  :                                                                  
//* 输出参数  : 无                                                               
//* 返回值    : 无                                                             
//******************************************************************************     
void IIC1_IIC_Start(void)
{ 
  IIC1_SDA_SET;
  delay_us(8);
  IIC1_SCL_SET;
  delay_us(14);
  IIC1_SDA_RESET;
  delay_us(14);
  IIC1_SCL_RESET;
  delay_us(14);
}

//******************************************************************************
//* 函数名称  : IIC1_IIC_Stop(void)                                                 
//* 函数描述  : IIC停止信号                                                    
//* 输入参数  :                                                                  
//* 参数描述  :                                                                  
//* 输出参数  : 无                                                              
//* 返回值    : 无                                                              
//******************************************************************************     
void IIC1_IIC_Stop(void)
{
  IIC1_SDA_RESET;
  delay_us(14);
  IIC1_SCL_SET; 
  delay_us(8);
  IIC1_SDA_SET;
  delay_us(14);
}

//******************************************************************************
//* 函数名称  : IIC1_SendACK(uint8_t ack)                                    
//* 函数描述  : 发送应答信号                                                    
//* 输入参数  :ack (0:ACK 1:NAK)                                                
//* 参数描述  :                                                                 
//* 输出参数  : 无                                                               
//* 返回值    : 无                                                               
//******************************************************************************     
void IIC1_SendACK(uint8_t ack)  
{ 
  IIC1_SDA_INITOut;
  if(ack == 0)
  IIC1_SDA_RESET;                                                              //写应答信号 
  else
  IIC1_SDA_SET;  
  delay_us(14);
  IIC1_SCL_SET;                                                                //拉高时钟线  
  delay_us(14);                                                           //延时  
  IIC1_SCL_RESET;                                                              //拉低时钟线  
  delay_us(14);                                                           //延时    
} 

//******************************************************************************
//* 函数名称  : uint8_t IIC1_RecvACK(void)                                        
//* 函数描述  : 接收应答信号                                                   
//* 输入参数  :                                                                 
//* 参数描述  :                                                                  
//* 输出参数  : RecvACK                                                        
//* 返回值    : 无                                                              
//******************************************************************************  
uint8_t IIC1_RecvACK(void)  
{  
  
  uint8_t RecvACK;
    
  IIC1_SDA_INITIn;                                                    //SDA接口为输入
  delay_us(8);
  IIC1_SCL_SET;                                                                //拉高时钟线  
  delay_us(8);                                                           //延时  
  RecvACK = IIC1_ReadSDA;                                                      //读应答信号  
  IIC1_SCL_RESET;                                                              //拉低时钟线  
  delay_us(8);                                                           //延时 
  IIC1_SDA_INITOut;
    
  return RecvACK;
    
} 

//******************************************************************************
//* 函数名称  : void IIC1_SendByte(uint8_t dat)                                
//* 函数描述  : 向设备发送一个数据                                         
//* 输入参数  :                                                                  
//* 参数描述  :                                                                 
//* 输出参数  : 无                                                               
//* 返回值    : 无                                                               
//****************************************************************************** 
uint8_t IIC1_SendByte(uint8_t dat)  
{  
  uint8_t datsendbit;
  uint8_t RecvACK;
   
  for (uint8_t i=0; i<8; i++)                                                   //8位计数器  
  {  
    datsendbit = ((dat & 0x80) >> 7);
    dat <<= 1;                                                                  //移出数据的最高位 
    if(datsendbit == 1)
    {
      IIC1_SDA_SET;
    }
    if(datsendbit == 0)
    {
      IIC1_SDA_RESET;
    }                                                                           //送数据口 
    delay_us(8);
    IIC1_SCL_SET;                                                               //拉高时钟线  
    delay_us(8);                                                                //延时  
    IIC1_SCL_RESET;                                                             //拉低时钟线
    delay_us(8);  
  } 
  RecvACK = IIC1_RecvACK();
  return RecvACK;  
} 

//******************************************************************************
//* 函数名称  : IIC1_RecvByte()                                           
//* 函数描述  : IIC1接收一个数据                                                
//* 输入参数  :dat                                                               
//* 参数描述  :                                                                  
//* 输出参数  : 无                                                               
//* 返回值    : 无                                                               
//******************************************************************************
uint8_t IIC1_RecvByte(void)  
{    
  uint8_t RecvDat = 0;
  
  IIC1_SDA_INITIn; 
  for (uint8_t i=0; i<8; i++)                                                   //8位计数器  
  {  
    RecvDat <<= 1;
    IIC1_SCL_SET;                                                               //拉高时钟线  
    delay_us(10);                                                               //延时 
    RecvDat |= (IIC1_ReadSDA);
    IIC1_SCL_RESET;                                                             //拉低时钟线  
    delay_us(10);                                                               //延时   
  }
  IIC1_SDA_INITOut;
  return RecvDat; 
      
}

//******************************************************************************
//* 函数名称  : void IIC1_SendByte(uint8_t dat)                                
//* 函数描述  : IIC1向设备发送多个数据                                         
//* 输入参数  :                                                                  
//* 参数描述  :                                                                 
//* 输出参数  : 无                                                               
//* 返回值    : 无                                                               
//******************************************************************************

void IIC1_SendBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr)  
{  
  uint8_t ack = 0;
  IIC1_IIC_Start();
  IIC1_SendByte(dev_addr<<1);
  
  for(uint8_t i = 0; i < len; i++) 
  {
    ack = IIC1_SendByte(*(dat+i));
  }
  IIC1_IIC_Stop();
}


//******************************************************************************
//* 函数名称  : IIC1_SendBytes                               
//* 函数描述  : IIC1从设备接收多个数据                                         
//* 输入参数  :                                                                  
//* 参数描述  :                                                                 
//* 输出参数  : 无                                                               
//* 返回值    : 无                                                               
//******************************************************************************  
void IIC1_RecvBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr)  
{  
  IIC1_IIC_Start();
  IIC1_SendByte((dev_addr<<1)+1);
  
  for(uint8_t i = 0; i < len; i++) 
  {
    *(dat+i) = IIC1_RecvByte();
    
    if(i == (len - 1))
    {
      IIC1_SendACK(1);
    }
    else
    {
      IIC1_SendACK(0);
    }
  }
  IIC1_IIC_Stop();
}

 

3、硬件IIC获取AHT20

        参考开发板IICdemo例程进行初始化配置,雅特力的IIC例程中有完整的时序判断定位,非常有助于直接定位失败位置,查找原因。雅特力的官网有一个IIC的配置工具,不过不包含本次开发板的芯片,挺遗憾的。直接引用官方的i2c_application.c,不过遗憾的是并没有调通,单独移植过来也是一样,一直是发送地址错误,大神可以帮忙指导一下,有可能也是传感器的问题,在进行驱动编写是如果IIC发送地址后发送寄存器需要重新开始,才能接受数据,不过这个传感器不用发送寄存器地址直接接受,尝试了还就也没有实现。

 

实际效果:

WeChat_20220820120942

 

 

 

 

在爱好的道路上不断前进,在生活的迷雾中播撒光引

回复评论 (3)

其它的没怎么看明白,但是这显示屏那是真的好!

点赞  2022-8-20 20:28
引用: lugl4313820 发表于 2022-8-20 20:28 其它的没怎么看明白,但是这显示屏那是真的好!

其实就是设计了前两个模块的内容,一个是LED测试,一个是温湿度显示

在爱好的道路上不断前进,在生活的迷雾中播撒光引
点赞  2022-8-20 21:12
引用: lugl4313820 发表于 2022-8-20 20:28 其它的没怎么看明白,但是这显示屏那是真的好!

屏其实算是比较细腻的,1.54寸的屏分辨率是240*240的

在爱好的道路上不断前进,在生活的迷雾中播撒光引
点赞  2022-8-20 21:13
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复