一步一步的在昨天终于把基于 mini2440的ds18b20的驱动编译成功了。其中最大的问题居然是18b20插反了,导致我研究了一天时间最后还是别人告诉我才发现反了。百度图片不可信啊,居然有错图,以后一定要长记性,去下官方的datasheet。呵呵
下面记录下自己的编译过程。
首先是从网上找了个18b20的驱动下载下来了,因为18b20是个技术很成熟的芯片,因此网上资料很多。我下载的代码如下:
- #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 242
- #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;
- }
- 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("benjamin_xc@163.com"); // 驱动程序的作者
- MODULE_DESCRIPTION("DS18B20 Driver"); // 一些描述信息
- MODULE_LICENSE("GPL"); // 遵循的协议
我只改了引脚和主设备号。其他的都没改。
按照之前的帖子编译,编译成功后出现*.ko文件。
建立nfs服务器,
mknod /dev/DS18B20 c 242 0
insmod ds18b20.ko
两条命令如果都没有错误自少说明驱动的方法没有问题,就看驱动本身有没有错误了。
连线,18b20有三根线,把平面对着自己,左手边起为地,数据,正。
在数据和正之间要加一个4-10k的电阻,我加的是4.7K的。开发板插的是一个正,地,和gpf0端口。fpf0端口在con4的靠着滑动电阻的第五根线。正是第一根,地是第二跟。
之后编译测试程序,如下:
- #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");
- while(1){
- read(fd, &tmp , sizeof(tmp));
- res=tmp*K;
- printf("the currently temperature is %f/n",res);
- sleep(1);
- }
- close(fd);
- return 0;
- }
编译后运行,如果没有什么线插错的情况下应该就能正常显示温度了。呵呵~