本帖最后由 mingxiangjun 于 2024-7-14 18:25 编辑
进阶任务:I2C主设备收发 一、说明 I2C总线具有很好的主从仲裁逻辑,本次使用P4.0做SCL,P4.1做SDA进行通信,读取气压计BMP180的温度和气压数据。而BMP180传感器的从设备地址为0xEE。
二、编码 底层对接层i2c_comm.c: #include "i2c_comm.h"
#include <string.h>
void I2cWriteRegister(uint8_tslave_addr,uint8_t reg_addr,uint8_t instword)
{
uint8_twrBuff[2];
wrBuff[0]=reg_addr;
wrBuff[1]=instword;
cyhal_i2c_master_write(&mI2C,slave_addr,wrBuff,2,0,true);
}
void I2cWriteRegisters(uint8_tslave_addr,uint8_t reg_addr,uint8_tinstword[],uint8_t len)
{
uint8_twrBuff[len+1];
wrBuff[0]=reg_addr;
memcpy(wrBuff+1,instword,len);
cyhal_i2c_master_write(&mI2C,slave_addr,wrBuff,len+1,0,true);
}
uint8_t I2cReadRegister(uint8_tslave_addr,uint8_t reg_addr)
{
uint8_t rdBuff=0;
cyhal_i2c_master_write(&mI2C,slave_addr,®_addr,1,0,true);
cyhal_i2c_master_read(&mI2C,slave_addr,&rdBuff,1,0,true);
return rdBuff;
}
uint16_t I2cReadWord(uint8_tslave_addr,uint8_t reg_addr)
{
uint8_trdBuff[2];
cyhal_i2c_master_write(&mI2C,slave_addr,®_addr,1,0,true);
cyhal_i2c_master_read(&mI2C,slave_addr,rdBuff,2,0,true);
return (((uint16_t)rdBuff[0]))<<8|(rdBuff[1]);
}
void I2cReadRegisters(uint8_tslave_addr,uint8_t reg_addr,uint8_t*p_buffer,uint8_t num)
{
uint8_trdBuff[num];
cyhal_i2c_master_write(&mI2C,slave_addr,®_addr,1,0,true);
cyhal_i2c_master_read(&mI2C,slave_addr,rdBuff,num,0,true);
}
传感器驱动层sensor_bmp180.h: #ifndef_SENSOR_BMP180_H
#define_SENSOR_BMP180_H
#define BMP180 1
#if BMP180
#define BMP180_SA 0x77 //0xEE
#define BMP180_MANUID 0x55
#define RESET 0xB6
#define OSS 0 //oversamplingsetting(pressure)
#define REG_OUT_XLSB (0xF8)
#define REG_OUT_LSB (0xF7)
#define REG_OUT_MSB (0xF6)
#define REG_CTRL_MEAS (0xF4)
#define REG_RESET (0XE0)
#define REG_MANUID (0XD0)
#define REG_AC1 (0xAA) //便于理解,提高可阅读性
#define REG_AC2 (0xAC)
#define REG_AC3 (0xAE)
#define REG_AC4 (0xB0)
#define REG_AC5 (0xB2)
#define REG_AC6 (0xB4)
#define REG_B1 (0xB6)
#define REG_B2 (0xB8)
#define REG_MB (0xBA)
#define REG_MC (0xBC)
#define REG_MD (0xBE)
extern short ac1,ac2,ac3,b1,b2;//EEPROM的11个校正系数(全局变量)
extern unsigned shortac4,ac5,ac6;
extern short mb,mc,md;
void delay(uint32_t n);
void BMP180_Init(void);
long BMP180_ReadTemperature(void);
long BMP180_ReadPressure(void);
extern void BMP180_Calibration(longtemp,long press);
#endif //BMP180
#endif //_SENSOR_BMP180_H
传感器驱动文件sensor_bmp180.c: #include "sensor_BMP180.h"
#include "i2c_comm.h"
#include <stdio.h>
void delay(uint32_t n)
{
cyhal_system_delay_ms(n);
}
void BMP180_Init(void)
{
uint8_t manu_id=0;//uint8_t coeff[22];
manu_id=I2cReadRegister(BMP180_SA,REG_MANUID);
printf("ChipID=0x%x\r\n",manu_id);
if(manu_id==BMP180_MANUID)
{
ac1=I2cReadWord(BMP180_SA,REG_AC1);
ac2=I2cReadWord(BMP180_SA,REG_AC2);
ac3=I2cReadWord(BMP180_SA,REG_AC3);
ac4=I2cReadWord(BMP180_SA,REG_AC4);
ac5=I2cReadWord(BMP180_SA,REG_AC5);
ac6=I2cReadWord(BMP180_SA,REG_AC6);
b1=I2cReadWord(BMP180_SA,REG_B1);
b2=I2cReadWord(BMP180_SA,REG_B2);
mb=I2cReadWord(BMP180_SA,REG_MB);
mc=I2cReadWord(BMP180_SA,REG_MC);
md=I2cReadWord(BMP180_SA,REG_MD);
}
printf("%d%d %d %d %d %d %d %d %d %d %d\r\n",ac1,ac2,ac3,ac4,ac5,ac6,b1,b2,mb,mc,md);
}
long BMP180_ReadTemperature()
{
uint8_t tempdata[2];uint8_ti;
long ut;
I2cWriteRegister(BMP180_SA,REG_CTRL_MEAS,0x2E);//ADC
delay(50);
I2cReadRegisters(BMP180_SA,REG_OUT_MSB,tempdata,2);
ut=tempdata[1] | ((uint16_t)tempdata[0])<<8;
printf("Getut data:%d ",(int)ut);
for(i=0;i<2;i++)
printf("%d",tempdata);
return ut;
}
long BMP180_ReadPressure() //ultra low power mode
{
uint8_t pressdata[3];uint8_tn;
long up;
I2cWriteRegister(BMP180_SA,REG_CTRL_MEAS,0x34);//ADC
delay(50);
I2cReadRegisters(BMP180_SA,REG_OUT_MSB,pressdata,3);
up=((uint32_t)pressdata[2] | ((uint32_t)pressdata[1])<<8| \
((uint32_t)pressdata[0])<<16)>>(8-OSS);
printf("\r\nGetup data:%d",(int)up);
for(n=0;n<3;n++)
printf("%d",pressdata[n]);
return up;
}
extern void BMP180_Calibration(longtemp,long press)
{
long x1,x2,x3,b3,b5,b6;
unsigned longb4,b7,p;
long up,ut;
ut=BMP180_ReadTemperature();
up=BMP180_ReadPressure();
x1 = ((long)ut - (long)ac6)* (long)ac5 >> 15;
x2 = ((long) mc << 11) / (x1 + md);
b5 = x1 + x2;
temp = (b5 +8) >> 4;
b6 = b5 -4000;
x1 = (b2 * (b6* b6 >> 12)) >> 11;
x2 = ac2 * b6>> 11;
x3 = x1 + x2;
b3 = ((((long)ac1 * 4 + x3)<<OSS) + 2)/4;
x1 = ac3 * b6>> 13;
x2 = (b1 * (b6* b6 >> 12)) >> 16;
x3 = ((x1 +x2) + 2) >> 2;
b4 = (ac4 * (unsigned long)(x3 + 32768)) >> 15;
b7 = ((unsigned long)up - b3) * (50000 >> OSS);
if( b7 < 0x80000000)
p = (b7 * 2) / b4 ;
else
p = (b7 / b4) * 2;
x1 = (p>> 8) * (p >> 8);
x1 = (x1 *3038) >> 16;
x2 = (-7357 *(long)p) >> 16;
press = p +((x1 + x2 + 3791) >> 4);
printf("\n%ld%ld",temp,press);
printf("\nTemp:%ld.%ldDegC,Press:%ld Pa",temp/10,temp%10,press);
}
三、效果 有成功读出11个补偿系数、芯片ID和ADC原始值,但校准可能不太对,计算有问题: |
|