STM32基于软件模拟IIC进行AHT21B温湿度采集

摘要:通过学习软件IIC来进行实操AHT21B采集温湿度。

前期准备:

  • 软件:Keil 5.28,FlyMcu v0.188(烧录软件),XCOM v2.6(串口通信软件)
  • 硬件:stm32F103C8,AHT21B(温湿度采集模块),USB转TTL模块
    以下工程案例基于正点原子,请各位注意。

一、 IIC简介

1.1 IIC简介

IIC(Inter-Integrated Circuit)其实是IICBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。百度百科-IIC

IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。

在I2C总线传输过程中,将两种特定的情况定义为开始和停止条件:

  • 当SCL保持“高”时,SDA由“高”变为“低”为开始条件;
  • 当SCL保持“高”且SDA由“低”变为“高”时为停止条件。

开始和停止条件均由主控制器产生。使用硬件接口可以很容易地检测到开始和停止条件,没有这种接口的微机必须以每时钟周期至少两次对SDA取样,以检测这种变化。百度百科-IIC

在这里插入图片描述

具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式下可达 3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模式。

1.2 实现方式

目前有两种实现IIC的方式:(1)软件IIC(2)硬件IIC

  • 软件IIC

软件IIC一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。

  • 硬件IIC

硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的

1.3 实现方式对比

  • 硬件IIC的效率要远高于软件IIC
  • 软件I2C由于不受管脚限制,接口比较灵活,而硬件IIC只能在固定管脚上。
  • 硬件IIC速度比模拟快,并且可以用DMA
  • 软件IIC代码容量少且流程清晰简单

二、 AHT21B简介

2.1 简介

AHT21B数字温湿度模块是一款经过校准数字信号输出的温湿度复合传感器。它以专用的数字模块采集技术和温湿度传感技术,确保产品具有非常高的可靠性与卓越的长期稳定性。该产品具有品质卓越、响应迅速、抗干扰能力强、性价比高等优点。每个传感器都在专业的湿度校验室中进行校准,使产品达到更高的精度标准。标准I²C接口,使系统集成变得简易快捷。产品体积小、功耗低使其成为各类应用甚至最为苛刻的应用场合的最佳选择。奥松电子官网

2.2 产品特点

  • 完全标定
  • 数字输出,I²C接口
  • 优异的长期稳定性
  • 响应迅速
  • 抗干扰能力强
  • 多种配件可供选择
  • 量身定制应用方案

2.3 外观

在这里插入图片描述

在这里插入图片描述

2.4 技术参数

参数说明
供电电压DC:2-5.5V
测量范围温度:-40~+80°C; 湿度:0~100%RH
测量精度温度:±0.3℃; 湿度:±2%RH(25℃)
分辨率温度:0.01℃ 湿度:0.024%RH
输出信号I²C信号
包装吸塑盘

2.5 引脚定义

名称描述
VCC供电电压
SDA串行数据,双向口
GND电源地
SCL串行时钟,双向口

电源引脚( VDD GND)
AHT21B的供电范围为2.0-5.5V,推荐电压为3.3V,并且在VCC和GND之间必须加上去耦电容10uF,起到滤波作用。
串行时钟SCL
SCL用于微处理器与AHT21B之间的通讯同步。由于接口包含了完全静态逻辑,因而不存在最小SCL频率。
串行数据SDA
SDA引脚用于传感器的数据输入和输出。当向传感器发送命令时,SDA在串行时钟SCL的上升沿有效,且当SCL为高电平时,SDA必须保持稳定。在SCL下降沿之后,SDA值可被改变。为确保通信安全,SDA的有效时间在SCL上升沿之前,和下降沿之后应该分别延长至 TSU AND THO,当从传感器读取数据时,SDA在SCL变低以后有效(TV),且维持到下一个SCL的下降沿

在这里插入图片描述

三、 工程编写

3.1 实验要求

1.采集温湿度并进行串口输出显示

3.2 主要代码

  • main.c
int main(void)
 {	 	
    u32 CT_data[2]={0};
    volatile float  c1=0,t1=0;     
     
    delay_init();	    	 //延时函数初始化	  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    uart_init(115200);	 //串口初始化为115200
    LED_Init();			     //LED端口初始化
    temphum_init();    
	
	delay_ms(40);//刚上电,延时40ms才可以读取状态
	
	if(!((AHT20_Read_Status()&0x08)==0x08))//首先发0x71读取状态字bit[3],如果=1,为校准输出,无须初始化!!!    正常情况下读回来的状态是0x1C或者是0x18,读回来是0x80表示忙状态;
	{
        AHT20_Init(); //初始化AHT20 
	}
	while(1)
	{
        //DisableIrq(); //由于是模拟I2C,为读取数据更准确 ,读取之前禁止中断;
        delay_ms(1000);
        AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
        //AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 

        c1 = CT_data[0]*100*10/1024/1024;  //计算得到湿度值(放大了10倍)
        t1 = CT_data[1]*200*10/1024/1024-500;//计算得到温度值(放大了10倍)
        //printf("%d %d\r\n",*CT_data,*(CT_data+1));
				LED=0;
				delay_ms(500);
				LED=1;
        printf("湿度:%.1f%%\r\n",(c1/10));
        printf("温度:%.1f℃\r\n",(t1/10));
				printf("\r\n");
				delay_ms(500);

        
	 }

}
  • myiic.c
#include "myiic.h"
#include "delay.h"
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK精英STM32开发板
//IIC驱动 代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/9
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved									  
//
 
//初始化IIC
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); 	//PB6,PB7 输出高
}
//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);							   	
}
等待应答信号到来
返回值:1,接收应答成功
        0,接收应答失败
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 0;
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 1; 
}    

//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

  • temhum.c
#include "temhum.h"

//读取AHT20的状态寄存器
u8 AHT20_Read_Status(void)
{

	u8 Byte_first,flag;	
	IIC_Start();
    IIC_Send_Byte(0x71);
	flag=IIC_Wait_Ack();
	Byte_first = IIC_Read_Byte(flag);
		

	IIC_NAck();
	IIC_Stop();

	return Byte_first;
}

void AHT20_SendAC(void) //向AHT20发送AC命令
{

	IIC_Start();
	IIC_Send_Byte(0x70);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xac);//0xAC采集命令
	IIC_Wait_Ack();
	IIC_Send_Byte(0x33);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();

}

void AHT20_Init(void)   //初始化AHT20
{	
	IIC_Init();
	IIC_Start();
	IIC_Send_Byte(0x70);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xa8);//0xA8进入NOR工作模式
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();

	delay_ms(10);//延时10ms左右

	IIC_Start();
	IIC_Send_Byte(0x70);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xbe);//0xBE初始化命令,AHT20的初始化命令是0xBE,   AHT10的初始化命令是0xE1
	IIC_Wait_Ack();
	IIC_Send_Byte(0x08);//相关寄存器bit[3]置1,为校准输出
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();
	delay_ms(10);//延时10ms左右
}

void temphum_init()
{
	delay_ms(40);//刚上电,延时40ms才可以读取状态
	
    //首先发0x71读取状态字bit[3],如果=1,为校准输出,无须初始化!!!正常情况下读回来的状态是0x1C或者是0x18,读回来是0x80表示忙状态;
	if(!((AHT20_Read_Status()&0x08)==0x08))
	{
        AHT20_Init(); //初始化AHT20 
	}
}
    
void AHT20_Read_CTdata(u32 *ct) //没有CRC校验,直接读取AHT20的温度和湿度数据
{
	volatile u8  Byte_1th=0;
	volatile u8  Byte_2th=0;
	volatile u8  Byte_3th=0;
	volatile u8  Byte_4th=0;
	volatile u8  Byte_5th=0;
	volatile u8  Byte_6th=0;
	u32 RetuData = 0;
	u16 cnt = 0,flag;
	AHT20_SendAC();//向AHT20发送AC命令
	delay_ms(80);	//大约延时80ms
    cnt = 0;
	while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表示为空闲状态,若为1,表示忙状态
	{
		delay_ms(1);
		if(cnt++>=100) break;
	}
	IIC_Start();

	IIC_Send_Byte(0x71);
	flag=IIC_Wait_Ack();
	Byte_1th = IIC_Read_Byte(flag);//状态字
	//IIC_Ack();
	Byte_2th = IIC_Read_Byte(flag);//湿度
	//IIC_Ack();
	Byte_3th = IIC_Read_Byte(flag);//湿度
	//IIC_Ack();
	Byte_4th = IIC_Read_Byte(flag);//湿度/温度
	//IIC_Ack();
	Byte_5th = IIC_Read_Byte(flag);//温度
	//IIC_Ack();
	Byte_6th = IIC_Read_Byte(!flag);//温度
	//IIC_NAck();
	IIC_Stop();

	RetuData = (RetuData|Byte_2th)<<8;
	RetuData = (RetuData|Byte_3th)<<8;
	RetuData = (RetuData|Byte_4th);
	RetuData =RetuData >>4;
	ct[0] = RetuData;//湿度
	RetuData = 0;
	RetuData = (RetuData|Byte_4th)<<8;
	RetuData = (RetuData|Byte_5th)<<8;
	RetuData = (RetuData|Byte_6th);
	RetuData = RetuData&0xfffff;
	ct[1] =RetuData; //温度

}

部分代码参考基于I2C通信协议的温湿度采集

3.3 烧录

1.USB转TTL连线

stm32核心板USB转串口
PA9 (USART1-TX)RXD
PA10 (USART1-RX)TXD
3V33V3
GNDGND

跳线BOOT0为1,BOOT1为0.

2.AHT21B与STM32F103C8

AHT20STM32F10X
SCLPB6
SDAPB7
VCC3V3
GNDGND

3.4 结果展示

  • 正常室内温湿度采集

在这里插入图片描述

  • 升温采集

在这里插入图片描述

通过实验结果可以看出,AHT21B可以正常采集温湿度进行串口显示。

四、 总结

通过此次学习,我初步了解了软件IIC与硬件IIC的基本知识。通过实操AHT21B采集温湿度,学习并掌握了软件IIC的代码编写以及工程调试。其中遇到了很多问题,特别感谢我的老师和不#曾&轻听博主对我的帮助。

五、 参考资料

1.奥松官网
2.AHT21B温湿度采集-GitHub
3.基于I2C通信协议的温湿度采集
4.硬件IIC和软件IIC区别

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值