MS5805传感器的引脚及封装图如下:
通过C语言实现
内核代码
#include <linux/module.h> //所有模块都需要的头文件
#include <linux/init.h> // init和exit相关宏
#include <linux/kernel.h> // printk(),内核打印函数
#include <linux/delay.h> // 延时函数头文件
#include <linux/device.h> // 用于设备创建的函数头文件
#include <linux/fs.h> //和fops相关的头文件
#include <linux/cdev.h> //字符设备 初始化相关
#include <linux/version.h>
#include <linux/platform_device.h> //platform总线设备相关
#include <linux/err.h> //错误码相关
#include <linux/timer.h> //定时器相关
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#define DEV_NAME "ms5805"
// MS5805 device address
#define MS5805_ADDR 0x76 //0b1110110
// MS5805 device commands
#define MS5805_RESET_COMMAND 0x1E
#define MS5805_START_PRESSURE_ADC_CONVERSION 0x40
#define MS5805_START_TEMPERATURE_ADC_CONVERSION 0x50
#define MS5805_READ_ADC 0x00
// MS5805 commands
#define MS5805_PROM_ADDRESS_READ_ADDRESS_0 0xA0
#define MS5805_PROM_ADDRESS_READ_ADDRESS_1 0xA2
#define MS5805_PROM_ADDRESS_READ_ADDRESS_2 0xA4
#define MS5805_PROM_ADDRESS_READ_ADDRESS_3 0xA6
#define MS5805_PROM_ADDRESS_READ_ADDRESS_4 0xA8
#define MS5805_PROM_ADDRESS_READ_ADDRESS_5 0xAA
#define MS5805_PROM_ADDRESS_READ_ADDRESS_6 0xAC
#define MS5805_PROM_ADDRESS_READ_ADDRESS_7 0xAE
struct i2c_client *hi_client;
static struct i2c_board_info hi_info = {
I2C_BOARD_INFO("ms8858", MS5805_ADDR),
};
struct data_temp_pre
{
uint16_t C0;
uint16_t C1;
uint16_t C2;
uint16_t C3;
uint16_t C4;
uint16_t C5;
uint16_t C6;
uint32_t D1;
uint32_t D2;
};
void ms5805_init(void)
{
struct i2c_adapter *adapter;
int ret;
// 获取I2C适配器
adapter = i2c_get_adapter(2); // 使用第二个I2C总线
if (adapter == NULL) {
printk("Failed to get I2C adapter\n");
return -ENODEV;
}
// 创建I2C客户端
hi_client = i2c_new_device(adapter, &hi_info);
if (hi_client == NULL) {
printk("Failed to create I2C client\n");
return -ENODEV;
}
}
void ms5805_exit(void)
{
//卸载I2C客户端
if(hi_client != NULL){
i2c_unregister_device(hi_client);
}
}
uint16_t read_two_byte_value(struct i2c_client *client , uint8_t cmd)
{
unsigned char recv_buf[2] = {0, 0};
char sned_buf[1];
sned_buf[0] = cmd;
int ret;
// 发送命令字节到设备以读取数据
ret = i2c_master_send(client, sned_buf, 1);
if (ret < 0) {
pr_err("Failed to send command byte\n");
return 0; // 错误返回0
}
// 从设备中读取数据到缓冲区
ret = i2c_master_recv(client, recv_buf, sizeof(recv_buf));
if (ret < 0) {
pr_err("Failed to read data from device\n");
return 0; // 错误返回0
}
// 数据转换
uint16_t value = (uint16_t)(recv_buf[0] << 8 | recv_buf[1]);
return value;
}
uint32_t read_there_byte_value(struct i2c_client *client , uint8_t cmd)
{
unsigned char recv_buf[3] = {0, 0, 0};
char sned_buf[1];
sned_buf[0] = cmd;
int ret;
// 发送命令字节到设备以读取数据
ret = i2c_master_send(client, sned_buf, 1);
if (ret < 0) {
pr_err("Failed to send command byte\n");
return 0; // 错误返回0
}
// 从设备中读取数据到缓冲区
ret = i2c_master_recv(client, recv_buf, sizeof(recv_buf));
if (ret < 0) {
pr_err("Failed to read data from device\n");
return 0; // 错误返回0
}
// 数据转换
uint32_t value = (uint32_t)(recv_buf[0] << 16) | (uint32_t)(recv_buf[1] << 8) | (uint32_t)(recv_buf[2]);
return value;
}
int ms5805_write_command( struct i2c_client *client,uint8_t cmd)
{
char buf[1]; // 创建一个包含一个字节数据的缓冲区
buf[0] = cmd; // 将命令字节放入缓冲区
int ret = i2c_master_send(client , buf , 1);
return ret;
}
struct data_temp_pre ms5805_read_temperature_and_pressure(struct i2c_client *client)
{
struct data_temp_pre data_temp_pres;
ms5805_write_command(client,MS5805_RESET_COMMAND);
udelay(10);
data_temp_pres.C0 = read_two_byte_value(client,MS5805_PROM_ADDRESS_READ_ADDRESS_0);
data_temp_pres.C1 = read_two_byte_value(client,MS5805_PROM_ADDRESS_READ_ADDRESS_1);
data_temp_pres.C2 = read_two_byte_value(client,MS5805_PROM_ADDRESS_READ_ADDRESS_2);
data_temp_pres.C3 = read_two_byte_value(client,MS5805_PROM_ADDRESS_READ_ADDRESS_3);
data_temp_pres.C4 = read_two_byte_value(client,MS5805_PROM_ADDRESS_READ_ADDRESS_4);
data_temp_pres.C5 = read_two_byte_value(client,MS5805_PROM_ADDRESS_READ_ADDRESS_5);
data_temp_pres.C6 = read_two_byte_value(client,MS5805_PROM_ADDRESS_READ_ADDRESS_6);
ms5805_write_command(client,MS5805_START_PRESSURE_ADC_CONVERSION);
udelay(500);
data_temp_pres.D1 = read_there_byte_value(client,MS5805_READ_ADC);
ms5805_write_command(client,MS5805_START_TEMPERATURE_ADC_CONVERSION);
udelay(500);
data_temp_pres.D2 = read_there_byte_value(client,MS5805_READ_ADC);
return data_temp_pres;
}
static int ms5805_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Driver: ms5805 open\n");
return 0;
}
static ssize_t ms5805_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
printk(KERN_INFO "Driver: ms5805 read\n");
struct data_temp_pre data_temp_pre_copy;
data_temp_pre_copy = ms5805_read_temperature_and_pressure(hi_client);
if (copy_to_user(buff,&data_temp_pre_copy,sizeof(data_temp_pre_copy)))
{
printk(KERN_ERR "Failed to copy data to user space\n");
return -EFAULT;
}
return count;
}
static struct file_operations ms5805_fops = {
.owner = THIS_MODULE,
.open = ms5805_open,
.read = ms5805_read,
};
static struct miscdevice ms5805_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name =DEV_NAME,
.fops = &ms5805_fops,
};
static int __init ms5805_dev_init(void)
{
int ret = 0;
printk("insmod ms5805! func:= %s\n", __func__);
/* register MISC device */
if ((ret = misc_register(&ms5805_misc)))
{
printk("failed add a64_misc_dev_device\n");
return ret;
}
ms5805_init();
return 0;
}
static void __exit ms5805_dev_exit(void)
{
ms5805_exit();
misc_deregister(&ms5805_misc);
printk("rmmod ms5805! func:= %s\n", __func__);
}
module_init(ms5805_dev_init);
module_exit(ms5805_dev_exit);
MODULE_AUTHOR("liufeng");
MODULE_DESCRIPTION("helpera133 ms5805 Driver");
MODULE_LICENSE("GPL")
用户端读取实现
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
struct data_temp_pre
{
uint16_t C0;
uint16_t C1;
uint16_t C2;
uint16_t C3;
uint16_t C4;
uint16_t C5;
uint16_t C6;
uint32_t D1;
uint32_t D2;
};
int main() {
int fd = open("/dev/ms5805", O_RDONLY);
if (fd == -1) {
perror("Failed to open device");
return -1;
}
while (1)
{
struct data_temp_pre data;
int ret = read(fd, &data, sizeof(data));
if (ret == -1) {
perror("Failed to read from device");
close(fd);
return -1;
}
int32_t dT = data.D2 - data.C5 * 256;
int32_t TEMP = 2000 + (int64_t)dT * (int64_t)data.C6 / 8388608;
int64_t OFF = (int64_t)data.C2 * 131072 + (int64_t)data.C4 * (int64_t)dT / 64;
int64_t SENS = (int64_t)data.C1 * 65536 + (int64_t)data.C3 * (int64_t)dT / 128;
int32_t T2 = 0;
int64_t OFF2 = 0;
int64_t SENS2 = 0;
if (TEMP < 2000) {
T2 = 11 * ((int64_t)dT * (int64_t)dT) / 34359738368;
OFF2 = 31 * (((int64_t)TEMP - 2000) * ((int64_t)TEMP - 2000)) / 8;
SENS2 = 63 * (((int64_t)TEMP - 2000) * ((int64_t)TEMP - 2000)) / 32;
}
int32_t TEMP2 = TEMP - T2;
OFF2 = OFF - OFF2;
SENS2 = SENS - SENS2;
float pressure = (((((data.D1 * SENS2) / 2097152) - OFF2) / 32768)) / 100.0;
float cTemp = TEMP2 / 100.0;
float fTemp = cTemp * 1.8 + 32;
// 打印结构体中的每个数据
// printf("C0: %u\n", data.C0);
// printf("C1: %u\n", data.C1);
// printf("C2: %u\n", data.C2);
// printf("C3: %u\n", data.C3);
// printf("C4: %u\n", data.C4);
// printf("C5: %u\n", data.C5);
// printf("C6: %u\n", data.C6);
// printf("D1: %u\n", data.D1);
// printf("D2: %u\n", data.D2);
printf("Pressure: %.2f mbar\n", pressure);
printf("Temperature : %.2f C\n", cTemp);
printf("Temperature : %.2f F\n", fTemp);
printf("----------------------------\n");
sleep(1);
}
close(fd);
return 0;
}
实现结果截图
通过python代码进行实现
python代码
# Distributed with a free-will license.
# Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
# MS5805_02BA01
# This code is designed to work with the MS5805_02BA01_I2CADC I2C Mini Module available from ControlEverything.com.
# https://www.controleverything.com/products
import smbus
import time
MS5805_02BA01_I2CADDR = 0x76
# Get I2C bus
bus = smbus.SMBus(2)
# MS5805_02BA01 address, 0x76(118)
# 0x1E(30) Reset command
bus.write_byte(MS5805_02BA01_I2CADDR, 0x1E)
time.sleep(0.3)
# Read 12 bytes of calibration data
# Read pressure sensitivity
data = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0xA0, 2)
C0 = data[0] * 256 + data[1]
data = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0xA2, 2)
C1 = data[0] * 256 + data[1]
# Read pressure offset
data = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0xA4, 2)
C2 = data[0] * 256 + data[1]
# Read temperature coefficient of pressure sensitivity
data = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0xA6, 2)
C3 = data[0] * 256 + data[1]
# Read temperature coefficient of pressure offset
data = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0xA8, 2)
C4 = data[0] * 256 + data[1]
# Read reference temperature
data = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0xAA, 2)
C5 = data[0] * 256 + data[1]
# Read temperature coefficient of the temperature
data = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0xAC, 2)
C6 = data[0] * 256 + data[1]
# MS5805_02BA01 address, 0x76(118)
# 0x40(64) Pressure conversion(OSR = 256) command
bus.write_byte(MS5805_02BA01_I2CADDR, 0x40)
time.sleep(0.5)
# Read digital pressure value
# Read data back from 0x00(0), 3 bytes
# D1 MSB2, D1 MSB1, D1 LSB
value = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0x00, 3)
D1 = value[0] * 65536 + value[1] * 256 + value[2]
# MS5805_02BA01 address, 0x76(118)
# 0x50(64) Temperature conversion(OSR = 256) command
bus.write_byte(MS5805_02BA01_I2CADDR, 0x50)
time.sleep(0.5)
# Read digital temperature value
# Read data back from 0x00(0), 3 bytes
# D2 MSB2, D2 MSB1, D2 LSB
value = bus.read_i2c_block_data(MS5805_02BA01_I2CADDR, 0x00, 3)
D2 = value[0] * 65536 + value[1] * 256 + value[2]
dT = D2 - C5 * 256
TEMP = 2000 + dT * C6 / 8388608
OFF = C2 * 131072 + (C4 * dT) / 64
SENS = C1 * 65536 + (C3 * dT ) / 128
T2 = 0
OFF2 = 0
SENS2 = 0
if TEMP < 2000 :
T2 = 11 *(dT * dT) / 34359738368
OFF2 = 31 * ((TEMP - 2000) * (TEMP - 2000)) / 8
SENS2 = 63 * ((TEMP - 2000) * (TEMP - 2000)) / 32
TEMP2 = TEMP - T2
OFF2 = OFF - OFF2
SENS2 = SENS - SENS2
pressure = (((((D1 * SENS2) / 2097152) - OFF2) / 32768)) / 100.0
cTemp = TEMP2 / 100.0
fTemp = cTemp * 1.8 + 32
# Output data to screen
print ("C0 : %.2f " %C0)
print ("C1 : %.2f " %C1)
print ("C2 : %.2f " %C2)
print ("C3 : %.2f " %C3)
print ("C4 : %.2f " %C4)
print ("C5 : %.2f " %C5)
print ("C6 : %.2f " %C6)
print ("D1 : %.2f " %D1)
print ("D2 : %.2f " %D2)
print ("TEMP2 : %.2f " %TEMP2)
print ("OFF2 : %.2f " %OFF2)
print ("SENS2 : %.2f " %SENS2)
print ("Pressure : %.2f mbar" %pressure)
print ("Temperature in Celsius : %.2f C" %cTemp)
print ("Temperature in Fahrenheit : %.2f F" %fTemp)