1、http:/ 在 linux 下跑起来上次的让 LED 在 linux 下闪烁起来可算是困难重重,毕竟是刚入手。这次的 DS18B20 加载到 linux同样是个探险之旅。在不断的摸索、尝试,最后还是有点小成果。现在写下笔记,希望能与同路人分享交流。在加载到 linux 之前,我先确保 DS18B20 在无 OS 的环境下能正常工作,即“裸奔”。这个阶段也不是一路顺利,虽然以前有在单片机下驱动 DS18B20 的经验,但是在 ARM 延时确实是个问题。上网搜索一下,有的人用定时器延时,有的就直接程序耗时的方式延时。急于求成的我,为了避免使用定时器又出现新的麻烦,唯有使用后者的方法。好了,解决延
2、时问题,DS18B20 也自然运行起来,没有辜负我!哈“裸奔”成功之后,现在就要给 DS18B20 披上 linux 的大衣。这次同样是将它以字符型设备驱动。按上次驱动 LED 的过程照葫芦画瓢,一个驱动程序,一个测试程序。驱动程序驱动程序对比上次有所加深,多使用了几个系统调用函数。open()函数,对设备特殊文件进行 open()系统调用时,将调用驱动程序的 open () 函数:int (*open)(struct inode * ,struct file *);其中参数 inode 为设备特殊文件的 inode (索引结点) 结构的指针,参数 file 是指向这一设备的文件结构的指针。o
3、pen()的主要任务是确定硬件处在就绪状态、验证次设备号的合法性(次设备号可以用MINOR(inode- i - rdev) 取得)、控制使用设备的进程数、根据执行情况返回状态码(0 表示成功,负数表示存在错误) 等。read()函数。当对设备特殊文件进行 read() 系统调用时,将调用驱动程序 read() 函数:ssize_t (*read) (struct file *, char *, size_t, loff_t *);来从设备中读取数据。当该函数指针被赋为 NULL 值时,将导致 read 系统调用出错并返回-EINVAL(“Invalid argument,非法参数“)。函数返
4、回非负值表示成功读取的字节数(返回值为“signed size“数据类型,通常就是目标平台上的固有整数类型)。release()函数,当最后一个打开设备的用户进程执行 close ()系统调用时,内核将调用驱动程序的release () 函数:void (*release) (struct inode * ,struct file *) ;release 函数的主要任务是清理未结束的输入/输出操作、释放资源、用户自定义排他标志的复位等。程序如下:/*/文件名:ds18b20.c/功能:linux 下的 ds18b20 驱动程序/使用说明: (1)/ (2)/ (3)/ (4)/作者:jammy
5、-lee/日期:2009-03-31/*/包含头文件#include #include #include #include #include #include #include #include #inculde #include #include #include #include #include /DS18B20 端口的定义#define DQ_PIN S3C2410_GPG14#define DQ_IN S3C2410_GPG14_INP#define DQ_OUT S3C2410_GPG14_OUTP#define DEVICE_NAME “DS18B20“ /驱动设备的名称,可以使
6、用命令 cat /proc/devices#define DS18B20_MAJOR 182 /主设备号/定义 DS18B20 端口控制#define GPG_UP s3c2410_gpio_pullup(DQ_PIN, 1) /打开上拉电阻#define GPG_DOWN s3c2410_gpio_pullup(DQ_PIN, 0) /关闭上拉电阻#define DS18B20_L s3c2410_gpio_setpin(DQ_PIN, 0) /拉低数据线电平?#define DS18B20_H s3c2410_gpio_setpin(DQ_PIN, 1) /拉高数据线电平#define D
7、S18B20_OUT s3c2410_gpio_cfgpin(DQ_PIN, DQ_OUT) /数据线设置为输出#define DS18B20_IN s3c2410_gpio_cfgpin(DQ_PIN, DQ_IN) /数据线设置为输入#define DS18B20_STU s3c2410_gpio_getpin(DQ_PIN) /数据状态/定义 DS18B20ROM 指令#define DS18B20_ReadROM 0x33 /读 ROM#define DS18B20_MatchROM 0x55 /匹配 ROM#define DS18B20_SkipROM 0xCC /跳过 ROM#de
8、fine DS18B20_SearchROM 0xF0 /搜索 ROM#define DS18B20_AlarmROM 0xEC /报警搜索/定义 DS18B20 存储器操作命令#define DS18B20_WriteSCR 0x4E /写暂存存储器#define DS18B20_ReadSCR 0xBE /读暂存存储器#define DS18B20_CopySCR 0x48 /复制暂存存储器#define DS18B20_ConvertTemp 0x44 /温度变换#define DS18B20_RecallEP 0xB8 /重新调出#define DS18B20_ReadPower 0x
9、B4 /读电源/定义类型typedef unsigned char uint8 ;typedef unsigned int uint16 ;/全局变量uint8 opencount = 0;/函数声明uint8 Init_DS18B20(void); /初始化 DS18B20uint8 DS18B20_ReadByte(void); /读取 DS18B20 一字节void DS18B20_WriteByte(uint8 Data); /写入 DS18B20 一字节void DS18B20_ReadID(void); /读取 DS18B20 的 IDvoid DS18B20_Match(void
10、); /匹配 DS18B20uint16 DS18B20_Temperature(void); /单个 DS18B20 温度读取uint16 nDS18B20_Temperature(void); /读取多个 DS18B20 的温度?uint8 DS18B20_ID8 = 0;/初始化 DS18B20uint8 Init_DS18B20(void)uint8 errTime;DS18B20_OUT;DS18B20_H; DS18B20_L; /初始化发送一复位脉冲udelay(500); /脉冲时间大于 480usDS18B20_H;DS18B20_IN;udelay(80);while(DS
11、18B20_STU)udelay(6); /5.15userrTime+;if(errTime20)return 0; /如果等带大于约 5.15us*20 就返回 0x00,报告复位失败(实际上只要等待 15-60us)errTime=0;while(!(DS18B20_STU)udelay(6); /5.15userrTime+;if(errTime50)return 0; /如果等带大于约 5.15us*50 就返回 0x00,报告复位失败(实际上只要等待60-240us)return 0xff;/读取 DS18B20 一字节uint8 DS18B20_ReadByte(void)uin
12、t8 i;uint8 temp = 0;DS18B20_IN;/asm(“nop“);for(i=0;i= 1; /向右移动一位 ;DS18B20_OUT;DS18B20_L;udelay(8);DS18B20_H;DS18B20_IN; /释放总线if(DS18B20_STU)temp |= 0x80;udelay(32);DS18B20_OUT;DS18B20_H;/delay_nus(32);udelay(5);return (temp);/写入 DS18B20 一字节void DS18B20_WriteByte(uint8 Data)uint8 i;uint8 temp;DS18B20
13、_IN;/asm(“nop“);for(i=0;i i;temp if(temp)DS18B20_H;elseDS18B20_L;udelay(50);DS18B20_H;udelay(4);/DS18B20_H;/读取 DS18B20 的 IDvoid DS18B20_ReadID(void)udelay(1);Init_DS18B20();DS18B20_WriteByte(DS18B20_ReadROM);DS18B20_ID0 = DS18B20_ReadByte();DS18B20_ID1 = DS18B20_ReadByte();DS18B20_ID2 = DS18B20_Read
14、Byte();DS18B20_ID3 = DS18B20_ReadByte();DS18B20_ID4 = DS18B20_ReadByte();DS18B20_ID5 = DS18B20_ReadByte();DS18B20_ID6 = DS18B20_ReadByte();DS18B20_ID7 = DS18B20_ReadByte();/匹配 DS18B20void DS18B20_Match(void)DS18B20_WriteByte(DS18B20_MatchROM);DS18B20_WriteByte(DS18B20_ID0);DS18B20_WriteByte(DS18B20_
15、ID1);DS18B20_WriteByte(DS18B20_ID2);DS18B20_WriteByte(DS18B20_ID3);DS18B20_WriteByte(DS18B20_ID4);DS18B20_WriteByte(DS18B20_ID5);DS18B20_WriteByte(DS18B20_ID6);DS18B20_WriteByte(DS18B20_ID7);/单个 DS18B20 温度读取uint16 DS18B20_Temperature(void)uint8 flag = 0;uint8 tempH = 0;uint8 tempL = 0;uint16 temp =
16、0;flag = Init_DS18B20();if(flag = 0x00)return -1;DS18B20_WriteByte(DS18B20_SkipROM);DS18B20_WriteByte(DS18B20_ConvertTemp);flag = Init_DS18B20();if(flag = 0x00)return -1;DS18B20_WriteByte(DS18B20_SkipROM);DS18B20_WriteByte(DS18B20_ReadSCR);tempL = DS18B20_ReadByte();tempH = DS18B20_ReadByte();temp =
17、 (tempH#include #include #include #include #include #include #include #include #include int main(void)int fd = -1;char count = 5;unsigned int tmp = 0;fd = open(“/dev/ds18b20“, 0);if(fd 0)perror(“Cant open /dev/ds18b20 n“);exit(1);printf(“open ds18b20 success n“);while(count-)read(fd, printf(“the currently temperature is %d n“,tmp);终于,DS18B20 在 linux 下准确地报告了它测得的温度!欣喜若狂!若有错误,希望贵人能指出!jammy 感激万分