DS18B20温度传感器在开发板ubuntu下的实时温度获取

DS18B20传感器的引脚及封装图如下:

内核代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/miscdevice.h>
 
#include <asm/io.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
 
 
#define DQ_IN_GPIO      40     // 操作DS18B20的GPIO
 
/*********************************************DS18B20************************************************/
/* 1.复位信号 */
void DS18B20_Rst(void)
{
    int ret = gpio_request(DQ_IN_GPIO, "DQ_OUT");
    if (ret != 0)
    {
        printk("Rst gpio_request fail !\n");
        return;
    }
    
    gpio_direction_output(DQ_IN_GPIO, 0);
    udelay(750);		//拉低750us
    
    gpio_direction_output(DQ_IN_GPIO, 1);
    udelay(15);			//拉高15us
    
    gpio_free(DQ_IN_GPIO);
}
		
/* 2.应答信号 */
int DS18B20_CheckAck(void)
{
    int retry = 0;
    
    int ret = gpio_request(DQ_IN_GPIO, "DQ_OUT");
    if (ret != 0)
    {
        printk("Check gpio_request fail !\n");
        return;
    }
    gpio_direction_input(DQ_IN_GPIO);
 
    while(gpio_get_value(DQ_IN_GPIO) & (retry < 200))
    {
        retry++;
        udelay(1);
    };
 
    if(retry >= 200){
        gpio_free(DQ_IN_GPIO);
        return -1;
    }
 
    retry = 0;
    while(!gpio_get_value(DQ_IN_GPIO) & (retry < 240))
    {
        retry++;
        udelay(1);
    }
 
    if(retry >= 240){
        gpio_free(DQ_IN_GPIO);
        return -1;
    }
 
    gpio_free(DQ_IN_GPIO);
 
    return 0;
}
 
/* 3.写时序,一个字节 */
void DS18B20_Write_Byte(int dat)
{
    int j,testb;
    gpio_request(DQ_IN_GPIO, "DQ_OUT");
    
    for(j = 0; j < 8; j++){
        testb = dat & 0x1;
        dat >>= 1;
        
        if(testb){  // 写1时序
            gpio_direction_output(DQ_IN_GPIO, 0);				
            udelay(2);
        
            gpio_direction_output(DQ_IN_GPIO, 1);
            udelay(60);
        } else {    // 写0时序
            gpio_direction_output(DQ_IN_GPIO, 0);
            udelay(60);
 
            gpio_direction_output(DQ_IN_GPIO, 1);
            udelay(2);
        }
    }
    
    gpio_free(DQ_IN_GPIO);
}
 
/* 4.读一bit数据 */
int DS18B20_Read_Bit(void)
{
    int data;
    gpio_request(DQ_IN_GPIO, "DQ_OUT");
    
    gpio_direction_output(DQ_IN_GPIO, 0);
    udelay(2);
    
    gpio_direction_output(DQ_IN_GPIO, 1);
    udelay(12);
    
    // gpio_free(DQ_IN_GPIO);
    
    // gpio_request(DQ_IN_GPIO, "DQ_IN");
    
    gpio_direction_input(DQ_IN_GPIO);
    
    if(gpio_get_value(DQ_IN_GPIO))
        data = 1;
    else
        data = 0;
    udelay(50);
    
    gpio_free(DQ_IN_GPIO);
 
    return data;
}
 
/* 5.读一个字节的数据 */
int DS18B20_Read_Byte(void)
{
    int i, j, dat = 0;
    
    for(i = 0; i < 8; i++)
    {
        j = DS18B20_Read_Bit();
        
        //低位先行,j左移7位,把最低位赋给dat,同时dat左移1位,把低位右移,循环8次你懂的
        dat = (j << 7) | (dat >> 1);
    }
 
    return dat;
}
 
/* 6.温度转换 */
void DS18B20_Start(void)
{
    DS18B20_Rst();
    DS18B20_CheckAck();
    DS18B20_Write_Byte(0xcc);
    DS18B20_Write_Byte(0x44);
}
 
/* 7.处理温度信息 */
int DS18B20_Get_temp(void)
{
    int temp = 0,
        TL  = 0, 
        TH  = 0;
    
    DS18B20_Start();
    DS18B20_Rst();
    DS18B20_CheckAck();
    DS18B20_Write_Byte(0xcc);
    DS18B20_Write_Byte(0xbe);
 
    TL = DS18B20_Read_Byte();
    TH = DS18B20_Read_Byte();
    if(TH > 7){
        TH = ~TH;
        TL = ~TL;
        temp = 0;
    }else{
        temp = 1;
    }
 
    temp = TH;
    temp <<= 8;
    temp += TL;
    
	/**
	 * 内核不支持浮点运算,如果在内核里做计算会丢失小数部分
	 * 所以计算留给用户程序来完成,这里直接传输原始数据即可
	*/ 
    if(temp){
        return temp;
    }else{
        return ~temp + 1;
    }
}
/*****************************************************************************************************/
 
int 
ds18b20_open(struct inode *inode, struct file *filp)
{
    // 硬件初始化
    /*do nothing*/
 
    return 0;
}
 
ssize_t 
ds18b20_read(struct file *filp, char __user *buf, size_t count, loff_t *fpos)
{
    int temp_buf = 0;
    temp_buf = DS18B20_Get_temp();
    if (copy_to_user(buf, &temp_buf, sizeof(temp_buf))) {
        printk(KERN_ERR "Failed to copy data to user space\n");
        return -EFAULT;
    }
 
    return count;
}
 
const struct file_operations ds18b20_fops = {
    .open   = ds18b20_open,
    .read   = ds18b20_read,
};
 
struct miscdevice ds18_misc = {
    .minor  = MISC_DYNAMIC_MINOR,
    .name   = "ds18b20",
    .fops   = &ds18b20_fops,
};
 
static void __exit
ds18b20_drv_exit(void)
{
    misc_deregister(&ds18_misc);
}
 
static int __init
ds18b20_drv_init(void)
{
    // 注册杂项设备,因为比直接的普通字符设备少写好多代码
    int ret = misc_register(&ds18_misc);
    if(ret < 0){
        printk("ds18b20_misc register failed !\n");
        return -EINVAL;
    }else {
        printk("insmod ds18b20_misc! func:= %s\n", __func__);
    }
 
    return 0;
}
 
module_init(ds18b20_drv_init);
module_exit(ds18b20_drv_exit);
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liufeng");
MODULE_DESCRIPTION("helpera133 ds18b20 Driver");

用户端代码

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#define DS18B20 "/dev/ds18b20" // 你需要替换为实际的文件路径

int main() {
    int fd = open(DS18B20, O_RDWR);
    if (fd == -1) {
        perror("open");
        return 1; // 文件打开失败,程序退出
    }

    while (1) {
        int temp = 0;
        if (read(fd, &temp, sizeof(temp)) != sizeof(temp)) {
            perror("read");
            close(fd);
            return 1; // 读取失败,程序退出
        }
        int a = (int)(temp * 0.65);
        if (a > -551 && a < 1251) {
            printf("<APP> temp: %d.%d C\n", a / 10, a % 10);
            printf("----------------------------\n");
        }
        sleep(1); // 休眠一秒后再次读取温度
    }

    close(fd);
    return 0;
}

读取温度结结果截图

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值