完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、 IIC简介
1.1 IIC简介 IIC(Inter-Integrated Circuit)其实是IICBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。百度百科-IIC IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。 在I2C总线传输过程中,将两种特定的情况定义为开始和停止条件:
具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式下可达 3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模式。 1.2 实现方式 目前有两种实现IIC的方式:(1)软件IIC(2)硬件IIC
1.3 实现方式对比
2.1 简介 AHT21B数字温湿度模块是一款经过校准数字信号输出的温湿度复合传感器。它以专用的数字模块采集技术和温湿度传感技术,确保产品具有非常高的可靠性与卓越的长期稳定性。该产品具有品质卓越、响应迅速、抗干扰能力强、性价比高等优点。每个传感器都在专业的湿度校验室中进行校准,使产品达到更高的精度标准。标准I²C接口,使系统集成变得简易快捷。产品体积小、功耗低使其成为各类应用甚至最为苛刻的应用场合的最佳选择。 2.2 产品特点 • 完全标定 • 数字输出,I²C接口 • 优异的长期稳定性 • 响应迅速 • 抗干扰能力强 • 多种配件可供选择 • 量身定制应用方案 2.3 外观 2.4 技术参数 [tr]参数说明[/tr]
[tr]名称描述[/tr]
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 主要代码
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 %drn",*CT_data,*(CT_data+1)); LED=0; delay_ms(500); LED=1; printf("湿度:%.1f%%rn",(c1/10)); printf("温度:%.1f℃rn",(t1/10)); printf("rn"); 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; //温度 } 3.3 烧录 1.USB转TTL连线 [tr]stm32核心板USB转串口[/tr]
跳线BOOT0为1,BOOT1为0.2.AHT21B与STM32F103C8 [tr]AHT20STM32F10X[/tr]
通过实验结果可以看出,AHT21B可以正常采集温湿度进行串口显示。 四、 总结 通过此次学习,我初步了解了软件IIC与硬件IIC的基本知识。通过实操AHT21B采集温湿度,学习并掌握了软件IIC的代码编写以及工程调试。 |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2955 浏览 16 评论
3455 浏览 1 评论
8987 浏览 16 评论
4050 浏览 18 评论
1102浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1857浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 05:40 , Processed in 1.153099 second(s), Total 50, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号