#include "myiic.h"
#include "delay.h"
//#include "led.h"
#include "stm32f10x.h"
#include "LPS22HB.h"
#include "math.h"
#include "sys.h"
#include <string.h>
#include <stdio.h>
#include "myiic.h"
#include "usart.h"
#include "delay.h"
#include "lps22hb_read_data_polling.h"
#include "stm32f10x_usart.h"
// 定义I2C引脚 - 可根据实际接线修改
#define I2C_SCL_PIN GPIO_Pin_1
#define I2C_SDA_PIN GPIO_Pin_0
#define I2C_GPIO_PORT GPIOB
// 初始化GPIO
void I2C_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// SCL和SDA都配置为开漏输出
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(I2C_GPIO_PORT, &GPIO_InitStructure);
// 初始状态拉高
GPIO_SetBits(I2C_GPIO_PORT, I2C_SCL_PIN | I2C_SDA_PIN);
}
// 产生I2C起始信号
//void I2C_SDA_HIGH(void)
//{
// SDA_OUT();
// GPIO_SetBits(GPIOB, GPIO_Pin_0);
//}
//void I2C_SDA_LOW(void)
//{
// SDA_OUT();
// GPIO_ResetBits(GPIOB, GPIO_Pin_0);
//}
//void I2C_SCL_HIGH(void)
//{
//
// GPIO_SetBits(GPIOB, GPIO_Pin_1);
//}
//void I2C_SCL_LOW(void)
//{
//
// GPIO_ResetBits(GPIOB, GPIO_Pin_1);
//}
void I2C_Start(void)
{
SDA_OUT(); // SDA设置为输出
I2C_SDA_HIGH();
I2C_SCL_HIGH();
delay_us(5);
I2C_SDA_LOW(); // START: SDA从高到低
delay_us(5);
I2C_SCL_LOW(); // 钳住I2C总线,准备发送或接收数据
}
// 产生I2C停止信号
void I2C_Stop(void)
{
SDA_OUT(); // SDA设置为输出
I2C_SCL_LOW();
I2C_SDA_LOW();
delay_us(5);
I2C_SCL_HIGH();
I2C_SDA_HIGH(); // STOP: SDA从低到高
delay_us(5);
}
// 等待ACK信号
uint8_t I2C_Wait_Ack(void)
{
uint8_t ucErrTime = 0;
SDA_IN(); // SDA设置为输入
I2C_SDA_HIGH(); delay_us(1);
I2C_SCL_HIGH(); delay_us(1);
while(GPIO_ReadInputDataBit(I2C_GPIO_PORT, I2C_SDA_PIN))
{
ucErrTime++;
if(ucErrTime > 250)
{
I2C_Stop();
return 1;
}
delay_us(1);
}
I2C_SCL_LOW(); // 时钟输出0
return 0;
}
// 产生ACK应答
void I2C_Ack(void)
{
I2C_SCL_LOW();
SDA_OUT();
I2C_SDA_LOW();
delay_us(2);
I2C_SCL_HIGH();
delay_us(2);
I2C_SCL_LOW();
}
// 不产生ACK应答
void I2C_NAck(void)
{
I2C_SCL_LOW();
SDA_OUT();
I2C_SDA_HIGH();
delay_us(2);
I2C_SCL_HIGH();
delay_us(2);
I2C_SCL_LOW();
}
// I2C发送一个字节
void I2C_Send_Byte(uint8_t txd)
{
uint8_t t;
SDA_OUT();
I2C_SCL_LOW(); // 拉低时钟开始数据传输
for(t = 0; t < 8; t++)
{
if((txd & 0x80) >> 7)
{
I2C_SDA_HIGH();
}
else
{
I2C_SDA_LOW();
}
txd <<= 1;
delay_us(2);
I2C_SCL_HIGH();
delay_us(2);
I2C_SCL_LOW();
delay_us(2);
}
}
// I2C读取一个字节
uint8_t I2C_Read_Byte(uint8_t ack)
{
uint8_t i, receive = 0;
SDA_IN(); // SDA设置为输入
for(i = 0; i < 8; i++)
{
I2C_SCL_LOW();
delay_us(2);
I2C_SCL_HIGH();
receive <<= 1;
if(GPIO_ReadInputDataBit(I2C_GPIO_PORT, I2C_SDA_PIN))
receive++;
delay_us(1);
}
if(!ack)
I2C_NAck(); // 发送nACK
else
I2C_Ack(); // 发送ACK
return receive;
}
uint8_t LPS22HB_Init(void)
{
uint8_t who_am_i;
uint8_t ctrl_reg1 = 0x50;
uint8_t ctrl_reg2 = 0x00;
// 读取WHO_AM_I寄存器验证设备
I2C_ReadReg(LPS22HB_I2C_ADDRESS, LPS22HB_WHO_AM_I, &who_am_i, 1);
USART_SendData(USART1, who_am_i);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
printf( "%02X",who_am_i);
if(who_am_i != 0xB1) // LPS22HB的WHO_AM_I值应为0xB1
{
return 0; // 初始化失败
USART_SendData(USART1, who_am_i);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
printf( "%02X",who_am_i);
}
// 配置CTRL_REG1: ODR=10Hz, 低通滤波器使能
I2C_WriteReg(LPS22HB_I2C_ADDRESS, LPS22HB_CTRL_REG1, &ctrl_reg1, 1);
// 配置CTRL_REG2: 单次转换模式禁用, FIFO使能
I2C_WriteReg(LPS22HB_I2C_ADDRESS, LPS22HB_CTRL_REG2, &ctrl_reg2, 1);
return 1; // 初始化成功
}
// 向LPS22HB写入数据
void I2C_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len)
{
I2C_Start();
// I2C_Send_Byte(dev_addr << 1 | 0); // 发送设备地址+写命令 0xB8
I2C_Send_Byte(0xB8);
I2C_Wait_Ack();
I2C_Send_Byte(reg_addr); // 发送寄存器地址
I2C_Wait_Ack();
while(len--)
{
I2C_Send_Byte(*data++); // 发送数据
I2C_Wait_Ack();
}
I2C_Stop();
}
// 从LPS22HB读取数据
void I2C_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len)
{
I2C_Start();
// I2C_Send_Byte(dev_addr << 1 | 0); // 发送设备地址+写命令(LPS22HB_ADDR << 1 | 0)
I2C_Send_Byte(0xB8);
I2C_Wait_Ack();
I2C_Send_Byte(reg_addr); // 发送寄存器地址
I2C_Wait_Ack();
I2C_Start();
// I2C_Send_Byte(dev_addr << 1| 1); // 发送设备地址+读命令
I2C_Send_Byte(0xB9);
I2C_Wait_Ack();
while(len)
{
if(len == 1)
*data++ = I2C_Read_Byte(0); // 最后一个字节发送NACK
else
*data++ = I2C_Read_Byte(1); // 非最后一个字节发送ACK
len--;
}
I2C_Stop();
}
// 读取气压数据(单位:hPa)
float LPS22HB_ReadPressure(void)
{
uint8_t buffer[3],press_xl,press_l,press_h;
int32_t pressure_raw;
float pressure_hPa;
// 读取气压数据(3字节: XL, L, H)
I2C_ReadReg(LPS22HB_I2C_ADDRESS, 0x28, &press_xl , 1);
I2C_ReadReg(LPS22HB_I2C_ADDRESS, 0x29, &press_l, 1);
I2C_ReadReg(LPS22HB_I2C_ADDRESS, 0x2A, &press_h, 1);
pressure_raw = (int32_t)((press_h << 16) | (press_l << 8) | press_xl);
// 组合24位原始数据
// pressure_raw = (int32_t)((buffer[2] << 16) | (buffer[1] << 8) | buffer[0]);
if (pressure_raw & 0x00800000) {
pressure_raw |= 0xFF000000; // 符号扩展
}
// printf( "%02X",press_h);
// printf( "%02X",press_l);
// printf( "%02X",press_xl);
// 转换为hPa (4096 LSB/hPa)
pressure_hPa = (float)pressure_raw / 4096.0f;
return pressure_hPa;
}
// 读取温度数据(单位:°C)
float LPS22HB_ReadTemperature(void)
{
uint8_t buffer[2],temp_l,temp_h;
int16_t temp_raw;
float temp_degC;
// 读取温度数据(2字节: L, H)
I2C_ReadReg(LPS22HB_I2C_ADDRESS, 0x2B, &temp_l, 1);
I2C_ReadReg(LPS22HB_I2C_ADDRESS, 0x2C, &temp_h, 1);
// printf( "%02X",temp_h);
// printf( "%02X",temp_l);
// 组合16位原始数据
temp_raw = (int16_t)(( temp_h<< 8) | temp_l);
// 转换为°C (100 LSB/°C)
temp_degC = (float)temp_raw / 100.0f;
return temp_degC;
}
/****************************************************************
函数名称:LPS22HB_Get_Altitude
函数功能:获取海拔高度值
入口参数:无
出口参数:altitude //int型 2字节,当前海拔高度值
备 注: 返回的高度值单位为厘米,调用时再换算成带小数的以米为单位的高度值
*****************************************************************/
double LPS22HB_Get_Altitude(float pressure)
{
double altitude;
//pressure=(float)pressure; //获取气压值
altitude=44330.0*(1-pow((double)pressure/101325,1/5.255)); //根据芯片手册提供的公式计算海拔高度
altitude*=100; //转换成厘米单位的高度值,调用时再换算成带小数的高度值,提高精度
return altitude;
}