DS18B20 驱动编写

嵌入式开发平台:mini2440

DS18B20 所用GPIO:S3C2410_GPF(3)


一、DS18B20 时序分析

        DS18B20的一线工作协议流程是:初始化→ROM操作指令→存储器操作指令→数据传输,其工作时序包括:初始化时序、写时序、读时序。

1、初始化时序

       主机首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答,若无低电平出现一直都是高电平说明总线上无器件应答。

   作为从器件的DS18B20在一上电后就一直在检测总线上是否有480-960微秒的低电平出现,如果有,在总线转为高电平后等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备,若没有检测到就一直在检测等待。



[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static int ds18b20_init(void)    
  2. {    
  3.     int retval = 0;    
  4.     
  5.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  6.     s3c2410_gpio_pullup(DQ, 0);    
  7.     
  8.     s3c2410_gpio_setpin(DQ, 1);    
  9.     udelay(2);    
  10.     s3c2410_gpio_setpin(DQ, 0); // 拉低ds18b20总线,复位ds18b20     
  11.     udelay(500);                // 保持复位电平500us     
  12.     
  13.     s3c2410_gpio_setpin(DQ, 1); // 释放ds18b20总线     
  14.     udelay(60);    
  15.     
  16.     // 若复位成功,ds18b20发出存在脉冲(低电平,持续60~240us)     
  17.     s3c2410_gpio_cfgpin(DQ, CFG_IN);    
  18.     retval = s3c2410_gpio_getpin(DQ);    
  19.     
  20.     udelay(500);    
  21.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  22.     s3c2410_gpio_pullup(DQ, 0);    
  23.     s3c2410_gpio_setpin(DQ, 1); // 释放总线     
  24.     
  25.     return retval;    
  26. }    

2、写时序

     写周期最少为60微秒,最长不超过120微秒,写周期一开始作为主机先把总线拉低1微秒表示写周期开始,随后若主机想写0,则继续拉低电平最少60微秒直至写周期结束,然后释放总线为高电平;若主机想写1,在一开始拉低总线电平1微秒后就释放总线为高电平,一直到写周期结束

     而作为从机的DS18B20则在检测到总线被拉低后等待15微秒然后从15μs到45μs开始对总线采样,在采样期内总线为高电平则为1,若采样期内总线为低电平则为0。



[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static void write_byte(unsigned char data)    
  2. {    
  3.     int i = 0;    
  4.     
  5.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  6.     s3c2410_gpio_pullup(DQ, 1);    
  7.     
  8.     for (i = 0; i < 8; i++)    
  9.     {    
  10.         // 总线从高拉至低电平时,就产生写时隙     
  11.         s3c2410_gpio_setpin(DQ, 1);    
  12.         udelay(2);    
  13.         s3c2410_gpio_setpin(DQ, 0);    
  14.         s3c2410_gpio_setpin(DQ, data & 0x01);    
  15.         udelay(60);    
  16.         data >>= 1;    
  17.     }    
  18.     s3c2410_gpio_setpin(DQ, 1); // 重新释放ds18b20总线     
  19. }    

3、读时序

      对于读数据操作时序也分为读0时序和读1时序两个过程,读时序是从主机把单总线拉低之后,在1微秒之后就得释放单总线为高电平,以让DS18B20把数据传输到单总线上。DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束;若要送出1则释放总线为高电平。

     主机在一开始拉低总线1微秒后释放总线,然后在包括前面的拉低总线电平1微秒在内的15微秒时间内完成对总线进行采样检测,采样期内总线为低电平则确认为0,采样期内总线为高电平则确认为1,完成一个读时序过程,至少需要60μs才能完成。



[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. static unsigned char read_byte(void)    
  2. {    
  3.     int i;    
  4.     unsigned char data = 0;    
  5.   // 总线从高拉至低,只需维持低电平17ts,再把总线拉高,就产生读时隙     
  6.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  7.     s3c2410_gpio_pullup(DQ, 0);   
  8.    
  9.     for (i = 0; i < 8; i++)    
  10.     {    
  11.           
  12.         s3c2410_gpio_setpin(DQ, 1);    
  13.         udelay(2);    
  14.         s3c2410_gpio_setpin(DQ, 0);    
  15.         udelay(2);    
  16.         s3c2410_gpio_setpin(DQ, 1);    
  17.         udelay(8);    
  18.         data >>= 1;    
  19.         s3c2410_gpio_cfgpin(DQ, CFG_IN);    
  20.         if (s3c2410_gpio_getpin(DQ))    
  21.             data |= 0x80;    
  22.         udelay(50);    
  23.     }    
  24.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  25.     s3c2410_gpio_pullup(DQ, 0);    
  26.     s3c2410_gpio_setpin(DQ, 1); // 释放ds18b20总线     
  27.     return data;    
  28. }    


二、操作方法

       DS18B20单线通信功能是分时完成的,有严格的时序概念,如果出现序列混乱,1-WIRE器件将不影响主机,因此读写时序很重要。系统对DS18B20的各种操作必须按协议进行,根据DS18B20的协议规定,微控制器控制DS18B20完成温度的转换必须经过以下4个步骤:

1)每次读写前对DS18B20进行复位初始化。复位要求主CPU将数据线下拉500μs,然后释放,DS18B20收到信号后等待16μs-60μs左右,然后发出60μs-240μs的存在低脉冲,主CPU收到此信号后表示复位成功。


2)发送一条ROM指令



3)发送存储器指令



1、让DS18B20进行一次温度转换的具体操作如下:

a -- 主机先做个复位操作;
b -- 主机再写跳过ROM的操作(CCH)命令;
c -- 然后主机接着写转换温度的操作指令,后面释放总线至少1秒,让DS18B20完成转换操作。需要注意的是每个命令字节在写的时候都是低字节先写,例如CCH的二进制为11001100,在写到总线上时要从低位开始写,写的顺序是“0、0、1、1、0、0、1、1”,整个操作的总线状态如图所。



2、读取RAM的温度数据,同样,这个操作也要按照三个步骤:

a -- 主机发出复位操作并接受DS18B20的应答(存在)脉冲;
b -- 主机发出跳过对ROM操作的命令(CCH);
c -- 主机发出读取RAM的命令(BEH),随后主机依次读取DS18B20发出的从第0-第8,共九个字节的数据。如果只想读取温度数据,那在读完第0和第1个数据后就不再理会后面DS18B20发出的数据即可,同样读取数据也是低位在前,整个操作的总线状态如图所示。



三、具体驱动编写

1、ds18b20_drv.c

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. #include <linux/init.h>     
  2. #include <linux/module.h>     
  3. #include <linux/delay.h>     
  4. #include <linux/kernel.h>     
  5. #include <linux/moduleparam.h>     
  6. #include <linux/init.h>     
  7. #include <linux/types.h>     
  8. #include <linux/fs.h>     
  9. #include <mach/regs-gpio.h>     
  10. #include <mach/hardware.h>     
  11. #include <linux/cdev.h>     
  12. #include <asm/uaccess.h>     
  13. #include <linux/errno.h>     
  14. #include <linux/gpio.h>     
  15. #include <linux/device.h>     
  16.     
  17. /* 相关引脚定义,方便以后移植 */    
  18. #define DQ         S3C2410_GPF(3)     
  19. #define CFG_IN     S3C2410_GPIO_INPUT     
  20. #define CFG_OUT    S3C2410_GPIO_OUTPUT     
  21.     
  22. // ds18b20主次设备号(动态分配)     
  23. static int ds18b20_major = 0;    
  24. static int ds18b20_minor = 0;    
  25. static int ds18b20_nr_devs = 1;    
  26.     
  27. // 定义设备类型     
  28. static struct ds18b20_device    
  29. {    
  30.     struct cdev cdev;    
  31. };    
  32.     
  33. struct ds18b20_device *ds18b20_devp;    /*设备结构体指针 */    
  34.     
  35. static struct class *ds18b20_class;    
  36. static struct class_device *ds18b20_class_dev;    
  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, size_t count, loff_t * f_pos);    
  44. void ds18b20_setup_cdev(struct ds18b20_device *dev, int index);    
  45.     
  46. static int ds18b20_open(struct inode *inode, struct file *filp)    
  47. {    
  48.     int flag = 0;    
  49.     
  50.     flag = ds18b20_init();    
  51.     if (flag & 0x01)    
  52.     {    
  53.         printk(KERN_WARNING "open ds18b20 failed\n");    
  54.         return -1;    
  55.     }    
  56.     printk(KERN_NOTICE "open ds18b20 successful\n");    
  57.     return 0;    
  58. }    
  59.     
  60. static int ds18b20_init(void)    
  61. {    
  62.     int retval = 0;    
  63.     
  64.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  65.     s3c2410_gpio_pullup(DQ, 0);    
  66.     
  67.     s3c2410_gpio_setpin(DQ, 1);    
  68.     udelay(2);    
  69.     s3c2410_gpio_setpin(DQ, 0); // 拉低ds18b20总线,复位ds18b20     
  70.     udelay(500);                // 保持复位电平500us     
  71.     
  72.     s3c2410_gpio_setpin(DQ, 1); // 释放ds18b20总线     
  73.     udelay(60);    
  74.     
  75.     // 若复位成功,ds18b20发出存在脉冲(低电平,持续60~240us)     
  76.     s3c2410_gpio_cfgpin(DQ, CFG_IN);    
  77.     retval = s3c2410_gpio_getpin(DQ);    
  78.     
  79.     udelay(500);    
  80.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  81.     s3c2410_gpio_pullup(DQ, 0);    
  82.     s3c2410_gpio_setpin(DQ, 1); // 释放总线     
  83.     
  84.     return retval;    
  85. }    
  86.     
  87. static void write_byte(unsigned char data)    
  88. {    
  89.     int i = 0;    
  90.     
  91.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  92.     s3c2410_gpio_pullup(DQ, 1);    
  93.     
  94.     for (i = 0; i < 8; i++)    
  95.     {    
  96.         // 总线从高拉至低电平时,就产生写时隙     
  97.         s3c2410_gpio_setpin(DQ, 1);    
  98.         udelay(2);    
  99.         s3c2410_gpio_setpin(DQ, 0);    
  100.         s3c2410_gpio_setpin(DQ, data & 0x01);    
  101.         udelay(60);    
  102.         data >>= 1;    
  103.     }    
  104.     s3c2410_gpio_setpin(DQ, 1); // 重新释放ds18b20总线     
  105. }    
  106.     
  107. static unsigned char read_byte(void)    
  108. {    
  109.     int i;    
  110.     unsigned char data = 0;    
  111.     
  112.     for (i = 0; i < 8; i++)    
  113.     {    
  114.         // 总线从高拉至低,只需维持低电平17ts,再把总线拉高,就产生读时隙     
  115.         s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  116.         s3c2410_gpio_pullup(DQ, 0);    
  117.         s3c2410_gpio_setpin(DQ, 1);    
  118.         udelay(2);    
  119.         s3c2410_gpio_setpin(DQ, 0);    
  120.         udelay(2);    
  121.         s3c2410_gpio_setpin(DQ, 1);    
  122.         udelay(8);    
  123.         data >>= 1;    
  124.         s3c2410_gpio_cfgpin(DQ, CFG_IN);    
  125.         if (s3c2410_gpio_getpin(DQ))    
  126.             data |= 0x80;    
  127.         udelay(50);    
  128.     }    
  129.     s3c2410_gpio_cfgpin(DQ, CFG_OUT);    
  130.     s3c2410_gpio_pullup(DQ, 0);    
  131.     s3c2410_gpio_setpin(DQ, 1); // 释放ds18b20总线     
  132.     return data;    
  133. }    
  134.     
  135. static ssize_t ds18b20_read(struct file *filp, char __user * buf, size_t count, loff_t * f_pos)    
  136. {    
  137.     int flag;    
  138.     unsigned long err;    
  139.     unsigned char result[2] = { 0x00, 0x00 };    
  140.     //struct ds18b20_device *dev = filp->private_data;     
  141.     
  142.     flag = ds18b20_init();    
  143.     if (flag & 0x01)    
  144.     {    
  145.         printk(KERN_WARNING "ds18b20 init failed\n");    
  146.         return -1;    
  147.     }    
  148.     
  149.     write_byte(0xcc);    
  150.     write_byte(0x44);    
  151.     
  152.     flag = ds18b20_init();    
  153.     if (flag & 0x01)    
  154.         return -1;    
  155.     
  156.     write_byte(0xcc);    
  157.     write_byte(0xbe);    
  158.     
  159.     result[0] = read_byte();    // 温度低八位     
  160.     result[1] = read_byte();    // 温度高八位     
  161.     
  162.     err = copy_to_user(buf, &result, sizeof(result));    
  163.     return err ? -EFAULT : min(sizeof(result), count);    
  164. }    
  165.     
  166. static struct file_operations ds18b20_dev_fops = {    
  167.     .owner = THIS_MODULE,    
  168.     .open = ds18b20_open,    
  169.     .read = ds18b20_read,    
  170. };    
  171.     
  172. void ds18b20_setup_cdev(struct ds18b20_device *dev, int index)    
  173. {    
  174.     int err, devno = MKDEV(ds18b20_major, ds18b20_minor + index);    
  175.     
  176.     cdev_init(&dev->cdev, &ds18b20_dev_fops);    
  177.     dev->cdev.owner = THIS_MODULE;    
  178.     err = cdev_add(&(dev->cdev), devno, 1);    
  179.     if (err)    
  180.     {    
  181.         printk(KERN_NOTICE "ERROR %d add ds18b20\n", err);    
  182.     }    
  183. }    
  184.     
  185. static int __init ds18b20_dev_init(void)    
  186. {    
  187.     int result;    
  188.     dev_t dev = 0;    
  189.     
  190.     dev = MKDEV(ds18b20_major, ds18b20_minor);    
  191.     
  192.     if (ds18b20_major)    
  193.     {    
  194.         result = register_chrdev_region(dev, ds18b20_nr_devs, "ds18b20");    
  195.     }    
  196.     else    
  197.     {    
  198.         result = alloc_chrdev_region(&dev, ds18b20_minor, ds18b20_nr_devs, "ds18b20");    
  199.         ds18b20_major = MAJOR(dev);    
  200.     }    
  201.     if (result < 0)    
  202.     {    
  203.         printk(KERN_WARNING "ds18b20: failed to get major\n");    
  204.         return result;    
  205.     }    
  206.     
  207.     /* 为新设备分配内存和初始化 */    
  208.     ds18b20_devp = kmalloc(sizeof(struct ds18b20_device), GFP_KERNEL);    
  209.     if (!ds18b20_devp)    
  210.     {                           /*申请失败 */    
  211.         result = -ENOMEM;    
  212.         goto fail_malloc;    
  213.     }    
  214.     memset(ds18b20_devp, 0, sizeof(struct ds18b20_device));    
  215.     
  216.     ds18b20_setup_cdev(ds18b20_devp, 0);    
  217.     
  218.     /* 自动创建设备节点 */    
  219.     ds18b20_class = class_create(THIS_MODULE, "ds18b20_sys_class");    
  220.     if (IS_ERR(ds18b20_class))    
  221.         return PTR_ERR(ds18b20_class);    
  222.     
  223.     ds18b20_class_dev =    
  224.         device_create(ds18b20_class, NULL, MKDEV(ds18b20_major, 0), NULL, "ds18b20");    
  225.     if (unlikely(IS_ERR(ds18b20_class_dev)))    
  226.         return PTR_ERR(ds18b20_class_dev);    
  227.     
  228.     return 0;    
  229.     
  230.   fail_malloc:    
  231.     unregister_chrdev_region(dev, 1);    
  232.     return result;    
  233. }    
  234.     
  235. static void __exit ds18b20_dev_exit(void)    
  236. {    
  237.     cdev_del(&ds18b20_devp->cdev);  /*注销cdev */    
  238.     kfree(ds18b20_devp);        /*释放设备结构体内存 */    
  239.     unregister_chrdev_region(MKDEV(ds18b20_major, 0), ds18b20_nr_devs); /*释放设备号 */    
  240.     device_unregister(ds18b20_class_dev);    
  241.     class_destroy(ds18b20_class);    
  242. }    
  243.     
  244. module_init(ds18b20_dev_init);    
  245. module_exit(ds18b20_dev_exit);    
  246. MODULE_LICENSE("Dual BSD/GPL");    

2、app-ds18b20.c
[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>     
  2. #include <stdlib.h>     
  3. #include <unistd.h>     
  4. #include <linux/ioctl.h>     
  5.     
  6. // 函数声明     
  7. void ds18b20_delay(int i);    
  8.     
  9. int main()    
  10. {    
  11.     int fd, i;    
  12.     unsigned char result[2];    // 从ds18b20读出的结果,result[0]存放低八位     
  13.     unsigned char integer_value = 0;    
  14.     float decimal_value = 0;    // 温度数值,decimal_value为小数部分的值     
  15.     float temperature = 0;    
  16.     
  17.     fd = open("/dev/ds18b20", 0);    
  18.     if (fd < 0)    
  19.     {    
  20.         perror("open device failed\n");    
  21.         exit(1);    
  22.     }    
  23.     while (1)    
  24.     {    
  25.         i++;    
  26.         read(fd, &result, sizeof(result));    
  27.         integer_value = ((result[0] & 0xf0) >> 4) | ((result[1] & 0x07) << 4);    
  28.         // 精确到0.25度     
  29.         decimal_value = 0.5 * ((result[0] & 0x0f) >> 3) + 0.25 * ((result[0] & 0x07) >> 2);    
  30.         temperature = (float)integer_value + decimal_value;    
  31.         printf("Current Temperature:%6.2f\n", temperature);    
  32.     
  33.         ds18b20_delay(500);    
  34.     }    
  35. }    
  36.     
  37. void ds18b20_delay(int i)    
  38. {    
  39.     int j, k;    
  40.     for (j = 0; j < i; j++)    
  41.         for (k = 0; k < 50000; k++) ;    
  42. }    

测试结果:

[cpp] view plaincopy
在CODE上查看代码片派生到我的代码片
  1. [root@www.linuxidc.com home]#    
  2. [root@www.linuxidc.com home]#./app-ds18b20    
  3. open ds18b20 successful    
  4. Current Temperature: 23.50    
  5. Current Temperature: 23.50    
  6. Current Temperature: 23.25    
  7. Current Temperature: 23.50    
  8. Current Temperature: 23.50    
  9. Current Temperature: 23.50    
  10. ^C    
  11. [root@www.linuxidc.com home]#    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401944.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 自定义View实现画背景和前景(ViewGroup篇)

2019独角兽企业重金招聘Python工程师标准>>> 在定义ListView的Selector时候&#xff0c;有个drawSelectorOnTop的属性&#xff0c;如果drawSelectorOnTop为true的话&#xff0c;Selector的效果是画在List Item的上面&#xff08;Selector是盖住了ListView的文字或者…

Linux的mmap内存映射机制解析

在讲述文件映射的概念时,不可避免的要牵涉到虚存(SVR 4的VM).实际上,文件映射是虚存的中心概念, 文件映射一方面给用户提供了一组措施,好似用户将文件映射到自己地址空间的某个部分,使用简单的内存访问指令读写文件&#xff1b;另一方面,它也可以用于内核的基本组织模式,在这种…

svn add Default@2x.png的文件含有@的文件名注意事项

为什么80%的码农都做不了架构师&#xff1f;>>> iOS的Icon里面&#xff0c;包含符号 &#xff0c;svn add Icon2x.png&#xff0c;没法加进去。 解决的办法是&#xff0c;在文件名最后加一个&#xff0c;例如 svn add Icon2x.png 或者svn add Icon\2x.png\ 转载于…

Linux 设备驱动的固件加载

作为一个驱动作者, 你可能发现你面对一个设备必须在它能支持工作前下载固件到它里面. 硬件市场的许多地方的竞争是如此得强烈, 以至于甚至一点用作设备控制固件的 EEPROM 的成本制造商都不愿意花费. 因此固件发布在随硬件一起的一张 CD 上, 并且操作系统负责传送固件到设备自身…

Linux USB 驱动开发(二)—— USB 驱动几个重要数据结构

前面我们学习了USB 驱动的一个描述符&#xff0c;下面来学习 USB 驱动的几个重要数据结构 一、struct usb_interface 接口函数 [cpp] view plaincopy struct usb_interface { struct usb_host_interface *altsetting; struct usb_host…

Linux USB 驱动开发(三)—— 编写USB 驱动程序

前面学习了USB驱动的一些基础概念与重要的数据结构&#xff0c;那么究竟如何编写一个USB 驱动程序呢&#xff1f;编写与一个USB设备驱动程序的方法和其他总线驱动方式类似&#xff0c;驱动程序把驱动程序对象注册到USB子系统中&#xff0c;稍后再使用制造商和设备标识来判断是否…

Linux USB 驱动开发(一)—— USB设备基础概念

在终端用户看来&#xff0c;USB设备为主机提供了多种多样的附加功能&#xff0c;如文件传输&#xff0c;声音播放等&#xff0c;但对USB主机来说&#xff0c;它与所有USB设备的接口都是一致的。一个USB设备由3个功能模块组成&#xff1a;USB总线接口、USB逻辑设备和功能单元&am…

Linux USB 驱动开发(四)—— 热插拔那点事

学习USB热插拔之前&#xff0c;先学习一些USB的硬件知识&#xff1a; 一、USB基础概念 1、硬件知识&#xff08;USB插座和插头&#xff09; 在最初的标准里&#xff0c;USB接头有4条线&#xff1a;电源&#xff0c;D-,D,地线。我们暂且把这样的叫做标准的USB接头吧。后来OTG出现…

Linux USB 驱动开发(五)—— USB驱动程序开发过程简单总结

设备驱动程序是操作系统内核和机器硬件之间的接口&#xff0c;由一组函数和一些私有数据组成&#xff0c;是应用程序和硬件设备之间的桥梁。在应用程序看来&#xff0c;硬件设备只是一个设备文件&#xff0c;应用程序可以像操作普通文件一样对硬件设备进行操作。 设备驱动程序是…

android软键盘上推ui解决

为什么80%的码农都做不了架构师&#xff1f;>>> http://bbs.csdn.net/topics/340198955 android软键盘上推ui解决 good job 转载于:https://my.oschina.net/macleo/blog/204882

Linux USB 驱动开发实例(一) —— USB摄像头驱动实现源码分析

Spac5xx的实现是按照标准的USB VIDEO设备的驱动框架编写&#xff08;其具体的驱动框架可参照/usr/src/linux/drivers/usb/usbvideo.c文件&#xff09;&#xff0c;整个源程序由四个主体部分组成&#xff1a; 设备模块的初始化模块和卸载模块&#xff0c;上层软件接口模块&#…

System Center 2012R2之SCVMM云部署SCOM(2-2)

SCVMM云部署SCOM安装过程1、在SCVMM中&#xff0c;使用WINDOWS SERVER 2012母盘创建云主机SCOM在SCVMM中先创建到一个私有云指定一个私有云名称选择资源主机指定逻辑网络默认选负载衡器跳过VIP模板跳过选择端口&#xff0c;下一步选择存储分类指定存储的VM路径各只读共享默认设…

Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试

参考2.6.14版本中的driver/usb/input/usbmouse.c。鼠标驱动可分为几个部分&#xff1a;驱动加载部分、probe部分、open部分、urb回调函数处理部分。 一、驱动加载部分 [cpp] view plaincopy static int __init usb_mouse_init(void) { int retval usb_register(&a…

MySQL5.6 更改字段属性仍旧会锁全表,注意这个坑!

如图&#xff1a;如果开发让修改表字段属性&#xff0c;建议用pt-online-schema-change。MySQL5.6的在线DDL会锁全表。注意这个坑。另外&#xff0c;增加、删除字段或索引不会锁全表&#xff0c;删除主键会锁全表。

Linux USB 驱动开发实例 (三)—— 基于USB总线的无线网卡浅析

回顾一下USB的相关知识 USB(Universal Serial Bus)总线又叫通用串行外部总线&#xff0c;它是20世纪90年代发展起来的。USB接口现在得到了广泛的应用和普及&#xff0c;现在的PC机中都带有大量的USB接口。它最大的特点就是方便通用、支持热插拔并且可以在一个接口上插上多个设备…

Linux 设备驱动开发思想 —— 驱动分层与驱动分离

前面我们学习I2C、USB、SD驱动时&#xff0c;有没有发现一个共性&#xff0c;就是在驱动开发时&#xff0c;每个驱动都分层三部分&#xff0c;由上到下分别是&#xff1a; 1、XXX 设备驱动 2、XXX 核心层 3、XXX 主机控制器驱动 而需要我们编写的主要是设备驱动部分&#xff0c…

CortexM0开发 —— UART时序分析

通用异步收发传输器(UniversalAsynchronousReceiver/Transmitter)&#xff0c;通常称作UART&#xff0c;是一种异步收发传输器。将数据由串行通信与并行通信间作传输转换&#xff0c;作为并行输入成为串行输出的芯片UART是一种通用串行数据总线&#xff0c;用于异步通信。该总线…

CortexM0开发 —— LPC11C14的UART使用方法

LPC1100系列微控制器UART LPC1100系列Cortex-M0微控制器具有一个符合16C550工业标准的异步串行口&#xff08;UART&#xff09;。此口同时增加了调制解调器&#xff08;Modem&#xff09;接口&#xff0c;DSR、DCD和RI Modem信号是只用于LQFP48和PLCC44封装的管脚配置。 特性…

Linux SD卡驱动开发(一) —— SD 相关基础概念

一.SD/MMC卡基础概念 1.1.什么是MMC卡 MMC&#xff1a;MMC就是MultiMediaCard的缩写&#xff0c;即多媒体卡。它是一种非易失性存储器件&#xff0c;体积小巧(24mm*32mm*1.4mm)&#xff0c;容量大,耗电量低,传输速度快&#xff0c;广泛应用于消费类电子产品中。 1.2.什么是SD卡…

Linux SD卡驱动开发(二) —— SD 卡驱动分析HOST篇

回顾一下前面的知识&#xff0c;MMC 子系统范围三个部分&#xff1a; HOST 部分是针对不同主机的驱动程序&#xff0c;这一部是驱动程序工程师需要根据自己的特点平台来完成的。 CORE 部分: 这是整个MMC 的核心存&#xff0c;这部分完成了不同协议和规范的实现&#xff0c;并为…