tiny6410温度传感器详细开发步骤

2024-03-13 20:32

本文主要是介绍tiny6410温度传感器详细开发步骤,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

原文链接:http://blog.csdn.net/gameboy374/article/details/7516102

 

首先感谢署名为lixin的网友以及署名为tandesir的CSDN博主,我必须承认我是站在巨人的肩膀上才有能力迈出了这在我看来具有重要意义的一步!

程序代码:

ds18b20.c

 

01.#include <linux/init.h>  
02.#include <linux/module.h>  
03.#include <linux/delay.h>  
04.#include <linux/kernel.h>  
05.#include <linux/moduleparam.h>  
06.#include <linux/init.h>  
07.#include <linux/types.h>  
08.#include <linux/fs.h>  
09.#include <mach/regs-gpio.h>  
10.#include <linux/device.h>  
11.#include <mach/hardware.h>  
12.#include <linux/cdev.h>  
13.#include <asm/uaccess.h>  
14.#include <linux/errno.h>  
15.  
16.#include "ds18b20.h"  
17.  
18.//#define DEBUG  
19./* 相关引脚定义,方便以后移植 */  
20.#define DEVICE_NAME "ds18b20"  
21.#define DQ         8  
22.#define CFG_IN     0  
23.#define CFG_OUT    1  
24.  
25.// ds18b20主次设备号(动态分配)  
26.int ds18b20_major = 0;  
27.int ds18b20_minor = 0;  
28.int ds18b20_nr_devs = 1;  
29.  
30.// 定义设备类型  
31.static struct ds18b20_device {  
32.    struct cdev cdev;  
33.};  
34.struct ds18b20_device ds18b20_dev;  
35.  
36.static struct class *ds18b20_class;  
37.  
38./* 函数声明 */  
39.static int ds18b20_open(struct inode *inode, struct file *filp);  
40.static int ds18b20_init(void);  
41.static void write_byte(unsigned char data);  
42.static unsigned char read_byte(void);  
43.static ssize_t ds18b20_read(struct file *filp, char __user *buf,  
44.                            size_t count, loff_t *f_pos);  
45.void ds18b20_setup_cdev(struct ds18b20_device *dev, int index);  
46.  
47.  
48.  
49.  
50./* 
51. 函数名称: ds18b20_open() 
52. 函数功能: 打开设备,初始化ds18b20 
53. 入口参数: inode:设备文件信息; filp: 被打开的文件的信息 
54. 出口参数: 成功时返回0,失败返回-1 
55.*/  
56.  
57.static int ds18b20_open(struct inode *inode, struct file *filp)  
58.{  
59.    int flag = 0;  
60.    /*struct ds18b20_device *dev; 
61.    dev = container_of(inode->i_cdev, struct ds18b20_device, cdev); 
62.    filp->private_data = dev;*/  
63.  
64.    flag = ds18b20_init();  
65.    if(flag & 0x01)  
66.    {  
67.#ifdef DEBUG  
68.        printk(KERN_WARNING "open ds18b20 failed\n");  
69.#endif  
70.    return -1;  
71.    }  
72.#ifdef DEBUG  
73.    printk(KERN_NOTICE "open ds18b20 successful\n");  
74.#endif  
75.    return 0;  
76.}  
77.  
78.  
79.  
80.  
81.  
82.  
83./* 
84. 函数名称: ds18b20_init() 
85. 函数功能: 复位ds18b20 
86. 入口参数: 无 
87. 出口参数: retval:成功返回0,失败返回1 
88. 备    注: 操作时序见ds18b20 datasheet 
89.*/  
90.  
91.static int ds18b20_init(void)  
92.{  
93.    int retval = 0;  
94.  
95.    s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
96.    s3c6410_gpio_pullup(DQ, 0);  
97.  
98.    s3c6410_gpio_setpin(DQ, 1);  
99.    udelay(2);  
100.    s3c6410_gpio_setpin(DQ, 0);        // 拉低ds18b20总线,复位ds18b20  
101.    udelay(500);                       // 保持复位电平500us  
102.  
103.    s3c6410_gpio_setpin(DQ, 1);        // 释放ds18b20总线  
104.    udelay(60);  
105.  
106.    // 若复位成功,ds18b20发出存在脉冲(低电平,持续60~240us)  
107.    s3c6410_gpio_cfgpin(DQ, CFG_IN);  
108.    retval = s3c6410_gpio_getpin(DQ);  
109.  
110.    udelay(500);  
111.    s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
112.    s3c6410_gpio_pullup(DQ, 0);  
113.    s3c6410_gpio_setpin(DQ, 1);        // 释放总线  
114.      
115.    return retval;  
116.}  
117.  
118.  
119.  
120.  
121.  
122./* 
123. 函数名称: write_byte() 
124. 函数功能: 向18b20写入一个字节数据 
125. 入口参数: data 
126. 出口参数: 无 
127.*/  
128.static void write_byte(unsigned char data)  
129.{  
130.    int i = 0;  
131.  
132.    s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
133.    s3c6410_gpio_pullup(DQ, 1);  
134.  
135.    for (i = 0; i < 8; i ++)  
136.    {  
137.        // 总线从高拉至低电平时,就产生写时隙  
138.        s3c6410_gpio_setpin(DQ, 1);  
139.        udelay(2);  
140.        s3c6410_gpio_setpin(DQ, 0);  
141.        s3c6410_gpio_setpin(DQ, data & 0x01);  
142.        udelay(60);  
143.    data >>= 1;  
144.    }  
145.    s3c6410_gpio_setpin(DQ, 1);        // 重新释放ds18b20总线  
146.}  
147.  
148.  
149.  
150.  
151.  
152./* 
153. 函数名称: read_byte() 
154. 函数功能: 从ds18b20读出一个字节数据 
155. 入口参数: 无 
156. 出口参数: 读出的数据 
157.*/  
158.  
159.static unsigned char read_byte(void)  
160.{  
161.    int i;  
162.    unsigned char data = 0;  
163.  
164.    for (i = 0; i < 8; i++)  
165.    {  
166.        // 总线从高拉至低,只需维持低电平17ts,再把总线拉高,就产生读时隙  
167.        s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
168.        s3c6410_gpio_pullup(DQ, 0);  
169.        s3c6410_gpio_setpin(DQ, 1);  
170.        udelay(2);  
171.        s3c6410_gpio_setpin(DQ, 0);  
172.        udelay(2);  
173.    s3c6410_gpio_setpin(DQ, 1);  
174.        udelay(8);  
175.        data >>= 1;  
176.    s3c6410_gpio_cfgpin(DQ, CFG_IN);  
177.    if (s3c6410_gpio_getpin(DQ))  
178.        data |= 0x80;  
179.    udelay(50);  
180.    }  
181.    s3c6410_gpio_cfgpin(DQ, CFG_OUT);  
182.    s3c6410_gpio_pullup(DQ, 0);  
183.    s3c6410_gpio_setpin(DQ, 1);        // 释放ds18b20总线  
184.    return data;  
185.}  
186.  
187.  
188.  
189.  
190.  
191./* 
192. 函数名称: ds18b20_read() 
193. 函数功能: 读出18b20的温度 
194.*/    
195.  
196.static ssize_t ds18b20_read(struct file *filp, char __user *buf,  
197.                            size_t count, loff_t *f_pos)  
198.{  
199.    int flag;  
200.    unsigned long err;  
201.    unsigned char result[2] = {0x00, 0x00};  
202.    //struct ds18b20_device *dev = filp->private_data;  
203.  
204.    flag = ds18b20_init();  
205.    if (flag)  
206.    {  
207.#ifdef DEBUG  
208.        printk(KERN_WARNING "ds18b20 init failed\n");  
209.#endif  
210.        return -1;  
211.    }  
212.      
213.    write_byte(0xcc);  
214.    write_byte(0x44);  
215.  
216.    flag = ds18b20_init();  
217.    if (flag)  
218.        return -1;  
219.  
220.    write_byte(0xcc);  
221.    write_byte(0xbe);  
222.  
223.    result[0] = read_byte();    // 温度低八位  
224.    result[1] = read_byte();    // 温度高八位  
225.      
226.    err = copy_to_user(buf, &result, sizeof(result));  
227.    return err ? -EFAULT : min(sizeof(result),count);  
228.}  
229.  
230.  
231.  
232.  
233.  
234./* 
235.  字符驱动程序的核心,应用程序所调用的open,read等函数最终会 
236.  调用这个结构中的对应函数 
237.*/  
238.static struct file_operations ds18b20_dev_fops = {  
239.    .owner = THIS_MODULE,  
240.    .open = ds18b20_open,  
241.    .read = ds18b20_read,  
242.};  
243.  
244.  
245./* 
246. 函数名称: ds18b20_setup_cdev() 
247. 函数功能: 初始化cdev 
248. 入口参数: dev:设备结构体; index: 
249.*/  
250.  
251.void ds18b20_setup_cdev(struct ds18b20_device *dev, int index)  
252.{  
253.    int err, devno = MKDEV(ds18b20_major, ds18b20_minor + index);  
254.  
255.    cdev_init(&dev->cdev, &ds18b20_dev_fops);  
256.    dev->cdev.owner = THIS_MODULE;  
257.    err = cdev_add(&(dev->cdev), devno, 1);  
258.    if (err)  
259.    {  
260.#ifdef DEBUG  
261.        printk(KERN_NOTICE "ERROR %d add ds18b20\n", err);  
262.#endif  
263.    }  
264.}  
265.  
266.  
267.  
268.  
269.  
270.  
271./* 
272. 函数名称: ds18b20_dev_init() 
273. 函数功能: 为温度传感器分配注册设备号,初始化cdev 
274. 入口参数: 无 
275. 出口参数: 若成功执行,返回0 
276.*/  
277.  
278.static int __init ds18b20_dev_init(void)  
279.{  
280.    ds18b20_major = register_chrdev(ds18b20_major, DEVICE_NAME, &ds18b20_dev_fops);  
281.    if (ds18b20_major<0)  
282.    {  
283.    printk(DEVICE_NAME " Can't register major number!\n");  
284.    return -EIO;  
285.    }  
286.  
287.    ds18b20_class = class_create(THIS_MODULE, DEVICE_NAME);  
288.    device_create(ds18b20_class, NULL, MKDEV(ds18b20_major, ds18b20_minor), NULL, DEVICE_NAME);  
289.#ifdef DEBUG  
290.    printk(KERN_WARNING "register ds18b20 driver successful!\n");  
291.#endif  
292.    return 0;  
293.}  
294.  
295.  
296.  
297.  
298.  
299.  
300.  
301. /*函数名称: ds18b20_dev_exit() 
302.   函数功能: 注销设备*/  
303.  
304.static void __exit ds18b20_dev_exit(void)  
305.{  
306.    device_destroy(ds18b20_class, MKDEV(ds18b20_major,ds18b20_minor));  
307.    class_unregister(ds18b20_class);  
308.    class_destroy(ds18b20_class);  
309.    unregister_chrdev(ds18b20_major, DEVICE_NAME);  
310.#ifdef DEBUG  
311.    printk(KERN_WARNING "Exit ds18b20 driver!\n");  
312.#endif  
313.}  
314.  
315.module_init(ds18b20_dev_init);  
316.module_exit(ds18b20_dev_exit);  
317.MODULE_LICENSE("Dual BSD/GPL");  
318.MODULE_AUTHOR("xinli_whut@163.com");  


ds18b20.h

01.#ifndef __DS18B20_H__  
02.#define __DS18B20_H__  
03.  
04.#include <linux/kernel.h>  
05.#include <linux/init.h>  
06.#include <linux/module.h>  
07.#include <linux/interrupt.h>  
08.#include <linux/ioport.h>  
09.#include <linux/gpio.h>  
10.#include <linux/io.h>  
11.  
12.#include <mach/hardware.h>  
13.#include <mach/map.h>   
14.#include <mach/regs-gpio.h>  
15.#include <mach/gpio-bank-n.h>  
16.#include <mach/regs-clock.h>   
17.#include <asm/irq.h>  
18.  
19.#include <plat/gpio-core.h>  
20.#include <plat/gpio-cfg.h>  
21.  
22.void s3c6410_gpio_cfgpin(unsigned int pin, unsigned int function)  
23.{  
24.    //s3c_gpio_cfgpin(pin,function);  
25.        unsigned int tmp;   
26.        tmp = readl(S3C64XX_GPNCON);   
27.        tmp = (tmp & ~(3<<pin*2))|(function<<pin*2);   
28.        writel(tmp, S3C64XX_GPNCON);   
29.}  
30.  
31.void s3c6410_gpio_pullup(unsigned int pin, unsigned int to)  
32.{  
33.        //s3c_gpio_setpull(pin,to);  
34.        unsigned int tmp;   
35.        tmp = readl(S3C64XX_GPNPUD);   
36.        tmp = (tmp & ~(3<<pin*2))|(to<<pin*2);   
37.        writel(tmp, S3C64XX_GPNPUD);   
38.}  
39.  
40.unsigned int s3c6410_gpio_getpin(unsigned int pin)   
41.{   
42.        unsigned int tmp;  
43.    tmp = readl(S3C64XX_GPNDAT);   
44.    tmp = tmp & (1 << (pin));    
45.  
46.    return tmp;   
47.}  
48.  
49.void s3c6410_gpio_setpin(unsigned int pin, unsigned int dat)  
50.{  
51.        unsigned int tmp;   
52.    tmp = readl(S3C64XX_GPNDAT);   
53.    tmp &= ~(1 << (pin));   
54.    tmp |= ( (dat) << (pin) );   
55.    writel(tmp, S3C64XX_GPNDAT); ;  
56.}  
57.  
58.#endif  


 

  1. #endif 
#ifndef __DS18B20_H__
#define __DS18B20_H__#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/gpio.h>
#include <linux/io.h>#include <mach/hardware.h>
#include <mach/map.h> 
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-n.h>
#include <mach/regs-clock.h> 
#include <asm/irq.h>#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>void s3c6410_gpio_cfgpin(unsigned int pin, unsigned int function)
{//s3c_gpio_cfgpin(pin,function);unsigned int tmp; tmp = readl(S3C64XX_GPNCON); tmp = (tmp & ~(3<<pin*2))|(function<<pin*2); writel(tmp, S3C64XX_GPNCON); 
}void s3c6410_gpio_pullup(unsigned int pin, unsigned int to)
{//s3c_gpio_setpull(pin,to);unsigned int tmp; tmp = readl(S3C64XX_GPNPUD); tmp = (tmp & ~(3<<pin*2))|(to<<pin*2); writel(tmp, S3C64XX_GPNPUD); 
}unsigned int s3c6410_gpio_getpin(unsigned int pin) 
{ unsigned int tmp;tmp = readl(S3C64XX_GPNDAT); tmp = tmp & (1 << (pin));  return tmp; 
}void s3c6410_gpio_setpin(unsigned int pin, unsigned int dat)
{unsigned int tmp; tmp = readl(S3C64XX_GPNDAT); tmp &= ~(1 << (pin)); tmp |= ( (dat) << (pin) ); writel(tmp, S3C64XX_GPNDAT); ;
}#endif

寄存器所实现的具体的功能如下图:

温度传感器使用的是GPN8



测试程序:

test.c

01.#include <stdio.h>  
02.#include <stdlib.h>  
03.#include <unistd.h>  
04.#include <linux/ioctl.h>  
05.  
06.// 函数声明  
07.void ds18b20_delay(int i);  
08.  
09.int main()  
10.{  
11.    int fd, i;  
12.    unsigned char result[2];           // 从ds18b20读出的结果,result[0]存放低八位  
13.    unsigned char integer_value = 0;  
14.    float temperature, decimal_value;  // 温度数值,decimal_value为小数部分的值  
15.    fd = open("/dev/ds18b20", 0);  
16.    if (fd < 0)  
17.    {  
18.        perror("open device failed\n");  
19.    exit(1);  
20.    }  
21.    while (1)  
22.    {  
23.        i++;  
24.        read(fd, &result, sizeof(result));  
25.        integer_value = ((result[0] & 0xf0) >> 4) | ((result[1] & 0x07) << 4);  
26.        // 精确到0.25度  
27.        decimal_value = 0.5 * ((result[0] & 0x0f) >> 3) + 0.25 * ((result[0] & 0x07) >> 2);  
28.        temperature = (float)integer_value + decimal_value;  
29.    printf("The temperature is %6.2f\n",temperature);  
30.    if (i % 20 == 0)  
31.        printf("\n");  
32.    ds18b20_delay(50);  
33.    }  
34.}  
35.  
36./* 函数名称: ds18b20_delay() */  
37.  
38.void ds18b20_delay(int i)  
39.{  
40.    int j, k;  
41.    for (j = 0; j < i; j++)  
42.        for(k = 0; k < 50000; k++);  
43.}  


因为我的内核版本与配置还有路径与tandesir网友的不一样,所以没有借用他Makefile文件,下面我将详细介绍一下具体的实现过程:

首先编辑配置文件Kconfig:

我的linux-2.6.38内核放在“/home/zjp/文档”这个目录下面,所以直接进入/home/zjp/文档/linux-2.6.38/drivers/char,然后编辑Kconfig文件:#vim Kconfig。在这个文件里面加入:

config MINI6410_DS18B20
        tristate "ds18b20 drives"
        depends on CPU_S3C6410

保存退出。

如图:


这个时候返回到/linux-2.6.38目录,运行“#make menuconfig”就会返回一个界面,在Device Drivers -->Character devices菜单下面就可以看见“<M> ds18b20 drives”这个选项。

如图:


之后再进入linux-2.6.38/drivers/char,编辑Makefile文件,在其中加入“obj-$(CONFIG_MINI6410_DS18B20)  +=ds18b20.o“这一项。

如图:


最后一步就是生成*.ko文件了:

返回到/linux-2.6.38目录下面,执行“#make modules”就会在/linux-2.6.38/drivers/char目录里面生成你所需要的*.ko文件。


下一步加载到开发板的内核树里:

使用U盘或者SD卡或者直接ftp传输ds18b20.ko到开发板里,然后“#insmod ds18b20.ko“进去就可以了,这里我尝试了很长时间也不知道为什么modprobe命令不能加载这个文件,最后还是使用的insmod。

最后$arm-linux-gcc test.c -o test ,然后你是怎么样把*.ko文件弄到开发板上就怎么把test文件弄到开发板上,最最后“./test”直接就可以运行了!


 

 

 

 

 

 

这篇关于tiny6410温度传感器详细开发步骤的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/806121

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Goland debug失效详细解决步骤(合集)

《Golanddebug失效详细解决步骤(合集)》今天用Goland开发时,打断点,以debug方式运行,发现程序并没有断住,程序跳过了断点,直接运行结束,网上搜寻了大量文章,最后得以解决,特此在这... 目录Bug:Goland debug失效详细解决步骤【合集】情况一:Go或Goland架构不对情况二:

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤

《SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤》本文主要介绍了SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤,文中通过示例代码介绍的非常详... 目录 目标 步骤 1:确保 ProxySQL 和 mysql 主从同步已正确配置ProxySQL 的

Spring Boot整合log4j2日志配置的详细教程

《SpringBoot整合log4j2日志配置的详细教程》:本文主要介绍SpringBoot项目中整合Log4j2日志框架的步骤和配置,包括常用日志框架的比较、配置参数介绍、Log4j2配置详解... 目录前言一、常用日志框架二、配置参数介绍1. 日志级别2. 输出形式3. 日志格式3.1 PatternL

nginx部署https网站的实现步骤(亲测)

《nginx部署https网站的实现步骤(亲测)》本文详细介绍了使用Nginx在保持与http服务兼容的情况下部署HTTPS,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值... 目录步骤 1:安装 Nginx步骤 2:获取 SSL 证书步骤 3:手动配置 Nginx步骤 4:测

Springboot 中使用Sentinel的详细步骤

《Springboot中使用Sentinel的详细步骤》文章介绍了如何在SpringBoot中使用Sentinel进行限流和熔断降级,首先添加依赖,配置Sentinel控制台地址,定义受保护的资源,... 目录步骤 1: 添加 Sentinel 依赖步骤 2: 配置 Sentinel步骤 3: 定义受保护的

Ollama整合open-webui的步骤及访问

《Ollama整合open-webui的步骤及访问》:本文主要介绍如何通过源码方式安装OpenWebUI,并详细说明了安装步骤、环境要求以及第一次使用时的账号注册和模型选择过程,需要的朋友可以参考... 目录安装环境要求步骤访问选择PjrIUE模型开始对话总结 安装官方安装地址:https://docs.

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee