你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32模拟IIC驱动sht30温湿度传感器经验分享

[复制链接]
攻城狮Melo 发布时间:2023-5-1 17:34
最近有在使用sht30这个传感器,相比于新手常用的dht11传感器,sht30更精确,自己花了半小时调好了
所以拿出来分享给大家。

sht30外观

bffa7cbd45b741099fa0e90f0f74a175.jpg

驱动不是自己写的, 是采用CSDN上的一位朋友的 ,这里贴出来的代码不是本文的主旨, 重要是教会大

家如何配置各个端口(因为是模拟iic 所以大多数引脚都模拟为SCLK和DATA)。

串口输出图

52ceba75d06043168c6b13052ebbc1e2.png


驱动代码


sht30.c

  1. #include "SHT30.h"

  2. #define write 0
  3. #define read  1

  4. //IIC总线接口定义
  5. #define SCL PAout(5)
  6. #define SDA_OUT PAout(6)
  7. #define SDA_IN PAin(6)
  8. #define IIC_INPUT_MODE_SET()  {GPIOA->CRL&=0XF0FFFFFF;GPIOA->CRL|=8<<24;}
  9. #define IIC_OUTPUT_MODE_SET() {GPIOA->CRL&=0XF0FFFFFF;GPIOA->CRL|=3<<24;}


  10. float humiture[4];
  11. u8 humiture_buff1[20];

  12. void SHT30_Init(void)
  13. {
  14.         GPIO_InitTypeDef GPIO_InitStructure;
  15.         //RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟
  16.         RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOA, ENABLE );       
  17.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
  18.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
  19.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  20.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  21.         SCL=1;
  22.         SDA_OUT=1;
  23. }       
  24. /*主机发送ACK*/
  25. void IIC_ACK(void)
  26. {
  27.   IIC_OUTPUT_MODE_SET();
  28.   SCL=0;
  29.   delay_us(2);
  30.   SDA_OUT=0;
  31.   delay_us(2);     
  32.   SCL=1;
  33.   delay_us(2);                  
  34.   SCL=0;                     
  35.   delay_us(1);   
  36. }
  37. /*主机不发送ACK*/
  38. void IIC_NACK(void)
  39. {
  40.   IIC_OUTPUT_MODE_SET();
  41.   SCL=0;
  42.   delay_us(2);
  43.   SDA_OUT=1;
  44.   delay_us(2);      
  45.   SCL=1;
  46.   delay_us(2);                  
  47.   SCL=0;                     
  48.   delay_us(1);   
  49. }
  50. /*主机等待从机的ACK*/
  51. u8 IIC_wait_ACK(void)
  52. {
  53.     u8 t = 200;
  54.     IIC_OUTPUT_MODE_SET();
  55.     SDA_OUT=1;//8位发送完后释放数据线,准备接收应答位
  56.     delay_us(1);
  57.     SCL=0;
  58.     delay_us(1);
  59.     IIC_INPUT_MODE_SET();
  60.     delay_us(1);
  61.     while(SDA_IN)//等待SHT30应答
  62.     {
  63.         t--;
  64.         delay_us(1);
  65.         if(t==0)
  66.         {
  67.           SCL=0;
  68.           return 1;
  69.         }
  70.         delay_us(1);
  71.     }
  72.     delay_us(1);      
  73.     SCL=1;
  74.     delay_us(1);
  75.     SCL=0;            
  76.     delay_us(1);   
  77.     return 0;       
  78. }
  79. /*******************************************************************
  80. 功能:启动I2C总线,即发送I2C起始条件.  
  81. ********************************************************************/
  82. void IIC_Start(void)
  83. {
  84.   IIC_OUTPUT_MODE_SET();
  85.   SDA_OUT=1;
  86.   SCL=1;
  87.   delay_us(4);       
  88.   SDA_OUT=0;
  89.   delay_us(4);
  90.   SCL=0;
  91. }

  92. /*******************************************************************
  93. 功能:结束I2C总线,即发送I2C结束条件.  
  94. ********************************************************************/
  95. void IIC_Stop(void)
  96. {
  97.         IIC_OUTPUT_MODE_SET();
  98.         SCL=0;
  99.         SDA_OUT=0;  
  100.         delay_us(4);       
  101.         SCL=1;
  102.         delay_us(4);
  103.         SDA_OUT=1;
  104.         delay_us(4);
  105. }

  106. /*******************************************************************
  107. 字节数据发送函数               
  108. 函数原型: void  SendByte(UCHAR c);
  109. 功能:将数据c发送出去,可以是地址,也可以是数据
  110. ********************************************************************/
  111. void  IIC_SendByte(u8 byte)
  112. {
  113.         u8  BitCnt;
  114.         IIC_OUTPUT_MODE_SET();
  115.         SCL=0;
  116.         for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位
  117.         {
  118.                 if(byte&0x80) SDA_OUT=1;//判断发送位
  119.                 else SDA_OUT=0;
  120.                 byte<<=1;
  121.                 delay_us(2);
  122.                 SCL=1;
  123.                 delay_us(2);
  124.                 SCL=0;
  125.                 delay_us(2);
  126.         }
  127. }
  128. /*******************************************************************
  129. 字节数据接收函数               
  130. 函数原型: UCHAR  RcvByte();
  131. 功能: 用来接收从器件传来的数据  
  132. ********************************************************************/   
  133. u8 IIC_RcvByte(void)
  134. {
  135.   u8 retc;
  136.   u8 BitCnt;
  137.   retc=0;
  138.   IIC_INPUT_MODE_SET();//置数据线为输入方式
  139.   delay_us(1);                    
  140.   for(BitCnt=0;BitCnt<8;BitCnt++)
  141.   {  
  142.         SCL=0;//置时钟线为低,准备接收数据位
  143.         delay_us(2);               
  144.         SCL=1;//置时钟线为高使数据线上数据有效               
  145.         retc=retc<<1;
  146.         if(SDA_IN) retc |=1;//读数据位,接收的数据位放入retc中
  147.         delay_us(1);
  148.   }
  149.   SCL=0;   
  150.   return(retc);
  151. }
  152. /*******************************************************************
  153. 温湿度获取函数               
  154. 函数原型: SHT30_read_result(u8 addr);
  155. 功能: 用来接收从器件采集并合成温湿度
  156. ********************************************************************/
  157. void SHT30_read_result(u8 addr)
  158. {
  159.         u16 tem,hum;
  160.         u16 buff[6];
  161.         float Temperature=0;
  162.         float Humidity=0;
  163.        
  164.         IIC_Start();
  165.         IIC_SendByte(addr<<1 | write);//写7位I2C设备地址加0作为写取位,1为读取位
  166.         IIC_wait_ACK();
  167.         IIC_SendByte(0x2C);
  168.         IIC_wait_ACK();
  169.         IIC_SendByte(0x06);
  170.         IIC_wait_ACK();
  171.         IIC_Stop();
  172.         delay_ms(50);
  173.         IIC_Start();
  174.         IIC_SendByte(addr<<1 | read);//写7位I2C设备地址加0作为写取位,1为读取位
  175.         if(IIC_wait_ACK()==0)
  176.         {
  177.                 buff[0]=IIC_RcvByte();
  178.                 IIC_ACK();
  179.                 buff[1]=IIC_RcvByte();
  180.                 IIC_ACK();
  181.                 buff[2]=IIC_RcvByte();
  182.                 IIC_ACK();
  183.                 buff[3]=IIC_RcvByte();
  184.                 IIC_ACK();
  185.                 buff[4]=IIC_RcvByte();
  186.                 IIC_ACK();
  187.                 buff[5]=IIC_RcvByte();
  188.                 IIC_NACK();
  189.                 IIC_Stop();
  190.         }
  191.        
  192.         tem = ((buff[0]<<8) | buff[1]);//温度拼接
  193.         hum = ((buff[3]<<8) | buff[4]);//湿度拼接
  194.        
  195.         /*转换实际温度*/
  196.         Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)
  197.         Humidity= (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)
  198.        
  199.         if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据
  200.         {
  201. //                humiture[0]=Temperature;
  202. //                humiture[2]=Humidity;
  203.                 sprintf(humiture_buff1,"%6.2f*C %6.2f%%",Temperature,Humidity);//111.01*C 100.01%(保留2位小数)
  204.         }
  205.         printf("温湿度:%s\n",humiture_buff1);
  206.         hum=0;
  207.         tem=0;
  208. }

复制代码


sht30.h
  1. #ifndef SHT30_H
  2. #define SHT30_H
  3. #include "delay.h"
  4. #include "sys.h"
  5. #include "stdio.h"
  6. #include "usart.h"
  7. #include "string.h"

  8. extern u8 humiture_buff1[20];

  9. void SHT30_Init(void);
  10. void IIC_ACK(void);
  11. void IIC_NACK(void);
  12. u8 IIC_wait_ACK(void);
  13. void IIC_Start(void);
  14. void IIC_Stop(void);
  15. void IIC_SendByte(u8 byte);
  16. u8 IIC_RcvByte(void);
  17. void SHT30_read_result(u8 addr);

  18. #endif

复制代码


主函数(while循环可以写个测试的printf)

  1. #include "delay.h"
  2. #include "sys.h"
  3. #include "usart.h"
  4. #include "SHT30.h"
  5.          

  6. int main(void)
  7. {
  8.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
  9.         delay_init();                     //延时函数初始化         
  10.         uart_init(9600);                 //串口初始化为9600
  11.         SHT30_Init();
  12.         while(1)
  13.         {
  14.         //printf("123456");
  15.         SHT30_read_result(0x44);
  16.         delay_ms(300);       
  17.        
  18.         }
  19. }
复制代码


代码实测能用 ,直接复制即可, 但是如果想改端口继续往下看。

6774c10dea2042098e99e8631077a6d7.png


上图红色框选的是换端口所有需要改变的地方 这里漏框了上面的几个宏定义, 上面几个也要改。

2e802c2982f548c4beeccdef58986892.png

GPIOA->CRL&=0XF0FFFFFF;理解为 清零了32位数据中的4位
GPIOA->CRL|=8<<24;理解为置位了32位中的(24,25,26,27)的值

46cf89261805482cad2f5e489dc4d963.png

2674b0d15ec04fb5bd7d02e88244a690.png

edd016c6192946cc96302a02c4e43e61.png

上面两副图来自stm32中文手册 ,意思很明了, 有两个寄存器用来配置io口模式,CRL配置GPIO0-7, CRH配置GPIO8-15,第三副图是教你具体怎么配置,按照手册就可以选择配置你想用的端口了。
————————————————
版权声明:文某9
如有侵权请联系删除



收藏 评论0 发布时间:2023-5-1 17:34

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版