#申请原创# @21小跑堂
BMP280是博世最推出的数字气压传感器,可以测量气压和温度,支持SPI和I2C通信接口,这里使用I2C来通讯
VCC:3.3V供电:
GND
SCL:时钟信号
SDA:I2C通信模式数据信号,SPI模式模块数据输入
CSB:通信模式选择,高电平I2C,低电平SPI,模块通过电阻上拉默认I2C模式
SDO:I2C通信模式下为传感器地址控制位,接GND的时候器件地址为0x76,接高电平为0x77,模块通过电阻下拉,SPI模式下为模块数据输出
I2C需要时钟线和数据线进行双向通讯,GPIO使用开漏模式
定义GPIO操作中间层
void yuyy_gpio_setlev(YUYY_GPIO_DEV_t *gpio_dev,YUYY_GPIO_LEV_TYPE lev)
{
gpio_bits_write(gpio_dev->gpio,gpio_dev->pin,lev);
}
YUYY_GPIO_LEV_TYPE yuyy_gpio_getlev(YUYY_GPIO_DEV_t *gpio_dev)
{
return gpio_input_data_bit_read(gpio_dev->gpio,gpio_dev->pin);
}
void yuyy_gpio_opod_out(YUYY_GPIO_DEV_t *gpio_dev)
{
}
void yuyy_gpio_opod_in(YUYY_GPIO_DEV_t *gpio_dev)
{
gpio_bits_write(gpio_dev->gpio,gpio_dev->pin,YUYY_GPIO_LEV1);
}
实现SCL和SDA操作方法
void yuyy_soft_iic_sdain(YUYY_SOFT_IIC_DEV_t *iicx)
{
yuyy_gpio_opod_in(&(iicx->sda));
}
void yuyy_soft_iic_sdaout(YUYY_SOFT_IIC_DEV_t *iicx)
{
yuyy_gpio_opod_out(&(iicx->sda));
}
void yuyy_soft_iic_sdalev(YUYY_SOFT_IIC_DEV_t *iicx,YUYY_GPIO_LEV_TYPE lev)
{
yuyy_gpio_setlev(&(iicx->sda),lev);
}
YUYY_GPIO_LEV_TYPE yuyy_soft_iic_sdaread(YUYY_SOFT_IIC_DEV_t *iicx)
{
return yuyy_gpio_readlev(&(iicx->sda));
}
void yuyy_soft_iic_sclin(YUYY_SOFT_IIC_DEV_t *iicx)
{
yuyy_gpio_opod_in(&(iicx->scl));
}
void yuyy_soft_iic_sclout(YUYY_SOFT_IIC_DEV_t *iicx)
{
yuyy_gpio_opod_out(&(iicx->scl));
}
void yuyy_soft_iic_scllev(YUYY_SOFT_IIC_DEV_t *iicx,YUYY_GPIO_LEV_TYPE lev)
{
yuyy_gpio_setlev(&(iicx->scl),lev);
}
YUYY_GPIO_LEV_TYPE yuyy_soft_iic_sclread(YUYY_SOFT_IIC_DEV_t *iicx)
{
return yuyy_gpio_readlev(&(iicx->scl));
}
之后按照I2C通讯逻辑实现I2C读写
uint8_t yuyy_soft_iic_start(YUYY_SOFT_IIC_DEV_t *iicx)
{
yuyy_soft_iic_sdaout(iicx);
yuyy_soft_iic_sclout(iicx);
yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
yuyy_soft_iic_sclin(iicx);
if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
return 1;
yuyy_soft_iic_sclout(iicx);
yuyy_soft_iic_delay();
yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
yuyy_soft_iic_delay();
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
yuyy_soft_iic_delay();
return YUYY_SOFT_IIC_OK;
}
uint8_t yuyy_soft_iic_stop(YUYY_SOFT_IIC_DEV_t *iicx)
{
yuyy_soft_iic_sdaout(iicx);
yuyy_soft_iic_sclout(iicx);
yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
yuyy_soft_iic_sclin(iicx);
if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
return 1;
yuyy_soft_iic_sclout(iicx);
yuyy_soft_iic_delay();
yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
return YUYY_SOFT_IIC_OK;
}
uint8_t yuyy_soft_iic_readack(YUYY_SOFT_IIC_DEV_t *iicx)
{
uint8_t i=0,ack=YUYY_SOFT_IIC_ACK;
yuyy_soft_iic_sdain(iicx);
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
yuyy_soft_iic_sclin(iicx);
if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
return 1;
yuyy_soft_iic_sclout(iicx);
yuyy_soft_iic_delay();
while(yuyy_soft_iic_sdaread(iicx)!=YUYY_GPIO_LEV0 && i<10)
{
yuyy_soft_iic_delay();
i += 1;
}
if(i>8)
ack = YUYY_SOFT_IIC_NACK;
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
yuyy_soft_iic_delay();
return ack;
}
uint8_t yuyy_soft_iic_sendack(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t ack)
{
yuyy_soft_iic_sdaout(iicx);
if(ack == YUYY_SOFT_IIC_ACK)
yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
else
yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
yuyy_soft_iic_sclin(iicx);
if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
return 1;
yuyy_soft_iic_sclout(iicx);
yuyy_soft_iic_delay();
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
yuyy_soft_iic_delay();
return YUYY_SOFT_IIC_OK;
}
uint8_t yuyy_soft_iic_sendbyte(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t dat)
{
uint8_t i = 0;
yuyy_soft_iic_sdaout(iicx);
while(i<8)
{
if(dat & 0x80)
yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
else
yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
yuyy_soft_iic_sclin(iicx);
if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
return 1;
yuyy_soft_iic_sclout(iicx);
yuyy_soft_iic_delay();
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
yuyy_soft_iic_delay();
dat = dat << 1;
i += 1;
}
return YUYY_SOFT_IIC_OK;
}
uint8_t yuyy_soft_iic_readbyte(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t *dat)
{
uint8_t i = 0;
*dat = 0;
yuyy_soft_iic_sdain(iicx);
while(i<8)
{
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
yuyy_soft_iic_sclin(iicx);
if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
return 1;
yuyy_soft_iic_sclout(iicx);
yuyy_soft_iic_delay();
*dat = *dat << 1;
if(yuyy_soft_iic_sdaread(iicx) == YUYY_GPIO_LEV1)
*dat |= 0x01;
yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
yuyy_soft_iic_delay();
i += 1;
}
return YUYY_SOFT_IIC_OK;
}
BMP280手册提供的 参考代码
代码实现
uint8_t yuyy_bmp280_writereg(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg,uint8_t dat)
{
uint8_t result = 0;
if(bmp280_dev->wiretype == YUYY_BMP280_WIRE_IIC)
result = bmp280_dev->iic_senddatas_func(bmp280_dev->iicx,BMP280_IIC_ADDR+bmp280_dev->addrlastbit,reg,1,&dat,1);
return result;
}
uint8_t yuyy_bmp280_readdatas(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg,uint8_t *datas,uint8_t len)
{
uint8_t result = 0;
if(bmp280_dev->wiretype == YUYY_BMP280_WIRE_IIC)
result = bmp280_dev->iic_readdatas_func(bmp280_dev->iicx,BMP280_IIC_ADDR,reg,1,datas,len);
return result;
}
uint8_t yuyy_bmp280_read1byte(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg)
{
uint8_t dat;
yuyy_bmp280_readdatas(bmp280_dev,reg,&dat,1);
return dat;
}
uint16_t yuyy_bmp280_read2byte(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg,uint8_t le)
{
uint8_t datas[2];
yuyy_bmp280_readdatas(bmp280_dev,reg,datas,2);
if(le > 0)
return (datas[1]<<8)|datas[0];
return (datas[0]<<8)|datas[1];
}
void yuyy_bmp280_readCoefficients(YUYY_BMP280_DEV_t *bmp280_dev)
{
bmp280_calib.dig_T1 = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_T1,1);
bmp280_calib.dig_T2 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_T2,1);
bmp280_calib.dig_T3 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_T3,1);
bmp280_calib.dig_P1 = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P1,1);
bmp280_calib.dig_P2 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P2,1);
bmp280_calib.dig_P3 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P3,1);
bmp280_calib.dig_P4 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P4,1);
bmp280_calib.dig_P5 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P5,1);
bmp280_calib.dig_P6 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P6,1);
bmp280_calib.dig_P7 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P7,1);
bmp280_calib.dig_P8 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P8,1);
bmp280_calib.dig_P9 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P9,1);
}
float yuyy_bmp280_readtemp(YUYY_BMP280_DEV_t *bmp280_dev)
{
int32_t var1, var2;
float T;
int32_t adc_T = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_TEMPDATA,0);
adc_T <<= 8;
adc_T |= yuyy_bmp280_read1byte(bmp280_dev,BMP280_REGISTER_TEMPDATA+2);
adc_T >>= 4;
var1 = ((((adc_T>>3) - ((int32_t)bmp280_calib.dig_T1 <<1))) * ((int32_t)bmp280_calib.dig_T2)) >> 11;
var2 = (((((adc_T>>4) - ((int32_t)bmp280_calib.dig_T1)) * ((adc_T>>4) - ((int32_t)bmp280_calib.dig_T1))) >> 12) * ((int32_t)bmp280_calib.dig_T3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T/100;
}
float yuyy_bmp280_readpress(YUYY_BMP280_DEV_t *bmp280_dev)
{
int64_t var1, var2, p;
int32_t adc_P = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_PRESSUREDATA,0);
adc_P <<= 8;
adc_P |= yuyy_bmp280_read1byte(bmp280_dev,BMP280_REGISTER_PRESSUREDATA+2);
adc_P >>= 4;
var1 = ((int64_t)t_fine) - 128000;
var2 = var1 * var1 * (int64_t)bmp280_calib.dig_P6;
var2 = var2 + ((var1*(int64_t)bmp280_calib.dig_P5)<<17);
var2 = var2 + (((int64_t)bmp280_calib.dig_P4)<<35);
var1 = ((var1 * var1 * (int64_t)bmp280_calib.dig_P3)>>8) + ((var1 * (int64_t)bmp280_calib.dig_P2)<<12);
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)bmp280_calib.dig_P1)>>33;
if (var1 == 0) {
return 0; // avoid exception caused by division by zero
}
p = 1048576 - adc_P;
p = (((p<<31) - var2)*3125) / var1;
var1 = (((int64_t)bmp280_calib.dig_P9) * (p>>13) * (p>>13)) >> 25;
var2 = (((int64_t)bmp280_calib.dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280_calib.dig_P7)<<4);
return (float)p/256;
}
初始化代码,将读到的气压和温度通过printf打印
YUYY_SOFT_IIC_DEV_t siic_dev;
YUYY_BMP280_DEV_t bmp280_dev;
void bmp280_init()
{
siic_dev.scl.gpio = SIIC_SCL_GPIO_PORT;
siic_dev.scl.pin = SIIC_SCL_PIN;
siic_dev.sda.gpio = SIIC_SDA_GPIO_PORT;
siic_dev.sda.pin = SIIC_SDA_PIN;
yuyy_soft_iic_init(&siic_dev);
bmp280_dev.iicx = &siic_dev;
bmp280_dev.wiretype = YUYY_BMP280_WIRE_IIC;
bmp280_dev.iic_readdatas_func = (yuyy_iic_readdatas_func_t)yuyy_soft_iic_readdatas;
bmp280_dev.iic_senddatas_func = (yuyy_iic_senddatas_func_t)yuyy_soft_iic_senddatas;
yuyy_bmp280_init(&bmp280_dev);
yuyy_bmp280_setctrlmeas(&bmp280_dev,0x3F);
}
void bmp280_readpress()
{
float temp,press;
temp = yuyy_bmp280_readtemp(&bmp280_dev);
press = yuyy_bmp280_readpress(&bmp280_dev);
printf("BMP280 读取温度:%.1f℃ 压力:%.1fpa",temp,press);
}
运行效果
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
|