历史上的今天
返回首页

历史上的今天

今天是:2025年05月29日(星期四)

正在发生

2018年05月29日 | STM32F1驱动AM2302温湿度传感器

2018-05-29 来源:eefocus

先来个AM2302的自我介绍:

AM2302数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个AM2302传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为 4 针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。

重要的来了啊:AM2302时序图


单总线通信特殊说明: 
1.典型应用电路中建议连接线长度短于30米时用5.1K上拉电阻,大于30米时根据实际情况降低上拉电阻的阻值。 
2.使用3.3V电压供电时连接线长度不得大于30cm。否则线路压降会导致传感器供电不足,造成测量偏差。 
3.读取传感器最小间隔时间为2S;读取间隔时间小于2S,可能导致温湿度不准或通信不成功等情况。 
4.每次读出的温湿度数值是上一次测量的结果,欲获取实时数据,需连续读取两次, 建议连续多次读取传感器,且每次读取传感器间隔大于2秒即可获得准确的数据。
看到这里相信对AM2302有了一定了解了。下面开始贴出程序,共同驱动AM2302吧。
先来主函数把

  1. /*********************************************************************************** 

  2.  * 文件名  :main.c 

  3.  * 描述    :          

  4.  * 实验平台:神舟III号 

  5.  * 库版本  :ST3.5 

  6.  * 作者    :xiayufeng  xiayufeng90520@163.com  

  7.  * 博客    :http://hi.baidu.com/xiayufeng520 

  8. **********************************************************************************/  

  9. #include "stm32f10x.h"  

  10. #include "led.h"  

  11. #include "delay.h"  

  12. #include "usart1.h"  

  13. #include "am2302.h"  

  14.         

  15. AM2302_Data_TypeDef AM2302_Data;  

  16.         

  17. /*                                                

  18. ************************************************************************ 

  19. 函 数 名: int main(void) 

  20.        

  21. 功    能: 主函数 

  22.        

  23. 入口参数: None 

  24.        

  25. 返 回 值: None 

  26.          

  27. 其他说明: None 

  28.        

  29. 调用形式: None    

  30. ************************************************************************ 

  31. */  

  32. int main(void)  

  33. {  

  34.     unsigned int RH_Value,TEMP_Value;  

  35.     unsigned char RH_H,RH_L,TP_H,TP_L;  

  36.     Led_Init(); //LED初始化  

  37.     Delay_Init();//Delay初始化  

  38.     USART1_Init();//串口初始化  

  39.             

  40.     AM2302_GPIO_Config();//AM2302管脚初始化    

  41.         

  42.     while(1)  

  43.     {  

  44.         /*调用Read_AM2302读取温湿度,若成功则输出该信息*/  

  45.         if( Read_AM2302(&AM2302_Data)==SUCCESS)  

  46.         {             

  47.             //计算出实际湿度值的10倍  

  48.             RH_Value= AM2302_Data.humi_int*256 + AM2302_Data.humi_deci;  

  49.             RH_H = RH_Value/10;  

  50.             RH_L = RH_Value%10;  

  51.             //计算出时间温度值的10倍  

  52.             TEMP_Value = AM2302_Data.temp_int*256 + AM2302_Data.temp_deci;  

  53.             TP_H = TEMP_Value/10;  

  54.             TP_L = TEMP_Value%10;  

  55.             printf("\r\n读取AM2302成功!\r\n\r\n湿度为%d.%d %RH \  

  56.                             ,温度为 %d.%d℃ \r\n",RH_H,RH_L,TP_H,TP_L);//“\”表示转向一下行  

  57.         }  

  58.         else  

  59.             printf("Read AM2302 ERROR!\r\n");  

  60.                 

  61.         Led_Turn(LED2,LED_ON);  

  62.         Delay_ms(1100);  

  63.         Led_Turn(LED2,LED_OFF);  

  64.         Delay_ms(1100);  

  65.     }  

  66. }  

再来AM2302的头文件部分:


  1. #ifndef __AM2302_H  

  2. #define __AM2302_H  

  3.         

  4. #include "stm32f10x.h"  

  5. #include "delay.h"  

  6.         

  7. #define RCC_GPIO_AM2302   RCC_APB2Periph_GPIOF  

  8. #define GPIO_AM2302       GPIOF  

  9. #define PIN_AM2302        GPIO_Pin_6  

  10. #define HIGH  1  

  11. #define LOW   0  

  12.         

  13. typedef struct  

  14. {  

  15.     uint8_t  humi_int;      //湿度的整数部分  

  16.     uint8_t  humi_deci;     //湿度的小数部分  

  17.     uint8_t  temp_int;      //温度的整数部分  

  18.     uint8_t  temp_deci;     //温度的小数部分  

  19.     uint8_t  check_sum;     //校验和  

  20.                                  

  21. }AM2302_Data_TypeDef;  

  22.         

  23. //带参宏,可以像内联函数一样使用,输出高电平或低电平  

  24. #define  AM2302_DATA_OUT(a) if (a)  \  

  25.                     GPIO_SetBits(GPIO_AM2302,PIN_AM2302);\  

  26.                     else        \  

  27.                     GPIO_ResetBits(GPIO_AM2302,PIN_AM2302)  

  28.  //读取引脚的电平  

  29. #define  AM2302_DATA_IN()      GPIO_ReadInputDataBit(GPIO_AM2302,PIN_AM2302)  

  30.         

  31.         

  32. void AM2302_GPIO_Config(void);  

  33. static void AM2302_Mode_IPU(void);  

  34. static void AM2302_Mode_Out_PP(void);  

  35. uint8_t Read_AM2302(AM2302_Data_TypeDef *AM2302_Data);  

  36. static uint8_t Read_Byte(void);  

  37.         

  38. #endif /* __AM2302_H */  

最后来AM2302的实现函数部分:


  1. #include "am2302.h"  

  2.        

  3. /* 

  4.  * 函数名:AM2302_GPIO_Config 

  5.  * 描述  :配置AM2302用到的I/O口 

  6.  * 输入  :无 

  7.  * 输出  :无 

  8.  */  

  9. void AM2302_GPIO_Config(void)  

  10. {         

  11.     /*定义一个GPIO_InitTypeDef类型的结构体*/  

  12.     GPIO_InitTypeDef GPIO_InitStructure;  

  13.        

  14.     /*开启GPIOF的外设时钟*/  

  15.     RCC_APB2PeriphClockCmd( RCC_GPIO_AM2302, ENABLE);   

  16.        

  17.     /*选择要控制的GPIOF引脚*/                                                               

  18.     GPIO_InitStructure.GPIO_Pin = PIN_AM2302;     

  19.        

  20.     /*设置引脚模式为通用推挽输出*/  

  21.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     

  22.        

  23.     /*设置引脚速率为50MHz */    

  24.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   

  25.        

  26.     /*调用库函数,初始化GPIO_AM2302*/  

  27.     GPIO_Init(GPIO_AM2302, &GPIO_InitStructure);            

  28.        

  29.     /* 拉高PIN_AM2302 */  

  30.     GPIO_SetBits(GPIO_AM2302, PIN_AM2302);     

  31. }  

  32.        

  33. /* 

  34.  * 函数名:AM2302_Mode_IPU 

  35.  * 描述  :使AM2302-DATA引脚变为输入模式 

  36.  * 输入  :无 

  37.  * 输出  :无 

  38.  */  

  39. static void AM2302_Mode_IPU(void)  

  40. {  

  41.       GPIO_InitTypeDef GPIO_InitStructure;  

  42.        

  43.         /*选择要控制的GPIOD引脚*/    

  44.       GPIO_InitStructure.GPIO_Pin = PIN_AM2302;  

  45.        

  46.        /*设置引脚模式为浮空输入模式*/  

  47.       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;   

  48.        

  49.       /*调用库函数,初始化GPIOD*/  

  50.       GPIO_Init(GPIO_AM2302, &GPIO_InitStructure);     

  51. }  

  52.        

  53. /* 

  54.  * 函数名:AM2302_Mode_Out_PP 

  55.  * 描述  :使AM2302-DATA引脚变为输出模式 

  56.  * 输入  :无 

  57.  * 输出  :无 

  58.  */  

  59. static void AM2302_Mode_Out_PP(void)  

  60. {  

  61.     GPIO_InitTypeDef GPIO_InitStructure;  

  62.        

  63.         /*选择要控制的GPIOD引脚*/                                                               

  64.     GPIO_InitStructure.GPIO_Pin = PIN_AM2302;     

  65.        

  66.     /*设置引脚模式为通用推挽输出*/  

  67.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     

  68.        

  69.     /*设置引脚速率为50MHz */    

  70.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

  71.        

  72.     /*调用库函数,初始化GPIOD*/  

  73.     GPIO_Init(GPIO_AM2302, &GPIO_InitStructure);           

  74. }  

  75.        

  76.        

  77. static uint8_t Read_Byte(void)  

  78. {       

  79.        

  80.    uint8_t i, temp=0;  

  81.        

  82.      for(i=0;i<8;i++)      

  83.      {  

  84.             

  85.        /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/   

  86.         while(AM2302_DATA_IN()==Bit_RESET);  

  87.                 

  88.          /*AM2302 以22~30us的高电平表示“0”,以68~75us高电平表示“1”, 

  89.              通过检测60us后的电平即可区别这两个状态*/  

  90.        

  91.          Delay_us(5); //延时50us              

  92.            

  93.           if(AM2302_DATA_IN()==Bit_SET)//60us后仍为高电平表示数据“1”  

  94.            {  

  95.               /*轮询直到从机发出的剩余的 30us 高电平结束*/  

  96.                  while(AM2302_DATA_IN()==Bit_SET);  

  97.        

  98.                  temp|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1   

  99.                    

  100.            }  

  101.            else  //60us后为低电平表示数据“0”  

  102.            {                 

  103.               temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0  

  104.            }  

  105.      }  

  106.      return temp;  

  107. }  

  108.        

  109. uint8_t Read_AM2302(AM2302_Data_TypeDef *AM2302_Data)  

  110. {    

  111.     /*输出模式*/  

  112.    AM2302_Mode_Out_PP();  

  113.    /*主机拉低*/  

  114.    AM2302_DATA_OUT(LOW);  

  115.    /*延时2ms*/  

  116.    Delay_ms(2);  

  117.        

  118.    /*总线拉高 主机延时30us*/  

  119.    AM2302_DATA_OUT(HIGH);   

  120.        

  121.    Delay_us(3);   //延时30us  

  122.           

  123.     /*主机设为输入 判断从机响应信号*/  

  124.    AM2302_Mode_IPU();  

  125.        

  126.  /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/    

  127.    if(AM2302_DATA_IN()==Bit_RESET)   //T !     

  128.     {  

  129.          

  130.            

  131.       /*轮询直到从机发出 的80us 低电平 响应信号结束*/   

  132.         while(AM2302_DATA_IN()==Bit_RESET);  

  133.                 

  134.       /*轮询直到从机发出的 80us 高电平 标置信号结束*/  

  135.         while(AM2302_DATA_IN()==Bit_SET);  

  136.        

  137.       /*开始接收数据*/    

  138.          AM2302_Data->humi_int= Read_Byte();  

  139.                                        

  140.          AM2302_Data->humi_deci= Read_Byte();  

  141.                        

  142.          AM2302_Data->temp_int= Read_Byte();  

  143.        

  144.          AM2302_Data->temp_deci= Read_Byte();  

  145.                                

  146.          AM2302_Data->check_sum= Read_Byte();  

  147.                                                  

  148.        

  149.          /*读取结束,引脚改为输出模式*/  

  150.     AM2302_Mode_Out_PP();  

  151.         /*主机拉高*/  

  152.         AM2302_DATA_OUT(HIGH);  

  153.        

  154.         /*检查读取的数据是否正确*/  

  155.         if(AM2302_Data->check_sum == AM2302_Data->humi_int + AM2302_Data->humi_deci + AM2302_Data->temp_int+ AM2302_Data->temp_deci)  

  156.           return SUCCESS;  

  157.         else  

  158.           return ERROR;  

  159.    }  

  160.    else  

  161.    {          

  162.             return ERROR;  

  163.      }  

  164.           

  165. }  

  166.        

  167. /*************************************END OF FILE******************************/  


好了,到此AM2302驱动算完全结束了。
驱动AM2302的过程磕磕绊绊的,分享出来希望和我一样走在STM32路上的人能少走些弯路。
给一个新鲜器件时,一定要先仔细研究它的手册,深刻的探究器件的要求,这样才能在实现器件功能上少遭受一些挫折,也算这次驱动AM2302温湿度传感器的一些心得吧。


推荐阅读

史海拾趣

ARCOLECTRICSWITCHES公司的发展小趣事

随着电子行业的不断发展,ARCOLECTRIC SWITCHES公司意识到单打独斗已经无法满足市场需求。因此,公司积极寻求与上下游企业的合作,共同打造完善的产业链。通过与供应商建立长期稳定的合作关系,确保原材料的稳定供应;与下游企业开展深度合作,共同研发新产品、开拓新市场。这种合作共赢的模式使得ARCOLECTRIC SWITCHES公司在行业中更具竞争力。

依必安派特(ebmpapst)公司的发展小趣事

1996年,依必安派特在上海外高桥保税区设立了其在中国的首个据点——依必安派特风机(上海)有限公司。最初,它仅作为销售为主的贸易公司,为中国市场提供德国制造的风机和电机产品。然而,随着中国市场的快速增长和需求的不断变化,依必安派特意识到仅仅作为贸易公司已无法满足市场需求。于是,在2000年,依必安派特电气(上海)有限公司正式成立,开始在上海本地生产风机和电机,标志着依必安派特从贸易到制造的转变。

ELESTA GmbH公司的发展小趣事

1997年,ELESTA继电器有限公司正式成立,专注于制造符合IEC 61810-3标准的强制导向触点继电器。这一战略举措进一步巩固了ELESTA在电子继电器领域的领先地位,并为公司的长期发展奠定了坚实的基础。

CONTEC公司的发展小趣事

2008年,对于CONTEC公司来说是具有里程碑意义的一年。这一年,公司建成了康泰产业园(一期),并进一步加强了研发和生产能力。同时,公司技术中心被省发改委等部门确定为省认定企业技术中心,这标志着公司在技术研发和创新方面得到了官方认可和支持。随着产业园的投入使用,公司的生产规模和效率得到了显著提升。

Glenair公司的发展小趣事
首先检查电路的供电电源是否正常,确保电压稳定且符合电路要求。
Acculin Inc公司的发展小趣事

为了进一步提升技术水平,Acculin Inc积极寻求与国际知名企业的合作。通过与欧洲一家半导体制造商的技术交流,公司引进了一条先进的生产线,并成功将其应用于新型芯片的制造中。这一合作不仅提升了Acculin的生产效率,也使其在芯片制造领域达到了国际先进水平。

问答坊 | AI 解惑

这几天系统短消息有问题

这几天系统自动发的短消息有问题,打不开,不知道是什么原因,望管理员更正。…

查看全部问答>

关于FLASH的分盘的问题

请问 1 在哪里设置并修改FLASH的盘符 2 我有一个UI程序。放在MLC中,但是我不想可见,应该怎么做。 3 如何设置应用程序让其开机后自动运行?…

查看全部问答>

关于KernelIoControl和InterruptInitialize函数

请问这两个函数KernelIoControl和InterruptInitialize函数的区别是什么呢?? 个人理解:先用KernelIoControl申请中断号           然后利用InterruptInitialize把 (从KernelIoControl申请的)中断号与事件相关联 ...…

查看全部问答>

lan91c96网卡芯片ID(4#)读不对,总是0

我的平台式wince5.0+pxa270,在初始化网卡芯片过程中,读完0x3300的标志后,读ID#,结果每次读不对,大部分时候是0,有时候是其他的错误如15等。都不知道什么原因,网卡相关管脚配置应该都是对的,有谁遇到过吗…

查看全部问答>

ADS1.2 调用strtoul(str,NULL,0,NULL),地址0的内容会被更改

strtoul的定义: unsigned long strtoul(const char *str, char **endptr, int requestedbase, int *ret) 可见ADS1.2会把NULL指针指向地址0,但是地址0放着复位向量,怎么样才能不改变0地址的内容呢?(当然在调用的时候可以不用NULL,而定义一个 ...…

查看全部问答>

WINCE 使用USB HUB的问题

2440开发板,WINCE5.0系统, 启动系统后插入优盘或USB HUB 或鼠标都可以正常识别,当先插入优盘或USB HUB 再通电启动系统也可以识别,问题是先插入USB HUB再通电启动系统后,USB HUB无法识别,必需要再插拔一下才行,请问 怎么解决这个问题!…

查看全部问答>

windows高级程序设计

windows高级程序设计QQ群9033880…

查看全部问答>

新手的小程序,欢迎拍砖和扔鸡蛋!!!

以下小程序在EK-STM32实验板上通过.顺便那位高手推荐一块最小12位的Led显示芯片,2块zlg7290c成本太高最好系内建晶震和I2C接口,谢谢!!#include "stm32f10x_lib.h"void RCC_Configuration(void);void GPIO_Configuration(voi ...…

查看全部问答>

美国GE露点传感器的铭牌信息揭露

美国GE露点传感器 量    程:-110℃~+20℃ 精确度:-65~40℃露点温度是±2℃                -80~-66℃露点温度是±3℃ 工作环境:温度:-40℃~+60℃&nb ...…

查看全部问答>

低功率纳米技术及其它敏感器件的交流与直流测量方法的比较——大电阻的测量1

目前,大于10 kΩ的被测电阻是对电流噪声和输入负载误差[1]方面的挑战。因电压噪声与测试对象的电阻成比例,电流噪声就会非常明显。在锁定放大器法和直流反转系统中,电流噪声来自于测量电路,在流经测试对象和/或引线电阻时会产生额外的直流和交 ...…

查看全部问答>