talk is cheap, show you my code
SPL06.c
#include "SPL06.h"
//*************全局变量*************//
Factor_List* b_list; //存储过采样率对应的系数KP,KT
COEF_ValueStruct Coefficient = { 0 }; //存储校准系数
TEMP_InitTypedef TEMP_InitStructure = { 0 }; //温度测量初始化配置结构体
PSR_InitTypedef PSR_InitStructure = { 0 }; //大气压强测量初始化配置结构体
//*************1.初始化相关函数*************//
//*************1.1 链表初始化相关函数*******//
/**
* @name Factor_List* initList(void)
* @brief 初始化链表头节点,将头节点也利用起来,存储信息
* @param [NONE]
* @return [p] 返回创建的链表头节点地址
*/
Factor_List* initList(void)
{
Factor_List *p = (Factor_List*)malloc(sizeof(Factor_List));
p->OverSamplingRate = _SINGLE_OVERSAMPLING;
p->FACTOR = _SINGLE_SCALE_FACTOR;
p->next = NULL;
if (p == NULL) {
// 处理内存分配失败的情况
return NULL;
}
return p;
}
/**
* @name Factor_List* insertTail(Factor_List *l, uint8_t val, uint32_t Factor)
* @brief 向链表的末尾添加一个节点,即尾插法
* @param [Factor_List *list] 链表的起始节点
* [uint8_t val] 链表OverSamplingRate部分的值,对应过采样率的寄存器值
* [uint32_t Factor] 过采样率对应的比例因子
* @return 尾节点指针,由于数据量只有八个,且链表添加数据之后固定,为了简化代码,没有利用尾节点指针
*/
Factor_List* insertTail(Factor_List *l, uint8_t val, uint32_t Factor)
{
//先创建一个新节点
Factor_List *p = (Factor_List*)malloc(sizeof(Factor_List));
p->OverSamplingRate = val;
p->FACTOR = Factor;
p->next = NULL;
while(l->next != NULL) l = l->next;
l->next = p;
return p;
}
/**
* @name void Init_FactorList(void)
* @brief 初始化链表的所有数据,将过采样率及其对应的比例因子插入到链表中
* @param [NONE]
* @return [NONE]
*/
void Init_FactorList(void)
{
b_list = initList(); //_SINGLE_OVERSAMPLING的数据已经放入
insertTail(b_list, _2TIMES_OVERSAMPLING, _2TIMES_SCALE_FACTOR);
insertTail(b_list, _4TIMES_OVERSAMPLING, _4TIMES_SCALE_FACTOR);
insertTail(b_list, _8TIMES_OVERSAMPLING, _8TIMES_SCALE_FACTOR);
insertTail(b_list, _16TIMES_OVERSAMPLING, _16TIMES_SCALE_FACTOR);
insertTail(b_list, _32TIMES_OVERSAMPLING, _32TIMES_SCALE_FACTOR);
insertTail(b_list, _64TIMES_OVERSAMPLING, _64TIMES_SCALE_FACTOR);
insertTail(b_list, _128TIMES_OVERSAMPLING, _128TIMES_SCALE_FACTOR);
}
/**
* @brief 根据对应的过采样率寻找对应的比例因子
* @param [Factor_List *list] 要查找的链表
* [val] 用于查询的过采样率
* @return 返回的比例因子数值
*/
uint32_t FindFactor(Factor_List* l, uint8_t val)
{
while(l->OverSamplingRate != val)
{
l = l->next;
}
return l->FACTOR;
}
//*************1.2 SPL06初始化相关函数******//
/**
* @name uint8_t SPL06_Init(void)
* @brief SPL06初始化,包含采样模式,温度采样配置,大气压强采样配置,可以通过修改对应结构体成员来修改配置
* @return 0 配置成功
* 1 I2C通讯异常
* 2 配置采样模式失败,总线无应答
* 3 配置大气压强采样失败,总线无应答
* 4 配置温度采样失败,总线无应答
* 5 获取校正系数失败,可能是校正系数没有准备好,也可能是I2C通讯异常
*/
uint8_t SPL06_Init(void)
{
//1. 拉高SCL、SDA确保起始条件能够被正确发送
MyI2C_W_SCL(1);
MyI2C_W_SDA(1);
//2. 进行读写校验,验证I2C通讯
uint8_t write_buf[2] = {0x11, 0x13};
uint8_t read_buf[2];
MyI2C_WriteMultiRegister(SPL06_ADDRESS, PRS_CFG, 2, write_buf);
MyI2C_ReadMultiRegister(SPL06_ADDRESS, PRS_CFG, 2, read_buf);
for(uint8_t i = 0; i < 2; i++)
{
if(read_buf[i] != write_buf[i])
{
return 1;
}
}
//3. 确认I2C通信正常后,软复位芯片
MyI2C_WriteRegister(RESET, 0x89);
for(uint16_t i=0; i<1000; i++)
{
for(uint16_t j=0; j<2000; j++);
}
//4. 配置采样模式:连续采样大气压强和温度
if(SPL_OperatingModeInit(STRAT_CONTINUOUS_PSR_TEMP))
return 2;
//5. 配置大气压强采样频率,过采样率
PSR_InitStructure.MEASURE_RATE = _4HZ_MEASUREMENT; //采样频率
PSR_InitStructure.OVER_SAMPLING_TIMES = _64TIMES_OVERSAMPLING; //过采样率
if(SPL06_PSRInitStruct(&PSR_InitStructure))
return 3;
//6. 配置温度采样频率,过采样率
TEMP_InitStructure.MEASURE_RATE = _4HZ_MEASUREMENT; //采样频率
TEMP_InitStructure.OVER_SAMPLING_TIMES = _SINGLE_OVERSAMPLING; //过采样率
TEMP_InitStructure.SENSOR_SOURCE = _EXTERNAL_SENSOR;
if(SPL06_TEMPInitStruct(&TEMP_InitStructure))
return 2;
//7. 当大气压强过采样率>8时,必须启用P Shift
MyI2C_WriteRegister(CFG_REG, 0x04); // 启动P位移,0x04,禁用FIFO 0x06,启用FIFO
//8. 初始化KP、KT链表
Init_FactorList();
//9. 读取矫正系数,保存在Coefficient结构体中
if(GetCoefVal(&Coefficient) != 0)
return 5;
//10. 正常返回0
return 0;
}
/**
* @name uint8_t SPL06_PSRInitStruct(PSR_InitTypedef* PSR_InitStructure)
* @brief 配置大气压强测量控制寄存器,可配置采样频率,过采样率
* @param [PSR_InitStructure] 传入的结构体指针,包含配置信息
* @return 0 成功
* 1 失败
*/
uint8_t SPL06_PSRInitStruct(PSR_InitTypedef* PSR_InitStructure)
{
uint8_t config = 0x00;
config = PSR_InitStructure->MEASURE_RATE + PSR_InitStructure->OVER_SAMPLING_TIMES;
if(MyI2C_WriteRegister(PRS_CFG, (uint8_t)config))
{
return 1;
}
return 0;
}
/**
* @name uint8_t SPL06_TEMPInitStruct(TEMP_InitTypedef* TEMP_InitStructure)
* @brief 配置温度测量控制寄存器,可配置采样频率,过采样率
* @param [TEMP_InitStructure] 传入的结构体指针,包含配置信息
* @return 0 成功
* 1 失败
*/
uint8_t SPL06_TEMPInitStruct(TEMP_InitTypedef* TEMP_InitStructure)
{
uint8_t config = 0x00;
config = TEMP_InitStructure->SENSOR_SOURCE + TEMP_InitStructure->MEASURE_RATE \
+ TEMP_InitStructure->OVER_SAMPLING_TIMES;
if(MyI2C_WriteRegister(TMP_CFG, config))
{
return 1;
}
return 0;
}
/**
* @name uint8_t SPL_OperatingModeInit(MeasureModeConfig config)
* @brief 设置SPL06的测量模式,可以在@<! MeasureModeConfig >中查看可配置的测量模式
* @param [config] 具体见@<! MeasureModeConfig >
* @return 0 成功
* 1 失败
*/
uint8_t SPL_OperatingModeInit(MeasureModeConfig config)
{
if(MyI2C_WriteRegister(MEAS_CFG, config))
{
return 1;
}
return 0;
}
/**
* @name uint8_t COEF_CheckStatus(void)
* @brief 查询SPL06的矫正系数是否可读
* @return 0 可读
* 1 不可读
*/
uint8_t COEF_CheckStatus(void)
{
if((MyI2C_ReadRegister(MEAS_CFG) & 0x80) == 0x80) //如果bit[7]COFE_RDY为高,说明矫正系数可读
{
return 0;
}
return 1;
}
/**
* @brief 读取SPL06的ID
* @param [void]
* @return [ID] ID默认值
*/
uint8_t SPL06_ReadID(void)
{
return MyI2C_ReadRegister(ID);
}
/**
* @brief 获得出厂校准系数
* @param COEF_ValueStruct* COEF,系数结构体指针,用于存储系数
* @return 0 获取成功
* 1 获取失败,读取过程出错,但矫正系数本身可以被读
* 2 获取失败,矫正系数没有准备就绪
*/
uint8_t GetCoefVal(COEF_ValueStruct* COEF)
{
uint8_t buffer[18] = { 0 };
if(COEF_CheckStatus() == 0)
{
//开始读取矫正系数
if(MyI2C_ReadMultiRegister(SPL06_ADDRESS, COEF_C0, 18, buffer))
{
return 1;
}
}else{
return 2;
}
//将校正系数正确存放到变量中
COEF->C0 = COEF->raw_C0 = (uint16_t)((buffer[0] << 4) | ((buffer[1] & 0xF0) >> 4)); // 12-bit value
COEF->C1 = COEF->raw_C1 = (uint16_t)(((buffer[1] & 0x0F) << 8) | buffer[2]); // 12-bit value
COEF->C00 = COEF->raw_C00 = (uint32_t)((buffer[3] << 12) | (buffer[4] << 4) | ((buffer[5] & 0xF0) >> 4)); // 20-bit value
COEF->C10 = COEF->raw_C10 = (uint32_t)((buffer[5] & 0x0F) << 16 | buffer[6] << 8 | buffer[7]); // 20-bit value
COEF->C01 = COEF->raw_C01 = (uint16_t)(buffer[8] << 8 | buffer[9]);
COEF->C11 = COEF->raw_C11 = (uint16_t)(buffer[10] << 8 | buffer[11]);
COEF->C20 = COEF->raw_C20 = (uint16_t)(buffer[12] << 8 | buffer[13]);
COEF->C21 = COEF->raw_C21 = (uint16_t)(buffer[14] << 8 | buffer[15]);
COEF->C30 = COEF->raw_C30 = (uint16_t)(buffer[16] << 8 | buffer[17]);
//这些数据都是以补码形式存放,如果为负数,应该将其转换
if(COEF->raw_C0 & 0x800) COEF->C0 = (COEF->raw_C0 - Total_Number_12);
if(COEF->raw_C1 & 0x800) COEF->C1 = (COEF->raw_C1 - Total_Number_12);
if(COEF->raw_C00 & 0x80000) COEF->C00 = COEF->raw_C00 - Total_Number_20;
if(COEF->raw_C10 & 0x80000) COEF->C10 = COEF->raw_C10 - Total_Number_20;
if(COEF->raw_C01 & 0x8000) COEF->C01 = COEF->raw_C01 - Total_Number_16;
if(COEF->raw_C11 & 0x8000) COEF->C11 = COEF->raw_C11 - Total_Number_16;
if(COEF->raw_C20 & 0x8000) COEF->C20 = COEF->raw_C20 - Total_Number_16;
if(COEF->raw_C21 & 0x8000) COEF->C21 = COEF->raw_C21 - Total_Number_16;
if(COEF->raw_C30 & 0x8000) COEF->C30 = COEF->raw_C30 - Total_Number_16;
return 0;
}
/**
* @brief 获取经过出厂校准系数补偿过的大气压强值,温度值
* @param [float* baroValue] 接收大气压强值的浮点数,单位: 百帕(hpa)
* [float* tempValue] 接收温度值的浮点数,单位: 摄氏度(℃)
* [COEF_ValueStruct* COEF] 校准系数结构体指针
* @return 0 获取成功
* 1 获取失败,I2C通讯异常
*/
uint8_t GetCompensatedVal(float* baroValue, float* tempValue, COEF_ValueStruct* COEF)
{
//1. 获取raw数据
uint8_t arr_temp[6] = { 0 };
uint32_t rawBaroValue = 0, rawTempValue = 0;
int32_t Baro, Temp;
if(MyI2C_ReadMultiRegister(SPL06_ADDRESS, PSR_B2, 6, arr_temp))//一次性读取大气压强值、温度值的6个寄存器
{
return 1;
}
rawBaroValue = (arr_temp[0] << 16) + (arr_temp[1] << 8) + (arr_temp[2]); //24bit有符号数
rawTempValue = (arr_temp[3] << 16) + (arr_temp[4] << 8) + (arr_temp[5]);
Baro = rawBaroValue & 0x00FFFFFF;
Temp = rawTempValue & 0x00FFFFFF;
if(rawBaroValue & 0x80000) Baro = rawBaroValue - Total_Number_24; //如果最高位为1,转化为负数
if(rawTempValue & 0x80000) Temp = rawTempValue - Total_Number_24;
//2. 根据过采样率选择对应的KP,KT系数
volatile uint32_t KP, KT;
float Praw_Sc, Traw_Sc;
KP = FindFactor(b_list, PSR_InitStructure.OVER_SAMPLING_TIMES); //在初始化的链表中寻找对应的比例因子
KT = FindFactor(b_list, TEMP_InitStructure.OVER_SAMPLING_TIMES);
//3. 带入公式求得校准后的数据
Praw_Sc = (float)Baro / KP;
Traw_Sc = (float)Temp / KT;
//4. 将数据传递到地址中
*baroValue = COEF->C00 + Praw_Sc * (COEF->C10 + Praw_Sc * ( COEF->C20 + Praw_Sc * COEF->C30)) + Traw_Sc * COEF->C01 + Traw_Sc * Praw_Sc * (COEF->C11 + Praw_Sc * COEF->C21);
*baroValue /= 100; //将压强值转化为hpa
*tempValue = COEF->C0 * 0.5f + COEF->C1 * Traw_Sc;
return 0;
}
/**
* @brief 将大气压强值转化为高度值
* @param [float P] 大气压强值,单位hpa
* @return -1 输入大气压强值错误
* Altitude 单精度浮点数,返回海拔高度值,单位m
*/
float getAltitude(float P)
{
P *= 100;
float Altitude;
if(P > 30000 && P < 200000)
{
Altitude = 44330.0f * (1.0f - (float)pow(P / P0, 1.0/5.255));
}else{
return 0;
}
return Altitude;
}
//*************快速排序算法*************//
void swap(float* a, float* b) {
float t = *a;
*a = *b;
*b = t;
}
int partition(float arr[], int low, int high) {
float pivot = arr[high]; // 选择最后一个元素作为基准
int i = (low - 1); // 小于基准的元素的索引
for (int j = low; j < high; j++) {
// 如果当前元素小于或等于基准
if (arr[j] <= pivot) {
i++; // 增加小于基准的元素的索引
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void quickSort(float arr[], int low, int high) {
if (low < high) {
// pi 是 partitioning index, arr[p] 现在位于正确位置
int pi = partition(arr, low, high);
// 分别对基准左右两边的子数组进行递归排序
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
/**
* @name float AltitudeFilter(float newAltitude)
* @brief 对计算得到校准后的高度值进一步滤波,采用快速排序+中值均值滤波
* @param [float newAltitude] 采集到的新数据
* @return [filterdAltitude] 滤波后的数据
*/
float AltitudeFilter(float newAltitude)
{
static float AltitudeRawArray[FILTER_MAX_SIZE] = { 0 }; //原始数据
static float AltitudeBuffer[FILTER_MAX_SIZE] = { 0 }; //排序缓冲数组
float filterdAltitude; //滤波后数据
//把原始数组里的数据前移
for(uint8_t i = 0; i < FILTER_MAX_SIZE - 1; i++)
{
AltitudeRawArray[i] = AltitudeRawArray[i + 1];
}
//更新数据
AltitudeRawArray[FILTER_MAX_SIZE - 1] = newAltitude;
//将更新的数据拷贝给缓冲排序数组
memcpy(&AltitudeBuffer, &AltitudeRawArray, sizeof(AltitudeRawArray));
//快速排序
quickSort(AltitudeBuffer, 0, FILTER_MAX_SIZE - 1);
//掐头去尾取中间,去掉前三分之一和后三分之一,取中间平均值
float bufferSum = 0;
for(uint8_t i = FILTER_MAX_SIZE / 3; i < FILTER_MAX_SIZE * 2/3; i++)
{
bufferSum += AltitudeBuffer[i];
}
filterdAltitude = bufferSum / (FILTER_MAX_SIZE / 3);
return filterdAltitude;
}
SPL06.h
#ifndef __SPL06_H
#define __SPL06_H
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "MyI2C.h"
//************自然值************//
#define P0 101325.0f //标准大气压强值
//************用于负数二补数转换************//
#define Total_Number_24 16777216.0
#define Total_Number_20 1048576.0
#define Total_Number_16 65536.0
#define Total_Number_12 4096.0
//************REGISTER ADDRESS************//
//仅列出了部分寄存器组,通过读写多个寄存器实现对所有寄存器的操作,如果需要更多的寄存器请参考datasheet
#define PSR_B2 0x00
#define PSR_B1 0x01
#define PSR_B0 0x02
#define TMP_B2 0x03
#define TMP_B1 0x04
#define TMP_B0 0x05
#define PRS_CFG 0x06
#define TMP_CFG 0x07
#define MEAS_CFG 0x08
#define CFG_REG 0x09
#define INT_STS 0x0A
#define FIFO_STS 0x0B
#define RESET 0x0C
#define ID 0x0D
#define COEF_C0 0x10
#define COEF_C00 0x13
#define COEF_C10 0x17
#define COEF_C01 0x18
#define COEF_C11 0x1A
#define COEF_C20 0x1C
#define COEF_C21 0x1E
#define COEF_C30 0x20
//************SPL06 I2C ADDRESS INITIALIZE************//
#define SPL06_ADDRESS 0x77 //SDO High -> 0x77, SDO Low -> 0x76
#define SPL06_ADDRESS_W (SPL06_ADDRESS<<1)|0x00
#define SPL06_ADDRESS_R (SPL06_ADDRESS<<1)|0x01
//************PRESSSURE & TEMPERATURE CONFIG************//
//bit[7] only accessiable for temperature config
#define _INTERNAL_SENSOR 0x00
#define _EXTERNAL_SENSOR 0x80
//bit[6:4] MEASURE_RATE for all
#define _1HZ_MEASUREMENT 0x00
#define _2HZ_MEASUREMENT 0x10
#define _4HZ_MEASUREMENT 0x20
#define _8HZ_MEASUREMENT 0x30
#define _16HZ_MEASUREMENT 0x40
#define _32HZ_MEASUREMENT 0x50
#define _64HZ_MEASUREMENT 0x60
#define _128HZ_MEASUREMENT 0x70
//bit[3:0] OVER_SAMPLING_TIMES for all
#define _SINGLE_OVERSAMPLING 0x00
#define _2TIMES_OVERSAMPLING 0x01
#define _4TIMES_OVERSAMPLING 0x02
#define _8TIMES_OVERSAMPLING 0x03
#define _16TIMES_OVERSAMPLING 0x04
#define _32TIMES_OVERSAMPLING 0x05
#define _64TIMES_OVERSAMPLING 0x06
#define _128TIMES_OVERSAMPLING 0x07
//************SCALE FACTOR************//
//存放KP、KT的数据集合,该数值与过采样率(OVER_SAMPLING_TIMES)相关
#define _SINGLE_SCALE_FACTOR 524288 //单次过采样对应scaleFactor
#define _2TIMES_SCALE_FACTOR 1572864 //2次过采样对应scaleFactor
#define _4TIMES_SCALE_FACTOR 3670016 //4次过采样对应scaleFactor
#define _8TIMES_SCALE_FACTOR 7864320 //8次过采样对应scaleFactor
#define _16TIMES_SCALE_FACTOR 253952 //16次过采样对应scaleFactor
#define _32TIMES_SCALE_FACTOR 516096 //32次过采样对应scaleFactor
#define _64TIMES_SCALE_FACTOR 1040384 //64次过采样对应scaleFactor
#define _128TIMES_SCALE_FACTOR 2088960 //128次过采样对应scaleFactor
//************滤波最大缓冲数************//
#define FILTER_MAX_SIZE 32
typedef struct
{
uint8_t MEASURE_RATE; //see @MEASURE_RATE
uint8_t OVER_SAMPLING_TIMES; //see @OVER_SAMPLING_TIMES
} PSR_InitTypedef;
typedef struct
{
uint8_t MEASURE_RATE;
uint8_t OVER_SAMPLING_TIMES;
uint8_t SENSOR_SOURCE;
} TEMP_InitTypedef;
//校准系数: coefficient
typedef struct
{
uint16_t raw_C0;
uint16_t raw_C1;
uint32_t raw_C00;
uint32_t raw_C10;
uint16_t raw_C01;
uint16_t raw_C11;
uint16_t raw_C20;
uint16_t raw_C21;
uint16_t raw_C30;
int16_t C0;
int16_t C1;
int32_t C00;
int32_t C10;
int16_t C01;
int16_t C11;
int16_t C20;
int16_t C21;
int16_t C30;
} COEF_ValueStruct;
//传感器测量模式
typedef enum
{
STANDBY = 0x00, //休眠
START_SINGLE_PSR, //单次转换大气压强值
START_SINGLE_TEMP, //单词转换温度值
STRAT_CONTINUOUS_PSR = 0x05, //连续转换大气压强值
STRAT_CONTINUOUS_TEMP, //连续转换温度值
STRAT_CONTINUOUS_PSR_TEMP = 0x07, //连续转换大气压强值和温度值
} MeasureModeConfig;
//定义过采样率对应的比例系数链表
typedef struct node
{
/* data */
uint8_t OverSamplingRate;
uint32_t FACTOR;
struct node* next;
} Factor_List;
extern Factor_List* b_list; //声明比例系数链表存在
extern COEF_ValueStruct Coefficient; //声明校准系数存在
extern TEMP_InitTypedef TEMP_InitStructure; //声明温度测量初始化配置结构体
extern PSR_InitTypedef PSR_InitStructure; //声明大气压强测量初始化配置结构体
//**********************<对外API,重要!>*********************//
//配置好GPIO引脚和IIC通讯地址后,依次调用下面四个函数即可得到高度值
uint8_t SPL06_Init(void);
uint8_t GetCompensatedVal(float* baroValue, float* tempValue, COEF_ValueStruct* COEF);//计算出气压计的单位为hpa
float getAltitude(float P);
float AltitudeFilter(float newAltitude);
//*********************链表初始化*********************//
Factor_List* initList(void);
Factor_List* insertTail(Factor_List *l, uint8_t val, uint32_t Factor);
void Init_FactorList(void);
uint32_t FindFactor(Factor_List* l, uint8_t val);
//*********************传感器初始化*********************//
uint8_t SPL06_PSRInitStruct(PSR_InitTypedef* PSR_InitStructure);
uint8_t SPL06_TEMPInitStruct(TEMP_InitTypedef* TEMP_InitStructure);
uint8_t SPL_OperatingModeInit(MeasureModeConfig config);
//*********************传感器状态获取*******************//
uint8_t COEF_CheckStatus(void);
//*********************传感器内部数据读取***************//
uint8_t GetCoefVal(COEF_ValueStruct* COEF);
uint8_t SPL06_ReadID(void);
#endif
MyI2C.c(基于江协科技)
#include "main.h" // Device header
#include "Delay.h"
#include "MyI2C.h"
void MyI2C_W_SCL(uint8_t BitValue)
{
HAL_GPIO_WritePin(BARO_SCL_GPIO_Port, BARO_SCL_Pin, (GPIO_PinState)BitValue);
}
void MyI2C_W_SDA(uint8_t BitValue)
{
HAL_GPIO_WritePin(BARO_SDA_GPIO_Port, BARO_SDA_Pin, (GPIO_PinState)BitValue);
}
uint8_t MyI2C_R_SDA(void)
{
uint8_t BitValue;
BitValue = HAL_GPIO_ReadPin(BARO_SDA_GPIO_Port, BARO_SDA_Pin);
return BitValue;
}
void MyI2C_Start(void)
{
MyI2C_W_SDA(1);
MyI2C_W_SCL(1);
MyI2C_W_SDA(0);
MyI2C_W_SCL(0);
}
void MyI2C_Stop(void)
{
MyI2C_W_SDA(0);
MyI2C_W_SCL(1);
MyI2C_W_SDA(1);
}
void MyI2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i ++)
{
MyI2C_W_SDA(!!(Byte & (0x80 >> i)));
MyI2C_W_SCL(1);
MyI2C_W_SCL(0);
}
}
uint8_t MyI2C_ReceiveByte(void)
{
uint8_t i, Byte = 0x00;
MyI2C_W_SDA(1);
for (i = 0; i < 8; i ++)
{
MyI2C_W_SCL(1);
if (MyI2C_R_SDA()){Byte |= (0x80 >> i);}
MyI2C_W_SCL(0);
}
return Byte;
}
void MyI2C_SendAck(uint8_t AckBit)
{
MyI2C_W_SDA(AckBit);
MyI2C_W_SCL(1);
MyI2C_W_SCL(0);
}
uint8_t MyI2C_ReceiveAck(void)
{
uint8_t AckBit;
MyI2C_W_SDA(1);
MyI2C_W_SCL(1);
AckBit = MyI2C_R_SDA();
MyI2C_W_SCL(0);
return AckBit;
}
uint8_t MyI2C_WriteRegister(uint8_t RegAddr, uint8_t byte)
{
MyI2C_Start(); //启动总线
MyI2C_SendByte(SPL06_ADDRESS_W); //发送写地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
MyI2C_SendByte(RegAddr); //要写入的寄存器地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
MyI2C_SendByte(byte);
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
MyI2C_Stop();
return 0;
}
uint8_t MyI2C_ReadRegister(uint8_t RegAddr)
{
MyI2C_Start(); //启动总线
MyI2C_SendByte(SPL06_ADDRESS_W); //发送写地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
MyI2C_SendByte(RegAddr); //要写入的寄存器地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
MyI2C_Start(); //启动总线
MyI2C_SendByte(SPL06_ADDRESS_R); //发送读地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
uint8_t byte = MyI2C_ReceiveByte();
MyI2C_SendAck(1);
MyI2C_Stop();
return byte;
}
uint8_t MyI2C_ReadMultiRegister(uint8_t I2CAddr, uint8_t RegAddr, uint8_t length, uint8_t* temp)
{
uint8_t AddrW,AddrR;
AddrW = I2CAddr<<1;
AddrR = (I2CAddr<<1) + 1;
MyI2C_Start(); //启动总线
MyI2C_SendByte(AddrW); //发送写地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
MyI2C_SendByte(RegAddr); //要写入的寄存器地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
MyI2C_Start(); //启动总线
MyI2C_SendByte(AddrR); //发送读地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
for(uint8_t i = 0; i < length; i++)
{
*(temp + i) = MyI2C_ReceiveByte();
if(i < length - 1)
{
MyI2C_SendAck(0);
}else{
MyI2C_SendAck(1);
}
}
MyI2C_Stop();
return 0;
}
uint8_t MyI2C_WriteMultiRegister(uint8_t I2CAddr, uint8_t RegAddr, uint8_t length, uint8_t* temp)
{
uint8_t AddrW;
AddrW = I2CAddr<<1;
MyI2C_Start(); //启动总线
MyI2C_SendByte(AddrW); //发送写地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
MyI2C_SendByte(RegAddr); //要写入的寄存器地址
if(MyI2C_ReceiveAck() == 1) //未应答
return 1;
for(uint8_t i = 0; i < length; i++)
{
MyI2C_SendByte(*(temp + i));
if(i < length - 1)
{
MyI2C_SendAck(0);
}else{
MyI2C_SendAck(1);
}
}
MyI2C_Stop();
return 0;
}
MyI2C.h
#ifndef __MYI2C_H
#define __MYI2C_H
#include "main.h"
#include "Delay.h"
#include "SPL06.h"
void MyI2C_W_SCL(uint8_t BitValue);
void MyI2C_W_SDA(uint8_t BitValue);
uint8_t MyI2C_R_SDA(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
uint8_t MyI2C_ReceiveByte(void);
void MyI2C_SendAck(uint8_t AckBit);
uint8_t MyI2C_ReceiveAck(void);
uint8_t MyI2C_ReadRegister(uint8_t RegAddr);
uint8_t MyI2C_WriteRegister(uint8_t RegAddr, uint8_t byte);
uint8_t MyI2C_ReadMultiRegister(uint8_t I2CAddr, uint8_t RegAddr, uint8_t length, uint8_t* temp);
uint8_t MyI2C_WriteMultiRegister(uint8_t I2CAddr, uint8_t RegAddr, uint8_t length, uint8_t* temp);
#endif
main.c
#include "main.h"
#include "SPL06.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
uint8_t ack = SPL06_Init();
float height, filtredHeight;
float baro, temp;
while(1)
{
//获取补偿后的值
GetCompensatedVal(&baro, &temp, &Coefficient);
//转化为高度值
height = getAltitude(baro);
//排序,中值平均滤波,可以在SPL06.h中修改FILTER_MAX_SIZE来调整滤波
filtredHeight = AltitudeFilter(height);
rt_thread_delay(250);
}
}