OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 868|回复: 3

求 STM32 模拟I2C读取BMP280的程序

[复制链接]

3

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2018-7-9
在线时间
15 小时
发表于 2022-1-14 17:33:52 | 显示全部楼层 |阅读模式
1金钱
有用模拟I2C读取BMP280的程序吗?
谢谢

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2018-7-9
在线时间
15 小时
 楼主| 发表于 2022-1-17 10:45:36 | 显示全部楼层
本帖最后由 bb2511 于 2022-1-17 15:21 编辑

自己写了一个利用PC6和PC7来模拟I2C的,输出数值不对,求大神指点。  气压:582.051514
温度 :0.000000
高度 :5125.797852

回复

使用道具 举报

3

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2018-7-9
在线时间
15 小时
 楼主| 发表于 2022-1-17 11:24:54 | 显示全部楼层
本帖最后由 bb2511 于 2022-1-17 11:51 编辑

#include "myiic.h"
#include "delay.h"
#include "stm32f10x.h"
#include "stdbool.h"

char   test=0;
void IIC_Init(void)
{                                             
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOC, ENABLE );         
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //íÆíìêä3ö
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
        
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOC, ENABLE );         
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   //¿a©êä3ö
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
               
//  SDA_H;
//  SCL_L;
//        IIC_SCL=1;
//        IIC_SDA=1;
}
/*******************************************************************************
* Function Name  : I2C_delay
* Description    : Simulation IIC Timing series delay
* Input          : None
* Output         : None
* Return         : None
****************************************************************************** */
void I2C_delay(void)
{
               
   u8 i=5; //Õaàï¿éòÔóÅ»ˉËù¶è        £¬¾-2aêÔ×îμíμ½5»1ÄüD′èë
   while(i)
   {
     i--;
   }  
}

void delay5ms(void)
{
               
   int i=5000;  
   while(i)
   {
     i--;
   }  
}
/*******************************************************************************
* Function Name  : I2C_Start
* Description    : Master Start Simulation IIC Communication
* Input          : None
* Output         : None
* Return         : Wheather         Start
****************************************************************************** */
//static void iicDevStart(void)
bool iicDevStart(void)
{
//        SDA_OUT();     //sdaÏßêä3ö
//        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×üÏߣ¬×¼±¸·¢Ëí»ò½óêÕêy¾Y
        SDA_H;
        SCL_H;
        I2C_delay();
        if(!SDA_read)return false;        //SDAÏßÎaμíμçÆ½Ôò×üÏßÃ|,íË3ö
        SDA_L;
        I2C_delay();
        if(SDA_read) return false;        //SDAÏßÎa¸ßμçÆ½Ôò×üÏß3ö′í,íË3ö
        SDA_L;
        I2C_delay();
        return true;
}         
//2úéúIIC1í£Ö1DÅoÅ
static void iicDevStop(void)
{
//        SDA_OUT();//sdaÏßêä3ö
//        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×üÏß½áêøDÅoÅ
//        delay_us(4);                                 SCL_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SDA_H;
        I2C_delay();
}
/*******************************************************************************
* Function Name  : I2C_WaitAck
* Description    : Master Reserive Slave Acknowledge Single
* Input          : None
* Output         : None
* Return         : Wheather         Reserive Slave Acknowledge Single
****************************************************************************** *///μè′yó|′eDÅoÅμ½à′
//·μ»ØÖμ£o1£¬½óêÕó|′eê§°ü
//        0£¬½óêÕó|′e3é1|
static u8 iicDevWaitAck(void)
{
//        u8 ucErrTime=0;
//        SDA_IN();      //SDAéèÖÃÎaêäèë  
//        IIC_SDA=1;delay_us(1);           
//        IIC_SCL=1;delay_us(1);         
//        while(READ_SDA)
//        {
//                ucErrTime++;
//                if(ucErrTime>250)
//                {
//                        iicDevStop();
//                        return 1;
//                }
//        }
//        IIC_SCL=0;//ê±Öóêä3ö0            
//        return 0;  
        
        SCL_L;
        I2C_delay();
        SDA_H;                        
        I2C_delay();
        SCL_H;
        I2C_delay();
        if(SDA_read)
        {
      SCL_L;
            I2C_delay();
      return false;
        }
        SCL_L;
        I2C_delay();
        return true;
}
/*******************************************************************************
* Function Name  : I2C_Ack
* Description    : Master Send Acknowledge Single
* Input          : None
* Output         : None
* Return         : None
****************************************************************************** */
//2úéúACKó|′e
static void iicDevAck(void)
{
//        IIC_SCL=0;
//        SDA_OUT();
//        IIC_SDA=0;
//        delay_us(1);
//        IIC_SCL=1;
//        delay_us(1);
//        IIC_SCL=0;
        
        SCL_L;
        I2C_delay();
        SDA_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}
/*******************************************************************************
* Function Name  : I2C_NoAck
* Description    : Master Send No Acknowledge Single
* Input          : None
* Output         : None
* Return         : None
****************************************************************************** */
//2»2úéúACKó|′e                    
static void iicDevNAck(void)
{
//        IIC_SCL=0;
//        SDA_OUT();
//        IIC_SDA=1;
//        delay_us(1);
//        IIC_SCL=1;
//        delay_us(1);
//        IIC_SCL=0;
        
        SCL_L;
        I2C_delay();
        SDA_H;
        I2C_delay();
        SCL_H;
        I2C_delay();
        SCL_L;
        I2C_delay();
}               
/*******************************************************************************
* Function Name  : I2C_SendByte
* Description    : Master Send a Byte to Slave
* Input          : Will Send Date
* Output         : None
* Return         : None
****************************************************************************** */
//IIC1·¢Ëíò»¸ö×Ö½ú
//·μ»Ø′ó»úóDÎTó|′e
//1£¬óDó|′e
//0£¬ÎTó|′e                          
static void iicDevSendByte(u8 txd)
{                        
//    u8 t;   
//          SDA_OUT();            
//    IIC_SCL=0;//à-μíê±Öó¿aê¼êy¾Y′«êä
//    for(t=0;t<8;t++)
//    {              
//        IIC_SDA=(txd&0x80)>>7;
//        txd<<=1;           
//                delay_us(1);   
//                IIC_SCL=1;
//                delay_us(1);
//                IIC_SCL=0;        
//                delay_us(1);
//    }         
               
                u8 i=8;
    while(i--)
    {
        SCL_L;
        I2C_delay();
      if(txd&0x80)
        SDA_H;  
      else
        SDA_L;   
        txd<<=1;
        I2C_delay();
                    SCL_H;
        I2C_delay();
    }
    SCL_L;
}            
//&#182;á1&#184;&#246;×&#214;&#189;ú£&#172;ack=1ê±£&#172;·¢&#203;íACK£&#172;ack=0£&#172;·¢&#203;ínACK   
static u8 iicDevReceiveByte(u8 ack)
{
//        u8 i,receive=0;
//        SDA_IN();//SDAéè&#214;&#195;&#206;aê&#228;è&#235;
//    for(i=0;i<8;i++ )
//        {
//        IIC_SCL=0;
//        delay_us(1);
//                IIC_SCL=1;
//        receive<<=1;
//        if(READ_SDA)receive++;   
//                delay_us(1);
//    }                                         
//    if (!ack)
//        iicDevNAck();//·¢&#203;ínACK
//    else
//        iicDevAck(); //·¢&#203;íACK   
//    return receive;
               
                u8 i=8;
    u8 ReceiveByte=0;

    SDA_H;                                
    while(i--)
    {
      ReceiveByte<<=1;      
      SCL_L;
      I2C_delay();
            SCL_H;
      I2C_delay();        
      if(SDA_read)
      {
        ReceiveByte|=0x01;
      }
    }
    SCL_L;
    return ReceiveByte;
}

//′ó&#214;&#184;&#182;¨μ&#216;&#214;·&#182;á3&#246;ò&#187;&#184;&#246;êy&#190;Y
//ReadAddr:&#191;aê&#188;&#182;áêyμ&#196;μ&#216;&#214;·  
//·μ&#187;&#216;&#214;μ  :&#182;áμ&#189;μ&#196;êy&#190;Y
u8 iicDevReadByte(u8 devaddr,u8 addr)
{                                 
        u8 temp=0;                                                                                                                                                               
        iicDevStart();  
        iicDevSendByte(devaddr);//·¢&#203;í&#198;÷&#188;tD′&#195;üá&#238;            
        iicDevWaitAck();
        iicDevSendByte(addr);   //·¢&#203;íμíμ&#216;&#214;·
        iicDevWaitAck();        

        iicDevStart();                     
        iicDevSendByte(devaddr|1);//·¢&#203;í&#198;÷&#188;t&#182;á&#195;üá&#238;                           
        iicDevWaitAck();         
        temp=iicDevReceiveByte(0);                           
        iicDevStop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t            
        return temp;
}
//á&#172;D&#248;&#182;á&#182;à&#184;&#246;×&#214;&#189;ú
//addr:&#198;eê&#188;μ&#216;&#214;·
//rbuf:&#182;áêy&#190;Y&#187;o′&#230;
//len:êy&#190;Y3¤&#182;è
void iicDevRead(u8 devaddr,u8 addr,u8 len,u8 *rbuf)
{
        int i=0;
        iicDevStart();  
        iicDevSendByte(devaddr);  
        iicDevWaitAck();        
        iicDevSendByte(addr);//μ&#216;&#214;·×&#212;&#212;&#246;  
        iicDevWaitAck();        

        iicDevStart();         
        iicDevSendByte(devaddr|1);         
        iicDevWaitAck();        
        for(i=0; i<len; i++)
        {
                if(i==len-1)
                {
                        rbuf = iicDevReceiveByte(0);//×&#238;oóò&#187;&#184;&#246;×&#214;&#189;ú2&#187;ó|′e
                }
                else
                        rbuf = iicDevReceiveByte(1);
        }
        iicDevStop( );        
}
//′ó&#214;&#184;&#182;¨μ&#216;&#214;·D′è&#235;ò&#187;&#184;&#246;êy&#190;Y
//WriteAddr ′è&#235;êy&#190;Yμ&#196;&#196;&#191;μ&#196;μ&#216;&#214;·   
//DataToWrite:òaD′è&#235;μ&#196;êy&#190;Y
void iicDevWriteByte(u8 devaddr,u8 addr,u8 data)
{                                                                                                                                                                                          
        iicDevStart();  
        iicDevSendByte(devaddr); //·¢&#203;í&#198;÷&#188;tD′&#195;üá&#238;         
        iicDevWaitAck();           
        iicDevSendByte(addr);   //·¢&#203;íμíμ&#216;&#214;·
        iicDevWaitAck();                                                                                                               
        iicDevSendByte(data); //·¢&#203;í×&#214;&#189;ú                                                           
        iicDevWaitAck();                                 
        iicDevStop();                //2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t         
}

//á&#172;D&#248;D′&#182;à&#184;&#246;×&#214;&#189;ú
//addr:&#198;eê&#188;μ&#216;&#214;·
//wbuf′êy&#190;Y&#187;o′&#230;
//len:êy&#190;Yμ&#196;3¤&#182;è
void iicDevWrite(u8 devaddr,u8 addr,u8 len,u8 *wbuf)
{
        int i=0;
        iicDevStart();  
        iicDevSendByte(devaddr);         
        iicDevWaitAck();        
        iicDevSendByte(addr);  //μ&#216;&#214;·×&#212;&#212;&#246;
        iicDevWaitAck();        
        for(i=0; i<len; i++)
        {
                iicDevSendByte(wbuf);  
                iicDevWaitAck();               
        }
        iicDevStop();        
}


回复

使用道具 举报

3

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2018-7-9
在线时间
15 小时
 楼主| 发表于 2022-1-17 15:22:02 | 显示全部楼层
#include <math.h>
#include "stdbool.h"
#include "delay.h"
#include "myiic.h"
#include "bmp280.h"
#include "usart.h"


#define BMP280_PRESSURE_OSR                        (BMP280_OVERSAMP_8X)
#define BMP280_TEMPERATURE_OSR                (BMP280_OVERSAMP_16X)
#define BMP280_MODE                                        (BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_NORMAL_MODE)


typedef struct
{
    u16 dig_T1;/* calibration T1 data */
    s16 dig_T2; /* calibration T2 data */
    s16 dig_T3; /* calibration T3 data */
    u16 dig_P1;/* calibration P1 data */
    s16 dig_P2; /* calibration P2 data */
    s16 dig_P3; /* calibration P3 data */
    s16 dig_P4; /* calibration P4 data */
    s16 dig_P5; /* calibration P5 data */
    s16 dig_P6; /* calibration P6 data */
    s16 dig_P7; /* calibration P7 data */
    s16 dig_P8; /* calibration P8 data */
    s16 dig_P9; /* calibration P9 data */
    s32 t_fine; /* calibration t_fine data */
} bmp280Calib;

bmp280Calib  bmp280Cal;

static u8 bmp280ID = 0;
static bool isInit = false;
static s32 bmp280RawPressure = 0;
static s32 bmp280RawTemperature = 0;

static void bmp280GetPressure(void);
static void presssureFilter(float* in, float* out);
static float bmp280PressureToAltitude(float* pressure/*, float* groundPressure, float* groundTemp*/);

bool bmp280Init(void)
{       
    if (isInit)
    return true;

          IIC_Init();                /*3&#245;ê&#188;&#187;ˉI2C*/
    delay_ms(20);
       
//        iicDevWriteByte(BMP280_ADDR,BMP280_RST_REG,0xb6);
//       
//        delay_ms(20);
       
        bmp280ID=iicDevReadByte(BMP280_ADDR,BMP280_CHIP_ID);        /* &#182;áè&#161;bmp280 ID*/
       
        if(bmp280ID == BMP280_DEFAULT_CHIP_ID)
                printf("BMP280 ID IS: 0x%X\n",bmp280ID);
    else
        return false;

    /* &#182;áè&#161;D£×&#188;êy&#190;Y */
  iicDevRead(BMP280_ADDR, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, 24, (u8 *)&bmp280Cal);       
        iicDevWriteByte(BMP280_ADDR, BMP280_CTRL_MEAS_REG,BMP280_MODE);
        iicDevWriteByte(BMP280_ADDR, BMP280_CONFIG_REG,5<<2);                /*&#197;&#228;&#214;&#195;IIR&#194;&#203;2¨*/
       
//        printf("BMP280 Calibrate Registor Are: \r\n");
//        for(i=0;i<24;i++)
//                printf("Registor %2d: 0x%X\n",i,p[i]);
       
    isInit = true;

    return true;
}

static void bmp280GetPressure(void)
{
    u8 data[BMP280_DATA_FRAME_SIZE];

    // read data from sensor
    iicDevRead(BMP280_ADDR, BMP280_PRESSURE_MSB_REG, BMP280_DATA_FRAME_SIZE, data);
    bmp280RawPressure = (s32)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4));
    bmp280RawTemperature = (s32)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4));
}

// Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
// t_fine carries fine temperature as global value
static s32 bmp280CompensateT(s32 adcT)
{
    s32 var1, var2, T;

    var1 = ((((adcT >> 3) - ((s32)bmp280Cal.dig_T1 << 1))) * ((s32)bmp280Cal.dig_T2)) >> 11;
    var2  = (((((adcT >> 4) - ((s32)bmp280Cal.dig_T1)) * ((adcT >> 4) - ((s32)bmp280Cal.dig_T1))) >> 12) * ((s32)bmp280Cal.dig_T3)) >> 14;
    bmp280Cal.t_fine = var1 + var2;
       
    T = (bmp280Cal.t_fine * 5 + 128) >> 8;

    return T;
}

// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
static uint32_t bmp280CompensateP(s32 adcP)
{
    int64_t var1, var2, p;
    var1 = ((int64_t)bmp280Cal.t_fine) - 128000;
    var2 = var1 * var1 * (int64_t)bmp280Cal.dig_P6;
    var2 = var2 + ((var1*(int64_t)bmp280Cal.dig_P5) << 17);
    var2 = var2 + (((int64_t)bmp280Cal.dig_P4) << 35);
    var1 = ((var1 * var1 * (int64_t)bmp280Cal.dig_P3) >> 8) + ((var1 * (int64_t)bmp280Cal.dig_P2) << 12);
    var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bmp280Cal.dig_P1) >> 33;
    if (var1 == 0)
        return 0;
    p = 1048576 - adcP;
    p = (((p << 31) - var2) * 3125) / var1;
    var1 = (((int64_t)bmp280Cal.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
    var2 = (((int64_t)bmp280Cal.dig_P8) * p) >> 19;
    p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280Cal.dig_P7) << 4);
    return (uint32_t)p;
}

#define FILTER_NUM        5
#define FILTER_A        0.1f

/*&#207;T·ù&#198;&#189;&#190;ù&#194;&#203;2¨·¨*/
static void presssureFilter(float* in, float* out)
{       
        static u8 i=0;
        static float filter_buf[FILTER_NUM]={0.0};
        double filter_sum=0.0;
        u8 cnt=0;       
        float deta;

        if(filter_buf[i] == 0.0f)
        {
                filter_buf[i]=*in;
                *out=*in;
                if(++i>=FILTER_NUM)        i=0;
        } else
        {
                if(i) deta=*in-filter_buf[i-1];
                else deta=*in-filter_buf[FILTER_NUM-1];
               
                if(fabs(deta)<FILTER_A)
                {
                        filter_buf[i]=*in;
                        if(++i>=FILTER_NUM)        i=0;
                }
                for(cnt=0;cnt<FILTER_NUM;cnt++)
                {
                        filter_sum+=filter_buf[cnt];
                }
                *out=filter_sum /FILTER_NUM;
        }
}

void bmp280GetData(float* pressure, float* temperature, float* asl)
{
    static float t;
    static float p;
       
        bmp280GetPressure();

        t = bmp280CompensateT(bmp280RawTemperature)/100.0;               
        p = bmp280CompensateP(bmp280RawPressure)/25600.0;               

        presssureFilter(&p,pressure);
        *temperature = (float)t;/*μ¥&#206;&#187;&#182;è*/
//        *pressure = (float)p ;        /*μ¥&#206;&#187;hPa*/       
       
        *asl=bmp280PressureToAltitude(pressure);        /*×a&#187;&#187;3éo£°&#206;*/       
}

#define CONST_PF 0.1902630958        //(1/5.25588f) Pressure factor
#define FIX_TEMP 25                                // Fixed Temperature. ASL is a function of pressure and temperature, but as the temperature changes so much (blow a little towards the flie and watch it drop 5 degrees) it corrupts the ASL estimates.
                                                                // TLDR: Adjusting for temp changes does more harm than good.
/**
* Converts pressure to altitude above sea level (ASL) in meters
*/
static float bmp280PressureToAltitude(float* pressure/*, float* groundPressure, float* groundTemp*/)
{
    if (*pressure > 0)
    {
        return ((pow((1015.7f / *pressure), CONST_PF) - 1.0f) * (FIX_TEMP + 273.15f)) / 0.0065f;
    }
    else
    {
        return 0;
    }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-22 07:17

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表