1、温度采集模块
// env/ds18b20.zip
1.1 硬件 温度传感器 ' ds18b20'
一线式设备( 1-wire)
' 独立式供电': VDD接独立的电源
' 寄生供电': DQ连接到GPIO管脚
当GPIO管脚上为高电平时 充电 (内部有电容)
当GPIO管脚上为低电平时 放电 来维持ds18b20工作所需要的能量
寄生电源优势: 布线简单
驱动程序中要时刻注意是否应该拉高DQ
一个GPIO管脚上可以有多个ds18b20
1.2 硬件驱动
1.2.1 ds18b20的数据手册
1.2.1.1 ds18b20的组成结构
1.2.1.2 通信方式
// P10
必要步骤:
1)初始化
reset信号
presence信号
2)发送rom command
match rom
发送命令0x55 64bit ID
一线式上有多个DS18B20
skip rom
发送命令0xcc
驱动程序例子ds18b20_drv.c 一线式上只有一个ds18b20
3) function command
convert T :开启温度转换
read : 读9个字节的RAM
write : 写温度值之后的RAM
P15:
复位 存在信号的时序
读写一个bit的时序
如何开始温度转换,并获取温度值
example1: 温度转换 读取温度
发送reset
接收响应信号
发送skip rom
发送开启温度转换的命令
延时等待转换完成
发送reset
接收响应信号
发送skip rom
发送读命令
接收数据
example2: 配置精度
1.3 应用程序
gui_client
给服务器发送读温度的命令
接收服务器返回的温度值值
显示温度值 Qlabel->setText("32")
server
如果接收到的命令读温度的
参考ds18b20_test.c读取温度值
把读到的温度值返回给client
// env/ds18b20.zip
1.1 硬件 温度传感器 ' ds18b20'
一线式设备( 1-wire)
' 独立式供电': VDD接独立的电源
' 寄生供电': DQ连接到GPIO管脚
当GPIO管脚上为高电平时 充电 (内部有电容)
当GPIO管脚上为低电平时 放电 来维持ds18b20工作所需要的能量
寄生电源优势: 布线简单
驱动程序中要时刻注意是否应该拉高DQ
一个GPIO管脚上可以有多个ds18b20
1.2 硬件驱动
1.2.1 ds18b20的数据手册
1.2.1.1 ds18b20的组成结构
1.2.1.2 通信方式
// P10
必要步骤:
1)初始化
reset信号
presence信号
2)发送rom command
match rom
发送命令0x55 64bit ID
一线式上有多个DS18B20
skip rom
发送命令0xcc
驱动程序例子ds18b20_drv.c 一线式上只有一个ds18b20
3) function command
convert T :开启温度转换
read : 读9个字节的RAM
write : 写温度值之后的RAM
P15:
复位 存在信号的时序
读写一个bit的时序
如何开始温度转换,并获取温度值
example1: 温度转换 读取温度
发送reset
接收响应信号
发送skip rom
发送开启温度转换的命令
延时等待转换完成
发送reset
接收响应信号
发送skip rom
发送读命令
接收数据
example2: 配置精度
1.3 应用程序
gui_client
给服务器发送读温度的命令
接收服务器返回的温度值值
显示温度值 Qlabel->setText("32")
server
如果接收到的命令读温度的
参考ds18b20_test.c读取温度值
把读到的温度值返回给client
/* ds18b20温度传感器驱动代码演示 */
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>
#include <asm/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/sched.h>
#define SKIP_ROM 0xcc
#define COVERTT 0x44
#define READ_MEM 0xbe
/* 参看文档P16,注意写1和0的时隙要求*/
/*11001100*/
static void ds18b20_write8(unsigned char data)
{
int i;
local_irq_disable();
for (i = 0; i < 8; i++) {
if ((data & 0x1) == 1) {
gpio_direction_output(S5PV210_GPH1(0), 0);
udelay(3);
gpio_direction_output(S5PV210_GPH1(0), 1);
udelay(80);
} else {
gpio_direction_output(S5PV210_GPH1(0), 0);
udelay(80);
gpio_direction_output(S5PV210_GPH1(0), 1);
udelay(3);
}
data >>= 1;
}
local_irq_enable();
}
/* 参看文档P16,注意读1和0的时隙要求*/
static unsigned char ds18b20_read8(void)
{
int i;
unsigned char bit;
unsigned char data = 0;
local_irq_disable();
for (i = 0; i < 8; i++) {
gpio_direction_output(S5PV210_GPH1(0), 0);
udelay(2);
gpio_direction_input(S5PV210_GPH1(0));
bit = gpio_get_value(S5PV210_GPH1(0));
data |= (bit << i);
udelay(60);
}
local_irq_enable();
return data;
}
/* 参看文档P15 初始化时序图 */
static void ds18b20_reset(void)
{
unsigned char ret;
gpio_direction_output(S5PV210_GPH1(0), 0);
udelay(500);
gpio_direction_output(S5PV210_GPH1(0), 1);
udelay(30);
gpio_direction_input(S5PV210_GPH1(0));
ret = gpio_get_value(S5PV210_GPH1(0));
udelay(500);
if (ret == 0) {
printk("reset ok.\n");
} else {
printk("reset failed.\n");
}
}
static ssize_t ds18b20_read(struct file *file, char *buf, size_t count, loff_t *pos)
{
unsigned char h8, l8;
int temp = 0;
ds18b20_reset();
ds18b20_write8(SKIP_ROM);
ds18b20_write8(COVERTT);
msleep(750);
//mdelay(750);
ds18b20_reset();
ds18b20_write8(SKIP_ROM);
ds18b20_write8(READ_MEM);
l8 = ds18b20_read8();
h8 = ds18b20_read8();
temp = (h8 << 8) | l8; //0x191,组合成一个16bit数据
temp *= 625; //扩大10000倍
if(copy_to_user(buf, &temp, 4))
return -EFAULT;
return count;
}
static struct file_operations ds18b20_fops = {
.owner = THIS_MODULE,
.read = ds18b20_read,
};
static struct miscdevice ds18b20_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "ds18b20",
.fops = &ds18b20_fops,
};
static int ds18b20_init(void)
{
gpio_request(S5PV210_GPH1(0), "GPH1_0");
misc_register(&ds18b20_miscdev);
return 0;
}
static void ds18b20_exit(void)
{
misc_deregister(&ds18b20_miscdev);
gpio_free(S5PV210_GPH1(0));
}
module_init(ds18b20_init);
module_exit(ds18b20_exit);
MODULE_LICENSE("GPL");
/* test.c */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int fd;
int data;
fd = open("/dev/ds18b20", O_RDWR);
if (fd < 0) {
printf("open ds18b20 failed.\n");
exit(-1);
}
while (1) {
read(fd, &data, sizeof(data));
sleep(1);
printf("%.3f\n", (float)data / 10000);
}
close(fd);
return 0;
}
# makefile for kernel module
MODNAME = ds18b20_drv
CROSS_COMPILE = arm-linux-
TESTPRE = ds18b20_test
ifeq ($(PLATFORM), PC)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
else
CC = $(CROSS_COMPILE)gcc
KERNELDIR ?= /opt/kernel
endif
obj-m := $(MODNAME).o
default: test driver
test:
@echo "Compiling test program..."
$(CC) $(TESTPRE).c -o $(TESTPRE)
@echo
driver:
@echo "Compiling device driver..."
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
@echo
clean:
@echo "Cleanup test program..."
@rm -f $(TESTPRE) $(MODNAME)
@echo
@echo "Cleanup device driver..."
@rm -rf *.o *.ko *.mod.* .$(MODNAME).* .tmp* module* Module*
@echo