本帖最后由 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原始值,但校准可能不太对,计算有问题: |