[STM32F1]

SHT10温度和湿度

[复制链接]
997|9
手机看帖
扫描二维码
随时随地手机跟帖
Jessicakjdsl|  楼主 | 2016-11-23 19:22 | 显示全部楼层 |阅读模式
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "usart1.h"
#include "stdio.h"
/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/
#define SDA_H()         GPIO_SetBits(GPIOB,GPIO_Pin_0)
#define SDA_L()         GPIO_ResetBits(GPIOB,GPIO_Pin_0)
#define SCK_H()         GPIO_SetBits(GPIOB,GPIO_Pin_1)
#define SCK_L()         GPIO_ResetBits(GPIOB,GPIO_Pin_1)
//读SDA数据
#define SDA_R()         GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)

/* Private macro -------------------------------------------------------------*/
#define noACK 0         //无应答
#define ACK   1         //应答

#define STATUS_REG_W    0x06   //000   0011    0
#define STATUS_REG_R    0x07   //000   0011    1
#define MEASURE_TEMP    0x03   //000   0001    1
#define MEASURE_HUMI    0x05   //000   0010    1
#define RESET           0x1e   //000   1111    0

/* Private variables ---------------------------------------------------------*/
enum {TEMP,HUMI};
uint8_t Test_Timetick = 0;
uint16_t Test_Counter = 0;
/* Private function prototypes -----------------------------------------------*/
void RCC_Config(void);
void USART1_Config(void);
void SHT10_Config(void);
void SHT10_SDAIn(void);
void SHT10_SDAOut(void);
void SHT10_Delay(void);
uint8_t SHT10_WriteByte(uint8_t value);
uint8_t SHT10_ReadByte(uint8_t Ack);
void SHT10_Start(void);
void SHT10_ConReset(void);
uint8_t SHT10_Measure(uint16_t* pValue, uint8_t* pCheckSum, uint8_t mode);
void SHT10_Cal(uint16_t Temp,uint16_t Hum, float* pTempValue,float* pHumValue);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  主程序
  * @param  无
  * @retval 无
  */
int main(void)
{
    //温度结果  16bit
    uint16_t TempValue;
    //湿度结果 16bit
    uint16_t HumValue;
    //温度转换结果
    float TempResult;
    //湿度转换结果
    float HumResult;
    //校验值
    uint8_t CheckValue = 0x00;
   
    //错误
    uint8_t error = 0x00;
   
    //初始化RCC
    RCC_Config();
    USART1_Config();
    SHT10_Config();
   
    printf("Start\n");
    while(1)
    {
        if(Test_Timetick)
        {
            Test_Timetick = 0;
            Test_Counter ++;
            
            //延时2000ms
            if(Test_Counter > 2000)
            {
                Test_Counter = 0;
               
                printf("启动转换!\n");
                //SHT10 连接
                SHT10_ConReset();
                //获得温度和湿度数据,16位格式
                error += SHT10_Measure(&TempValue,&CheckValue,TEMP);
                error += SHT10_Measure(&HumValue,&CheckValue,HUMI);
                //温度湿度计算,浮点数形式
                SHT10_Cal(TempValue ,HumValue,&TempResult,&HumResult);
                //通过串口输出,温度和湿度数据
                printf("温度 %2.1fC 湿度 %2.1f%%\n",TempResult,HumResult);

            }
        }
    }
}
Jessicakjdsl|  楼主 | 2016-11-23 19:22 | 显示全部楼层
/**
  * @brief  初始化Systick定时器
  * @param  None
  * @retval None
  */
void RCC_Config(void)
{      
    //Systick时钟每1ms触发一次
    if (SysTick_Config(SystemCoreClock / 1000))
    {
        //
        while (1);
    }
}

/**
  * @brief  初始化SHT10 IO口
  * @param  None
  * @retval None
  */
void SHT10_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
   
    //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,ENABLE);
  
    //PB0 SDA 推挽输出
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
          //PB1 SCK 推挽输出
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/**
  * @brief  配置为输入状态
  * @param  None
  * @retval None
  */
void SHT10_SDAIn(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
   
    //PB0 SDA 浮动输入,外部有上拉电阻
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
          GPIO_Init(GPIOB, &GPIO_InitStructure);   
}

/**
  * @brief  配置为输出状态
  * @param  None
  * @retval None
  */
void SHT10_SDAOut(void)
{
          GPIO_InitTypeDef GPIO_InitStructure;
   
    //PB0 SDA 推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
          GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/**
  * @brief  配置为输出状态
  * @param  写数据
  * @retval 应答
  */
uint8_t SHT10_WriteByte(uint8_t value)
{
    uint8_t i,error=0;  
    //SDA输出
    SHT10_SDAOut();
   
    for( i = 0x80 ; i>0 ; i/=2)            
    {
        if ( i & value)
            SDA_H();            
        else
            SDA_L();
        
        SHT10_Delay();                       
        SCK_H();                          
        SHT10_Delay();                     
        SCK_L();
        SHT10_Delay();                     
    }
   
    //SDA输入
    SHT10_SDAIn();
   
    SCK_H();                           
    error = SDA_R();   //读应答位                 
    SCK_L();
   
    return error;                 
}

/**
  * @brief  读数据
  * @param  应答
  * @retval 返回数据
  */
uint8_t SHT10_ReadByte(uint8_t Ack)
{
    uint8_t i,val=0;
    //输入状态
    SHT10_SDAIn();  
   
    for (i=0x80;i>0;i/=2)         
    {
        SHT10_Delay();  
        SCK_H();   
        SHT10_Delay();  
        if (SDA_R())
            val=(val | i);        //读数据
        SCK_L();                                          
    }
   
    //输出状态
    SHT10_SDAOut();  
    if(Ack)
        SDA_L();                //应答为低电平
    else
        SDA_H();

    SHT10_Delay();  
    SCK_H();                     
    SHT10_Delay();  
    SCK_L();
    SHT10_Delay();                                             
    return val;
}

使用特权

评论回复
Jessicakjdsl|  楼主 | 2016-11-23 19:24 | 显示全部楼层
/**
  * @brief  启动
  * @param  无
  * @retval 无
  */
void SHT10_Start(void)
{  
   //SDA输出
    SHT10_SDAOut();
   
    SCK_L();                  
    SHT10_Delay();         
    SCK_H();
    SHT10_Delay();         
    SDA_L();
    SHT10_Delay();         
    SCK_L();  
    SHT10_Delay();         
    SCK_H();
    SHT10_Delay();         
    SDA_H();                  
    SHT10_Delay();         
    SCK_L();                  
}

/**
  * @brief  重新连接
  * @param  无
  * @retval 无
  */
void SHT10_ConReset(void)
{
    uint8_t i;
    //输出
    SHT10_SDAOut();
   
    SDA_H();    //输出高电平
    SCK_L();
   
    for(i = 0 ; i < 9 ; i++)                  
    {
        SCK_H();
        SHT10_Delay();
        SCK_L();
        SHT10_Delay();
    }
   
    SHT10_Start();                  
}

/**
  * @brief  软件重启
  * @param  无
  * @retval 无
  */
uint8_t SHT10_SoftReset(void)
{
    uint8_t error=0;  
    SHT10_ConReset();              
    error += SHT10_WriteByte(RESET);      
    return error;                    
}

/**
  * @brief  温度或湿度测量
  * @param  温度或者湿度指针数据,校验值指针,模式
  * @retval 错误
  */
uint8_t SHT10_Measure(uint16_t* pValue, uint8_t* pCheckSum, uint8_t mode)
{
    uint8_t error=0;
   
    uint8_t Value_H = 0;
    uint8_t Value_L = 0;
   
    //启动
    SHT10_Start();               
    switch(mode)
    {                     
    case TEMP:
        error += SHT10_WriteByte(MEASURE_TEMP);
        break;
    case HUMI:
        error += SHT10_WriteByte(MEASURE_HUMI);
        break;
    default:
        break;         
    }
   
    //SDA读状态
    SHT10_SDAIn();
    //等待转换完成,代码有待优化
    while(SDA_R())
    {
        ;
    }

    Value_H = SHT10_ReadByte(ACK);    //读高位
    Value_L = SHT10_ReadByte(ACK);    //读低位
   
    *pCheckSum = SHT10_ReadByte(noACK);  //读校验结果
   
    //返回结果
    *pValue = (Value_H << 8) | Value_L;   
   
    return error;
}

使用特权

评论回复
Jessicakjdsl|  楼主 | 2016-11-23 19:24 | 显示全部楼层
/**
  * @brief  计算温度和湿度数据
  * @param  温度数据 湿度数据 温度结果 湿度结果
  * @retval 无
  */
void SHT10_Cal(uint16_t Temp,uint16_t Hum, float* pTempValue,float* pHumValue)
{
    const float d1 = -40.1;
    const float d2 = 0.01;
    float Temp_C;
    //温度结果,换算                 
    Temp_C = d1 + d2 * Temp;   
   
    const float C1 = -2.0468;           
    const float C2 = +0.0367;           
    const float C3 = -0.0000015955;     
    const float T1 = +0.01;            
    const float T2 = +0.00008;         
   
    //湿度线性值
    float RH_Lin;
    //湿度真实值
    float RH_True;  
   
    //RH线性结果
    RH_Lin = C1 + C2 * Hum + C3 * Hum *Hum;
    RH_True = (Temp_C - 25) * (T1 + T2 * Hum) + RH_Lin;
    //限定范围
    if( RH_True > 100 ) RH_True = 100;
    if( RH_True < 0.01) RH_True = 0.01;
   
    *pTempValue = Temp_C;
    *pHumValue = RH_True;
   
}


/**
  * @brief  延时函数
  * @param  无
  * @retval 无
  */
void SHT10_Delay(void)
{
    //延时函数,i有待修改
    for(uint16_t i = 500 ; i > 0 ; i--)
    {
        ;
    }
}

使用特权

评论回复
Jessicakjdsl|  楼主 | 2016-11-23 19:25 | 显示全部楼层
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

//函数声明
void USART1_Config(void);
uint8_t Add_Tx1Item(uint8_t ch);
uint8_t Get_Tx1BufCounter(void);
uint8_t Get_Rx1Item(void);
uint8_t Get_Rx1BufCounter(void);
void Clear_Tx1Buf(void);
void Clear_Rx1Buf(void);
#endif

c文件部分
/**
  ******************************************************************************
  * [url=home.php?mod=space&uid=288409]@file[/url]   
  * [url=home.php?mod=space&uid=187600]@author[/url]  
  * @version
  * [url=home.php?mod=space&uid=212281]@date[/url]   
  * @brief   以队列的方式发送和接收数据
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "usart1.h"
#include "stdio.h"
#include "stm32f10x_it.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
//发送缓冲区长度
#define TX1_BUFFER_SIZE        128
//接收缓冲区长度
#define RX1_BUFFER_SIZE 128
/* Private variables ---------------------------------------------------------*/
//发送缓冲区
uint8_t Tx1_Buffer[TX1_BUFFER_SIZE];
uint8_t Tx1_WriteIndex = 0;
uint8_t Tx1_ReadIndex = 0;
uint8_t Tx1_Counter = 0;
//接收缓冲区
uint8_t Rx1_Buffer[RX1_BUFFER_SIZE];
uint8_t Rx1_WriteIndex = 0;
uint8_t Rx1_ReadIndex = 0;
uint8_t Rx1_Counter = 0;
uint8_t Rx1_BufOverflow = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  USART1_Config 初始化USART1
  *         第一步 使能GPIOA时钟
  *         第二步 配置IO口
  *         第三步 配置USART1
  *         第四步 配置中断优先级
  * @param  None
  * @retval None
  */
void USART1_Config(void)
{
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
   
    Clear_Tx1Buf();
    Clear_Rx1Buf();
   
    //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA \
                        | RCC_APB2Periph_USART1 ,ENABLE);
  
    //PA9 TX1 复用推挽输出
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
          GPIO_Init(GPIOA, &GPIO_InitStructure);
          //PA10 RX1 浮动输入
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
          GPIO_Init(GPIOA, &GPIO_InitStructure);
  
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    //使能接收中断
        USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
    //使能USART1
        USART_Cmd(USART1, ENABLE);
   
    //配置USART1中断,最高优先级
    NVIC_InitTypeDef NVIC_InitStructure;
          //抢占优先级0  
          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
          //从优先级1
          NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);

}

使用特权

评论回复
Jessicakjdsl|  楼主 | 2016-11-23 19:26 | 显示全部楼层
/**
  * @brief  加入发送队列.
  * @param  待发送的数据
  * @retval 待发送的数据
  */
uint8_t Add_Tx1Item(uint8_t ch)
{
        //发送队列满。发送队列满
    while(Tx1_Counter == TX1_BUFFER_SIZE);      
      
    //压入数据
    Tx1_Buffer[Tx1_WriteIndex] = ch;
    //发送缓冲区写计数器移动
    Tx1_WriteIndex ++;
    if( Tx1_WriteIndex >= TX1_BUFFER_SIZE )
        {
            //写指针移动到队列头部      
                Tx1_WriteIndex = 0;                              
        }
    //数据总数增加
    Tx1_Counter++;
      
    //使能发送中断
        USART_ITConfig(USART1,USART_IT_TXE,ENABLE);
   
        return Tx1_WriteIndex;      
}
/**
  * @brief  返回发送队列中的字节数
  * @param  无
  * @retval 发送队列中的字节数
  */
uint8_t Get_Tx1BufCounter(void)
{
    return Tx1_Counter;
}

/**
  * @brief  从接收队列中取出数据.
  * @param  None
  * @retval 被取出数据
  */
uint8_t Get_Rx1Item(void)
{
        uint8_t Rx1_Data;
   
        //等待,需要修改
        while(Rx1_Counter == 0);
   
        //从队列中读取数据
        Rx1_Data = Rx1_Buffer[Rx1_ReadIndex];
    //接收缓冲区读指针移动
        Rx1_ReadIndex ++;
        if(Rx1_ReadIndex >= RX1_BUFFER_SIZE)
        {
                Rx1_ReadIndex = 0;
        }
    //
        Rx1_Counter --;

        return Rx1_Data;      
}

/**
  * @brief  返回接收队列中的字节数
  * @param  无
  * @retval 接收队列中的字节数
  */
uint8_t Get_Rx1BufCounter(void)
{
    return Rx1_Counter;
}

/**
  * @brief  清空发送队列
  * @param  无
  * @retval 无
  */
void Clear_Tx1Buf(void)
{
    for(uint8_t i = 0 ; i < TX1_BUFFER_SIZE ; i++)
    {
        Tx1_Buffer = 0;
    }
    Tx1_Counter = 0;
}
/**
  * @brief  清空接收队列
  * @param  无
  * @retval 无
  */
void Clear_Rx1Buf(void)
{
    for(uint8_t i = 0 ; i < RX1_BUFFER_SIZE ; i++)
    {
        Rx1_Buffer = 0;
    }
   
    Rx1_Counter = 0;
}

/**
  * @brief  USART1中断.
  * @param  None
  * @retval None
  */
void USART1_IRQHandler(void)
{
          uint8_t ch;
      
    //接收中断
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
          {
                //读取数据
                ch = USART_ReceiveData(USART1);               
        
        //清除接收中断标志位
        //USART_ClearFlag(USART1,USART_FLAG_RX1NE);
        //接收缓冲区数据个数递增
                Rx1_Counter++;      
        
                //数据填入接收队列
                Rx1_Buffer[Rx1_WriteIndex] = ch;
      
                Rx1_WriteIndex ++;
                if(Rx1_WriteIndex >= RX1_BUFFER_SIZE)
                {
                        Rx1_WriteIndex = 0;
                }

                //队列溢出
                if(Rx1_Counter >= RX1_BUFFER_SIZE)
                {
                        //数据作废,修改
                        //Rx1_Counter = 0;
                        //溢出标志置位
                        Rx1_BufOverflow = 1;
                }

          }
   
        //发送中断
        if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
          {
                //清除接收中断标志位
                //USART_ClearFlag(USART1,USART_FLAG_TX1E);
                //存在未发送的数据
                if(Tx1_Counter > 0)
                {
                        //发送数据
                        USART_SendData(USART1, Tx1_Buffer[Tx1_ReadIndex]);
            //发送数据总数递减
                        Tx1_Counter --;
                        Tx1_ReadIndex++;
                        //回到缓冲区开头
                        if(Tx1_ReadIndex >= TX1_BUFFER_SIZE)
                        {
                                Tx1_ReadIndex = 0;
                        }
                }
        else
        {
            //无发送数据,关闭发送中断
            USART_ITConfig(USART1,USART_IT_TXE,DISABLE);;  
        }
          }
}


int fputc(int ch, FILE * f)
{
    //通过串口发送数据  
    Add_Tx1Item((uint8_t)ch);
   
    return ch;
}

使用特权

评论回复
zhuomuniao110| | 2016-11-23 20:03 | 显示全部楼层
在室内如果好好的那么在外面也好好的,没要大问题,这个变化要看变化率了。温差是否大。

使用特权

评论回复
尤彼卡| | 2016-11-23 21:51 | 显示全部楼层
感谢分享

使用特权

评论回复
liubo0702| | 2016-11-24 09:09 | 显示全部楼层
谢谢分享!学习一下

使用特权

评论回复
Thethree| | 2016-11-26 18:56 | 显示全部楼层
温度的响应时间是多少,从20°下降到0°需要多长时间?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

116

帖子

1

粉丝