打印
[STM32]

STM32的DHT12,I2C驱动,不行啊

[复制链接]
2586|9
手机看帖
扫描二维码
随时随地手机跟帖
沙发
hugo0chen|  楼主 | 2017-3-28 11:23 | 只看该作者
本帖最后由 hugo0chen 于 2017-3-28 12:12 编辑

1、STM32L151的I2C2接口
    PB10 -  SCL
    PB11 -  SDA

2、DHT12的VCC是+3.3V

3、stm32的开发库版本是
  * @author  MCD Application Team
  * @version V1.1.1
  * @date    05-March-2012


4、DHT12的I2C时序

/**************************************************************************************************************************/
void Init_DHT12(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        I2C_InitTypeDef I2C_InitStructure;
        
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
//        GPIO_PinAFConfig(GPIOB, GPIO_Pin_10, GPIO_AF_I2C2);
//        GPIO_PinAFConfig(GPIOB, GPIO_Pin_11, GPIO_AF_I2C2);这个有bug,改为寄存器直接操作
        GPIOB->AFR[1] |= 0x00000400;
        GPIOB->AFR[1] |= 0x00004000;
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
               
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        
        I2C_InitStructure.I2C_ClockSpeed = 100000;         
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStructure.I2C_OwnAddress1 = 0;        
        I2C_Init(I2C2, &I2C_InitStructure);
        
        I2C_Cmd(I2C2, ENABLE);
        I2C_AcknowledgeConfig(I2C2, ENABLE);        
}
/*************************************************************
*************************************************************/
#define MAX_I2C_WAIT_TIME  2000
uint8_t Convert_DHT12(float* Temprature, float* Humi)
{
        uint8_t Humi_H,Humi_L;
        uint8_t Temp_H;
        uint8_t Temp_L;
        uint8_t Temp_CAL;
        uint8_t temp;
        float getTemp, getHumi;
        uint32_t timeCount;
        
        // WRITE Operation----------------------
        timeCount = 0;
        while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY))
        {
                timeCount++;
                if(timeCount > MAX_I2C_WAIT_TIME)
                {
                        break;
                }
        }
        // Start
        I2C_GenerateSTART(I2C2, ENABLE);
        timeCount = 0;
        while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
        {
                timeCount++;
                if(timeCount > MAX_I2C_WAIT_TIME )
                        break;
        }
        //Dev SEL
        I2C_Send7bitAddress(I2C2, DHT12_ADDR, I2C_Direction_Transmitter);
        timeCount = 0;
        while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        {
                timeCount++;
                if(timeCount > MAX_I2C_WAIT_TIME )
                        break;
        }
        I2C_SendData(I2C2, 0);
        timeCount = 0;
        while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        {
                timeCount++;
                if(timeCount > MAX_I2C_WAIT_TIME )
                        break;
        }
        // READ-------
                timeCount = 0;
        while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY))
        {
                timeCount++;
                if(timeCount > MAX_I2C_WAIT_TIME)
                {
                        break;
                }
        }
                I2C_GenerateSTART(I2C2, ENABLE);       //Ö÷»ú·¢ËÍÆðʼÐźŠ              
                timeCount = 0;
                while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
                {
                        timeCount++;
                        if(timeCount > MAX_I2C_WAIT_TIME )
                                break;
                }
                I2C_Send7bitAddress(I2C2, DHT12_ADDR, I2C_Direction_Receiver);
                timeCount = 0;
                while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
                {
                        timeCount++;                  
                        if(timeCount > MAX_I2C_WAIT_TIME )
                                break;
                }               
                timeCount = 0;
          if(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))
                {
                        Humi_H = I2C_ReceiveData(I2C2);                        
                        //printf("Data Out Humi_H:%d  \n", Humi_H);
                }
                if(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))
                {
                        Humi_L = I2C_ReceiveData(I2C2);
                        //printf("Data Out Humi_L:%d  \n", Humi_L);
                }
                if(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))
                {
                        Temp_H = I2C_ReceiveData(I2C2);
                        //printf("Data Out Temp_H:%d  \n", Temp_H);
                }
                if(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))
                {
                        Temp_L = I2C_ReceiveData(I2C2);
                        //printf("Data Out Temp_L:%d  \n\r", Temp_L);
                }
                if(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))
                {               
                        Temp_CAL = I2C_ReceiveData(I2C2);
                        //printf("Cal :%d \n\r", Temp_CAL);
                }
                I2C_AcknowledgeConfig(I2C2, DISABLE);
                I2C_GenerateSTOP(I2C2, ENABLE);                  
                I2C_AcknowledgeConfig(I2C2, ENABLE);
                printf("H: %x  .  %x  \n\rT:%x . %x \n\r" ,Humi_H, Humi_L, Temp_H, Temp_L);
                temp = (uint8_t)(Humi_H+Humi_L+Temp_H+Temp_L);
                printf("CAL: %x , %x \n\r", Temp_CAL, temp);
                if(Temp_CAL==temp)                                                     
                {
                        getHumi=Humi_H*10+Humi_L;
        
                        if(Temp_L&0X80)        
                        {
                                getTemp =0-(Temp_H*10+((Temp_L&0x7F)));
                        }
                        else   
                        {
                                getTemp=Temp_H*10+Temp_L;
                        }         

                        if(getHumi>950)
                        {
                          getHumi=950;
                        }
                        else if(getHumi<200)
                        {
                                getHumi =200;
                        }
                        
                        if(getTemp>600)
                        {
                          getTemp=600;
                        }
                        else if(getTemp<-200)
                        {
                                getTemp = -200;
                        }
                        *Temprature = getTemp/10.0;
                        *Humi = getHumi/10.0;
                }
                else
                {
                        printf("CRC Error !!\r\n");
                }

        return 0;
}示波器量测信号:




使用特权

评论回复
板凳
dawei360| | 2017-3-28 12:52 | 只看该作者
  参考别家的例子来写,IIC的不难,慢慢研究

使用特权

评论回复
地板
hugo0chen|  楼主 | 2017-3-28 13:48 | 只看该作者
dawei360 发表于 2017-3-28 12:52
参考别家的例子来写,IIC的不难,慢慢研究

能提供个测试通过的例子吗?

使用特权

评论回复
5
dawei360| | 2017-3-28 14:07 | 只看该作者
hugo0chen 发表于 2017-3-28 13:48
能提供个测试通过的例子吗?

还是不毁了你,慢慢想

使用特权

评论回复
6
hugo0chen|  楼主 | 2017-3-28 14:19 | 只看该作者
本帖最后由 hugo0chen 于 2017-3-28 14:21 编辑
dawei360 发表于 2017-3-28 14:07
还是不毁了你,慢慢想

(⊙o⊙)…·····参考别家的也是毁了我,

使用特权

评论回复
7
@若水| | 2017-3-28 21:09 | 只看该作者
hugo0chen 发表于 2017-3-28 14:19
(⊙o⊙)…·····参考别家的也是毁了我,

使用特权

评论回复
8
Prry| | 2017-3-28 23:31 | 只看该作者
单片机常用的总线如i2c、spi、uart等,将其硬件抽象层分离,相关外设在其抽象层上的应用函数接口调用。这样的好处是 :
1、外设的驱动方便移植到任何单片机;
2、外设总线方便移植到其他单片机,只需更改部分寄存器配置;
3、总线调试OK后,调试新的外设程序时,不用重重复复调试总线的程序。
比如,楼上的程序分层就不够好,每次使用一个新的i2c外设,就相当于重新配置一次底层的总线,移植到其他单片机时又是重新写一遍,多吃力啊。

使用特权

评论回复
9
hugo0chen|  楼主 | 2017-3-29 10:22 | 只看该作者
Prry 发表于 2017-3-28 23:31
单片机常用的总线如i2c、spi、uart等,将其硬件抽象层分离,相关外设在其抽象层上的应用函数接口调用。这样 ...

受教了

使用特权

评论回复
10
hugo0chen|  楼主 | 2017-3-29 19:56 | 只看该作者
本帖最后由 hugo0chen 于 2017-3-29 20:00 编辑

#include "dht12.h"
#include "i2c.h"

#define I2C_CLOCK                  300000
#define I2C_OWN_ADDR         0xC5                                //STM i2c address
/*************************************************************
*************************************************************/
static void init_I2C_InitStructure(void)
{
        I2C_InitTypeDef I2C_InitStructure;
        
        I2C_DeInit(I2C2);
        I2C_InitStructure.I2C_ClockSpeed = I2C_CLOCK;                  
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStructure.I2C_OwnAddress1 = I2C_OWN_ADDR;              
        I2C_Init(I2C2, &I2C_InitStructure);
        
        I2C_Cmd(I2C2, ENABLE);
        I2C_AcknowledgeConfig(I2C2, ENABLE);
}

void inti_I2C2(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
               
        RCC_AHBPeriphClockCmd        (RCC_AHBPeriph_GPIOB, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
//        GPIO_PinAFConfig(GPIOB, GPIO_Pin_10, GPIO_AF_I2C2);
//        GPIO_PinAFConfig(GPIOB, GPIO_Pin_11, GPIO_AF_I2C2);
        GPIOB->AFR[1] |= 0x00000400;
        GPIOB->AFR[1] |= 0x00004000;
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
               
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);        
               
        init_I2C_InitStructure();
}

uint32_t I2CTimeout;
#define WIAT_FOR_FLAG(flag, value, timeout, errorcode) I2CTimeout = timeout;\                                                                                       while(I2C_CheckEvent(I2C2,flag) != value )\
                                                                                        {        if((I2CTimeout--) == 0)\
                                                                                       return I2Cx_TIMEOUT_UserCallback(errorcode);}
/*************************************************************
*************************************************************/
static uint8_t I2Cx_TIMEOUT_UserCallback(uint8_t errorcode){
        I2C_GenerateSTOP(I2C2, ENABLE);
        I2C_SoftwareResetCmd(I2C2, ENABLE);
        I2C_SoftwareResetCmd(I2C2, DISABLE);   
        init_I2C_InitStructure();         
        return 1;
}

#define WAIT_FLAG_TIME 200
#define LONG_WAIT_**A_TIME (10*WAIT_FLAG_TIME)

static uint8_t Convert_DHT12(struct dht12_Reg_Data* reg_data)
{        
        uint8_t id;
        uint8_t point[4];
        //------WRITE Operation-----
        WIAT_FOR_FLAG(I2C_FLAG_BUSY, RESET,LONG_WAIT_**A_TIME,1);

        // Start
        I2C_GenerateSTART(I2C2, ENABLE);

        //Test On EV5 and clear it
        WIAT_FOR_FLAG(I2C_EVENT_MASTER_MODE_SELECT, SET,WAIT_FLAG_TIME,2);

        //Dev SEL  
        I2C_Send7bitAddress(I2C2, DHT12_ADDR, I2C_Direction_Transmitter);
        WIAT_FOR_FLAG(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED, SET,LONG_WAIT_**A_TIME,3);

        //Send Byte Addr
        I2C_SendData(I2C2, REG_HUMIDITY_HIGH);
        WIAT_FOR_FLAG(I2C_EVENT_MASTER_BYTE_TRANSMITTED, SET,LONG_WAIT_**A_TIME,4);
        
        //-------READ Operation------
        I2C_GenerateSTART(I2C2, ENABLE);        
        WIAT_FOR_FLAG(I2C_EVENT_MASTER_MODE_SELECT, SET,WAIT_FLAG_TIME,5);        

        I2C_Send7bitAddress(I2C2, DHT12_ADDR, I2C_Direction_Receiver);
        // Read Data        
        for( id = 0;id < 4;id++)
        {
                WIAT_FOR_FLAG(I2C_EVENT_MASTER_BYTE_RECEIVED, SET,LONG_WAIT_**A_TIME,6);
                point[id] = I2C_ReceiveData(I2C2);
        }
        I2C_AcknowledgeConfig(I2C2, DISABLE);
        WIAT_FOR_FLAG(I2C_EVENT_MASTER_BYTE_RECEIVED, SET,LONG_WAIT_**A_TIME,6);        
        reg_data->cal_value = I2C_ReceiveData(I2C2);
        
        reg_data->humi_high              = point[0];
        reg_data->humi_low              = point[1];
        reg_data->temperature_high = point[2];
        reg_data->temperature_low  = point[3];
        
        I2C_GenerateSTOP(I2C2, ENABLE);               
        I2C_AcknowledgeConfig(I2C2, ENABLE);
        return 0;
}

uint8_t getDHT12_Temp_Humi(float* temperature, float* huminity)
{
        uint8_t temp_cal = 0;
        float getTemp = 0.0, getHumi = 0.0;
        struct dht12_Reg_Data data;
        
        Convert_DHT12(&data);

        temp_cal = (uint8_t)(data.humi_high + data.humi_low + data.temperature_high + data.temperature_low);//ֻȡµÍ8λ
               
        if(data.cal_value == temp_cal)                                                                                                                                                                                                                                                                                
        {
                getHumi = data.humi_high*10 + data.humi_low;                                                                                                                                                                                                                     
                if(data.temperature_low&0X80)  
               {
                        getTemp = 0 - (data.temperature_high*10 + ((data.temperature_low&0x7F)));
                }
                else                                                                                                                                                                                                                                                                     
                {
                        getTemp=data.temperature_high*10+data.temperature_low;                                                                                                                                                                  
                }            
                if(getHumi > 950)
                {
                        getHumi = 950;
                }
                else if(getHumi < 200)
                {
                        getHumi = 200;
                }

                if(getTemp > 600)
                {
                        getTemp = 600;
                }
                else if(getTemp < -200)
                {
                        getTemp = -200;
                }
                *temperature = getTemp/10.0;
                *huminity = getHumi/10.0;               
        }        
        else               
        {
                return 1;
        }
        return 0;
}



使用特权

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

本版积分规则

15

主题

191

帖子

3

粉丝