DS18B20驱动编写–杂项设备框架注册
设备驱动最通俗的解释就是“驱使硬件设备行动”。驱动与底层硬件直接打交道,按照硬件设备的具体工作方式,读写设备的寄存器,完成设备的轮询、中断处理、DMA通信,进行物理内存向虚拟内存的映射等,最终让通信设备能收发数据,让显示设备能显示文字和画面,让存储设备能记录文件和数据。
驱动程序是应用层和硬件层的连接桥梁,应用层只管完成应用逻辑开发和界面设计,驱动层则处理硬件配置,实现应用层相关接口函数。
杂项设备:字符设备类的一种,杂项设备主设备号为10。
1.DS18B20简介DS18B20是Dallas半导体公司生产的数字温度传感器,是世界上第一片支持”一线总线”接口的温度传感器。测量温度范围为-55℃ ~ +125℃,精度为±0.5℃。分辨率为9 ~ 12位。支持3V ~ 5.5V输入电压。抗干扰能力强。
每一个DSl820包括一个唯一的64位长的序号,该序号值存放在 DSl820 内部的 ROM(只读存贮器)中。开始8位是产品类型编码(DSl820 编码均为 10H) ,接着的 48位是每个器件唯一的序号,最后 8 位是前面 56 位的CRC(循环冗余校验)码。 引脚 说明 GND 地 DQ 数字信号脚 VDD 电源脚3V~5.5VDS18B20以9位数字量形式反应器件的温度值。 DS18B20采用单总线通讯,与CPU之间只需要DQ脚相连,再和CPU之间共地即可。每一个DS18B20都有唯一的64位光刻ROM,因此可以在一根数据线上接多个DS18B20模块。
单总线协议特性 总线协议:一个数据线可挂载多个设备(DS18B20通过64位光刻ROM区分设备); 半双工通讯:数据线上同一时间只能发送或者接收数据;2.DS18B20驱动时序
2.1 发送复位脉冲和检测存在信号DS18B20初始化过程首先需要发送复位脉冲:至少480us的低电平信号。接下来释放总线,DS18B20开始返回存在信号:60~240us的低电平。最后释放总线,模块初始化完成。
复制/*发送复位信号,检测存在脉冲*/ static u8 ds18b20_CheckRst(void) { u8 time=0; DS18B20_OUT_MODE();/*输出模式*/ DS18B20_OUT(0);/*总线拉低*/ udelay(600);/*至少480us低电平*/ DS18B20_OUT(1);/*释放总线,恢复为空闲电平*/ udelay(15); DS18B20_INPUT_MODE();/*输入模式*/ while(DS18B20_IN) { time++; udelay(1); if(time>=100)return 1;/*等待存在脉冲失败*/ } time=0; while(!DS18B20_IN) { time++; udelay(1); if(time>=250)return 2;//模块出错 } return 0; } 2.2 写一位数据时序要实现写一字节数据,则首先要实现的是写一位数据时序。分为写1和写0。首先是总线拉低,产生写间隙(至少1us)。接着往数据线DQ上写入0或者1,周期时间为60us,最后释放总线(总线拉高,至少1us),至此,写数据完成。
复制DS18B20_OUT_MODE();/*输出模式*/ DS18B20_OUT(0);//总线拉低,产生写间隙时间 udelay(2); if(dat&0x01)DS18B20_OUT(1); else DS18B20_OUT(0); udelay(60);//写周期时间 DS18B20_OUT(1);//释放总线 udelay(2); dat>>=1;//继续发送下一位数据 2.3 读一位数据时序读数据首先需要主机产生读间隙:总线拉低,至少1us的低电平信号。接着释放总线,在15us内进行数据读取,读数据周期时间为60us,最后释放总线:总线拉高,至少1us时间。 至此,读一位数据完成。
复制DS18B20_OUT_MODE();/*输出模式*/ DS18B20_OUT(0);//总线拉低,产生读间隙时间 udelay(2); DS18B20_INPUT_MODE();//配置为输入模式 udelay(12);//等待数据到来 data>>=1; if(DS18B20_IN)data|=0x80; udelay(50);//读数据时间 DS18B20_OUT(1);//恢复总线为空闲电平 udelay(2);3.DS18B20相关命令
跳转指令0xCC这条指令允许控制器不需要提供64位光刻ROM就使用存储器操作命令,在总线上仅有一个DS18B20时使用,若有多个则会产生冲突。
启动一次温度转换0x44此命令完成一次温度转换。执行此命令后,DS18B20保持等待状态。若总线在这条命令发送后跟着读间隙,而DS18B20正处于数据转换,则会输出一个0,若温度转换完成,则会输出1。若使用寄生电源,总线必须在这条命令发完后拉高总线,保存500ms。
读取一次数据0xBE此命令用于读取暂存器中的内容,可连续读取9个字节数据。若只想读取温度数据,则只需要读取前两个字节即可。
读ROM 0x33此命令可以读取DS18B20的64位光刻ROM数据,此命令仅能在总线上一个设备的时候使用。
匹配ROM 0x55此命令可以实现和DS18B20的ROM进行匹配,只有和DS1820的64位光刻ROM完全匹配才能响应后面存储器命令。此命令用于当总线上不止一个设备时使用。
搜索ROM 0xF0当系统第一次启动时,无法确认总线上有多少个设备或者该设备的光刻ROM,搜索光刻ROM可以让控制器通过排除法识别总线上的所有设备的64位光刻ROM。
4.DS18B20采集一次温度步骤
采用外部电源供电,且总线上仅有一个DS18B20模块。
5.编写DS18B20驱动,通过杂项设备注册
开发平台开发平台:
Ubuntu18.04
编译器:arm-linux-gcc
硬件平台:tiny4412基于Cortex-A9 4核1.5GHZ
开发板内核:Linux3.5 复制#include #include #include #include #include #include #include #include #include #include static unsigned int ds18b20_gpio=EXYNOS4_GPB(4);//GPB_4 #define DS18B20_OUT_MODE() s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_OUTPUT)/*输出模式*/ #define DS18B20_INPUT_MODE() s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_INPUT)/*输入模式*/ #define DS18B20_OUT(x) gpio_set_value(ds18b20_gpio,(x)) #define DS18B20_IN gpio_get_value(ds18b20_gpio) /*发送复位信号,检测存在脉冲*/ static u8 ds18b20_CheckRst(void) { u8 time=0; DS18B20_OUT_MODE();/*输出模式*/ DS18B20_OUT(0);/*总线拉低*/ udelay(600);/*至少480us低电平*/ DS18B20_OUT(1);/*释放总线,恢复为空闲电平*/ udelay(15); DS18B20_INPUT_MODE();/*输入模式*/ while(DS18B20_IN) { time++; udelay(1); if(time>=100)return 1;/*等待存在脉冲失败*/ } time=0; while(!DS18B20_IN) { time++; udelay(1); if(time>=250)return 2;//模块出错 } return 0; } /*写一个字节函数*/ static void ds18b20_writeDat(u8 dat) { int i=0; DS18B20_OUT_MODE();/*输出模式*/ for(i=0;i<8;i++) { DS18B20_OUT(0);//总线拉低,产生写间隙时间 udelay(2); if(dat&0x01)DS18B20_OUT(1); else DS18B20_OUT(0); udelay(60);//写周期时间 DS18B20_OUT(1);//释放总线 udelay(2); dat>>=1;//继续发送下一位数据 } } /*读取1字节数据*/ static u8 ds18b20_readDat(void) { int i=0; u8 data=0; for(i=0;i<8;i++) { DS18B20_OUT_MODE();/*输出模式*/ DS18B20_OUT(0);//总线拉低,产生读间隙时间 udelay(2); DS18B20_INPUT_MODE();//配置为输入模式 udelay(12);//等待数据到来 data>>=1; if(DS18B20_IN)data|=0x80; udelay(50);//读数据时间 DS18B20_OUT(1);//恢复总线为空闲电平 udelay(2); } return data; } /*获取一次温度数据*/ static u16 ds18b20_GetTemp(void) { u8 L,H; u16 temp; if(ds18b20_CheckRst())return 0xffff; ds18b20_writeDat(0xcc); ds18b20_writeDat(0x44); while(ds18b20_readDat()!=0xff);/*等待温度转换完成*/ if(ds18b20_CheckRst())return 0xffff; ds18b20_writeDat(0xcc); ds18b20_writeDat(0xbe);/*读取一次温度*/ L=ds18b20_readDat(); H=ds18b20_readDat(); temp=H<<8|L; return temp; } static int ds18b20_open(struct inode *inode, struct file *file) { printk(“open函数调用成功\n”); if(ds18b20_CheckRst()) { printk(“DS18B20初始化失败\n”); } return 0; } static int ds18b20_release(struct inode *inode, struct file *file) { printk(“release函数调用成功”); return 0; } long ds18b20_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int dir=_IOC_DIR(cmd);/*数据读写方向,00无参数,10用户层读,01用户层写,11可读写*/ int type=_IOC_TYPE(cmd);/*魔术,标志符*/ int size=_IOC_SIZE(cmd);/*arg的字节数*/ printk(“dir=%d,type=%c,size=%d\n”,dir,type,size); int ret; u16 temp=ds18b20_GetTemp();/*获取一次温度*/ ret=copy_to_user((void *)arg, &temp,size); return 4-ret; } static struct file_operations ds18b20_fops= { .open =ds18b20_open, .release =ds18b20_release, .unlocked_ioctl =ds18b20_ioctl }; /*杂项设备结构体*/ static struct miscdevice ds18b20_drv= { .minor =MISC_DYNAMIC_MINOR,/*255,有内核自动分配*/ .name =”ds18b20″,//设备节点名字 .fops =&ds18b20_fops,//文件操作集合 }; static int __init wbyq_ds18b20_init(void) { /*1.GPIO注销*/ gpio_free(ds18b20_gpio); /*2.注册GPIO*/ gpio_request(ds18b20_gpio,”DS18B20″); /*配置GPIO模式*/ s3c_gpio_cfgpin(ds18b20_gpio,S3C_GPIO_OUTPUT); gpio_set_value(ds18b20_gpio,1);/*上拉*/ /*注册杂项设备*/ misc_register(&ds18b20_drv); return 0; } /*驱动释放*/ static void __exit wbyq_ds18b20_cleanup(void) { printk(“驱动出口,驱动注销成功\n”); /*注销杂项设备*/ misc_deregister(&ds18b20_drv); /*注销GPIO*/ gpio_free(ds18b20_gpio); } module_init(wbyq_ds18b20_init);//驱动入口函数 module_exit(wbyq_ds18b20_cleanup);//驱动出口函数 MODULE_LICENSE(“GPL”);//驱动注册协议 MODULE_AUTHOR(“it_ashui”); MODULE_DESCRIPTION(“Exynos4 ds18b20 Driver”);审核编辑:汤梓红
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:DS18B20驱动编写–杂项设备框架注册-ds-1168s驱动下载 https://www.yhzz.com.cn/a/7492.html