|
毕业设计中使用ARM做智能家居,打算使用DS18B20检测温度,并利用CGI程序在网页中动态显示。遇到很多问题,总算完成了,以下是调试步骤。
DS18B20是DALLAS公司生产的数字温度传感器。使用1-Wire技术,即单总线。具有线路简单,精度高,体积小,低功耗的特点。
1、DS18B20产品的特点
(1)、只要求一个端口即可实现通信。
(2)、不需要外加器件。
(3)、测量温度范围在-55℃到+125℃之间。
(4)、数字温度计的分辨率用户可以从9位到12位选择。
(5)、具有温度报警功能。
2、DS18B20在嵌入式应用中的难度
DS18B20的1-Wire技术,在减小体积方面有很好的作用,但是也增加了软件设计的复杂度。DS18B20的读写需要严格的读写时序。这种要求在单片机系统应用中比较容易实现。但是在嵌入式应用中就比较难办,因为嵌入式操作系统都是多任务的。用户程序随时都有可能被打断。
以下是我所做的驱动程序,测试程序,以及CGI程序。已在我所用的系统中调试通过。
所用开发环境: Red Hat Linux 9
编译器: arm-linux-gcc 3.4.1
Linux内核版本: kernel2.6.13
开发板: mini2440
网络服务器: Boa
//ds18b20.c DS18B20的驱动程序
//////////////////////////////////////////////////////////
// //
// ds18b20.c DS18B20的驱动程序 //
// //
// 作者:xshbx 日期:2009.4.19 //
//////////////////////////////////////////////////////////
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/miscdevice.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "DS18B20"
#define DS18B20_MAJOR 229
#define DS_PIN S3C2410_GPF0
#define OUT S3C2410_GPF0_OUTP
#define IN S3C2410_GPF0_INP
#define DIS_UP 1
#define EN_UP 0
#define Search 0x00F0
#define Read_ROM 0x0033 //just for one
#define Skip_ROM 0x00CC
#define Convert 0x0044
#define Write 0x004E //TH---TL---Config
#define Read 0x00BE
#define bit_9 0x001F
#define bit_10 0x003F
#define bit_11 0x005F
#define bit_12 0x007F
#define uint16 unsigned int
//unsigned int ROM_DATA[8];
void usdelay(unsigned int i) //延时 i us 对于不同系统可能会有所差别,请适当修改
{
unsigned int j;
for(i=i;i>0;i--)
for(j=90;j>0;j--);
}
void msdelay(unsigned int i) //延时 i us
{
for(i=i;i>0;i--)
usdelay(1000);
}
void SetL(void)
{
s3c2410_gpio_cfgpin(DS_PIN,OUT);
s3c2410_gpio_setpin(DS_PIN,0);
}
void SetH(void)
{
s3c2410_gpio_cfgpin(DS_PIN,OUT);
s3c2410_gpio_setpin(DS_PIN,1);
}
unsigned int Read_DS(void)
{
unsigned int i;
s3c2410_gpio_cfgpin(DS_PIN,IN);
s3c2410_gpio_pullup(DS_PIN,EN_UP);
__asm("nop");
__asm("nop");
__asm("nop");
i=s3c2410_gpio_getpin(DS_PIN);
if(i!=0)
i=1;
return i;
}
unsigned int ds_start(void)
{
unsigned int flag=1;int err=0;
SetL();
usdelay(500); //560
SetH();
usdelay(1);
while(Read_DS()!=0)
{
// printk(DEVICE_NAME "Wait....\n");
usdelay(5);
err++;
if(err==20)
{
printk(DEVICE_NAME "start fail\n");
return -1;
}
}
// printk(DEVICE_NAME "start sucess\n");
flag=0;
SetH();
usdelay(400);
return flag;
}
void ds_send(unsigned int uidata)
{
unsigned int i;
for(i=0;i<8;i++)
{
SetL();
if((uidata&1)!=0)
{
usdelay(3); //3
SetH();
usdelay(80);
}
else
{
usdelay(80);
SetH();
usdelay(5); //
}
uidata>>=1;
}
}
unsigned int ds_read(void)
{
unsigned int uidata=0;unsigned int i;
for(i=0;i<8;i++)
{
SetL();
usdelay(4); //2 3
SetH();
usdelay(7); //1 2 3 4 5(e)
if(Read_DS()==1)
uidata+=0x0100;
uidata>>=1;
SetH();
usdelay(65);
}
return uidata;
}
void ds_init(unsigned int TH,unsigned int TL,unsigned int bit_nmb)
{
SetH();
usdelay(80);
if(ds_start()==0)
{
ds_send(Skip_ROM); //复位
ds_send(Write); //跳过ROM匹配
ds_send(TH); //TH
ds_send(TL); //TL
ds_send(bit_nmb); //转换位数
}
}
unsigned int read_tem(void)
{
unsigned int th,tl;int err=0;
ds_init(100,0,bit_12);
th=tl=0;
ds_start();
ds_start();
ds_start();
ds_send(Skip_ROM);
ds_send(Convert);
msdelay(50);
while(Read_DS()==0)
{
// printk(DEVICE_NAME "Convert....\n");
msdelay(50);
err++;
if(err==10)
{
printk(DEVICE_NAME "convert fail\n");
return -1;
}
}
ds_start();
ds_start();
ds_send(Skip_ROM);
ds_send(Read);
tl=ds_read();
th=ds_read();
ds_start();
ds_start();
th<<=8;
tl|=th;
return tl;
}
/*
void read_ROM(void)
{
unsigned int i;
ds_start();
ds_send(Read_ROM);
for(i=0;i<8;i++)
ROM_DATA=ds_read();
}
*/
static int ds18b20_ioctl(
struct inode *inode,
struct file *file,
unsigned int cmd,unsigned long arg)
{
return 0;
}
static ssize_t ds18b20_read(struct file *pFile, uint16 __user *pData, size_t count, loff_t *off )
{
uint16 tmp,ret;
tmp =read_tem();
ret=copy_to_user(pData, &tmp, sizeof(tmp)); //将读取得的DS18B20数值复制到用户区
if(ret>0)
{
printk("copy data failed\n");
return -1;
}
return 0;
}
static struct file_operations ds18b20_fops = {
.owner = THIS_MODULE,
.ioctl = ds18b20_ioctl,
.read = ds18b20_read,
};
static int __init ds18b20_init(void)
{
int ret;
ret = register_chrdev(DS18B20_MAJOR, DEVICE_NAME, &ds18b20_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't register major number\n");
return ret;
}
devfs_mk_cdev(MKDEV(DS18B20_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);
s3c2410_gpio_cfgpin(DS_PIN, OUT);
s3c2410_gpio_setpin(DS_PIN, 1);
printk(DEVICE_NAME " initialized\n");
return 0;
}
static void __exit ds18b20_exit(void)
{
devfs_remove(DEVICE_NAME);
unregister_chrdev(DS18B20_MAJOR, DEVICE_NAME);
printk(DEVICE_NAME " rmmodule\n");
}
module_init(ds18b20_init);
module_exit(ds18b20_exit);
MODULE_AUTHOR("xshbx@126.com"); // 驱动程序的作者
MODULE_DESCRIPTION("DS18B20 Driver"); // 一些描述信息
MODULE_LICENSE("GPL"); // 遵循的协议
//Test_ds.c DS18B20的测试程序
//////////////////////////////////////////////////////////
// //
// Test_ds.c DS18B20的测试程序 //
// //
// 作者:xshbx 日期:2009.4.19 //
//////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#define K 0.0625
int main(void)
{
int fd = -1;
char count = 5;
unsigned int tmp = 0;float res=0;
fd = open("/dev/DS18B20", 0);
if(fd < 0)
{
perror("Can't open /dev/DS18B20 \n");
exit(1);
}
printf("open ds18b20 success \n");
read(fd, &tmp , sizeof(tmp));
printf("Tem %d \n",tmp);
res=tmp*K;
printf("the currently temperature is %f \n",res);
close(fd);
return 0;
}
//Temperature.c DS18B20的CGI程序
//////////////////////////////////////////////////////////
// //
// Temperature.c DS18B20的CGI程序 //
// //
// 作者:xshbx 日期:2009.4.19 //
//////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//#include <linux/sched.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define K 0.0625
int main()
{
unsigned int tem=0;int fd;
float res=0;
printf("Content-type: text/html\n\n");
printf("<HTML><HEAD><TITLE>温度监测</TITLE></HEAD>\n");
printf("<BODY style=\"background-image: url(http://192.168.1.230/images/bj.jpg);\">\n");
printf("<br><br><br>\n");
printf("<H2>温度监测</H2><br>\n");
fd = open("/dev/DS18B20", 0);
if(fd < 0)
{
printf("Can't open /dev/DS18B20 <br><br><br>\n");
printf("返回主界面请点击<font size=\"6\">这里</font><br>\n");
printf("</BODY></HTML>\n");
fflush(stdout);
exit(1);
}
read(fd, &tem , sizeof(tem));
res=tem*K;
close(fd);
printf("DS18B20返回值: %u <br><br>\n",tem);
printf("当前温度: %f <br><br><br><br>\n",res);
printf("返回主界面请点击<font size=\"6\">这里</font><br>\n");
printf("</CENTER></BODY></HTML>\n");
fflush(stdout);
return 0;
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|