把嵌入式设备驱动比相亲,那总线就是红娘,设备是男方,驱动是女方.....

传感器技术 2020-03-02 00:00


一、platform 驱动的工作过程


platform模型驱动编程,需要实现platform_device(设备)与platform_driver(驱动)在platform(虚拟总线)上的注册、匹配,相互绑定,然后再做为一个普通的字符设备进行相应的应用,总之如果编写的是基于字符设备的platform驱动,在遵循并实现platform总线上驱动与设备的特定接口的情况下,最核心的还是字符设备的核心结构:cdev、 file_operations(他包含的操作函数接口)、dev_t(设备号)、设备文件(/dev)等,因为用platform机制编写的字符驱动,它的本质是字符驱动。


我们要记住,platform 驱动只是在字符设备驱动外套一层platform_driver 的外壳。


在一般情况下,2.6内核中已经初始化并挂载了一条platform总线在sysfs文件系统中。那么我们编写platform模型驱动时,需要完成两个工作:


a -- 实现platform驱动 

b -- 实现platform设备


然而在实现这两个工作的过程中还需要实现其他的很多小工作,在后面介绍。platform模型驱动的实现过程核心架构就很简单,如下所示:

 

platform驱动模型三个对象:platform总线、platform设备、platform驱动。

platform总线对应的内核结构:struct bus_type-->它包含的最关键的函数:match() (要注意的是,这块由内核完成,我们不参与)

platform设备对应的内核结构:struct platform_device-->注册:platform_device_register(unregister)

platform驱动对应的内核结构:struct platform_driver-->注册:platform_driver_register(unregister)

       

那具体platform驱动的工作过程是什么呢:


设备(或驱动)注册的时候,都会引发总线调用自己的match函数来寻找目前platform总线是否挂载有与该设备(或驱动)名字匹配的驱动(或设备),如果存在则将双方绑定;


如果先注册设备,驱动还没有注册,那么设备在被注册到总线上时,将不会匹配到与自己同名的驱动,然后在驱动注册到总线上时,因为设备已注册,那么总线会立即匹配与绑定这时的同名的设备与驱动,再调用驱动中的probe函数等;


如果是驱动先注册,同设备驱动一样先会匹配失败,匹配失败将导致它的probe函数暂不调用,而是要等到设备注册成功并与自己匹配绑定后才会调用。

 


二、实现platform 驱动与设备的详细过程




1、思考问题?

在分析platform 之前,可以先思考一下下面的问题:

a -- 为什么要用 platform 驱动?不用platform驱动可以吗?

b -- 设备驱动中引入platform 概念有什么好处?


现在先不回答,看完下面的分析就明白了,后面会附上总结。

 


2、platform_device 结构体 VS   platform_driver 结构体

这两个结构体分别描述了设备和驱动,二者有什么关系呢?先看一下具体结构体对比



前面提到,实现platform模型的过程就是总线对设备和驱动的匹配过程 。打个比方,就好比相亲,总线是红娘,设备是男方,驱动是女方:


a -- 红娘(总线)负责男方(设备)和女方(驱动)的撮合;    

b -- 男方(女方)找到红娘,说我来登记一下,看有没有合适的姑娘(汉子)—— 设备或驱动的注册

c -- 红娘这时候就需要看看有没有八字(二者的name 字段)匹配的姑娘(汉子)——match 函数进行匹配,看name是否相同;

d -- 如果八字不合,就告诉男方(女方)没有合适的对象,先等着,别急着乱做事 —— 设备和驱动会等待,直到匹配成功;

e -- 终于遇到八字匹配的了,那就结婚呗!接完婚,男方就向女方交代,我有多少存款,我的房子在哪,钱放在哪等等( struct resource    *resource),女方说好啊,于是去房子里拿钱,去给男方买菜啦,给自己买衣服、化妆品、首饰啊等等(int (*probe)(struct platform_device *) 匹配成功后驱动执行的第一个函数),当然如果男的跟小三跑了(设备卸载),女方也不会继续待下去的(  int (*remove)(struct platform_device *))。

 


3、设备资源结构体

在struct platform_device 结构体中有一重要成员 struct resource *resource


[cpp] view plain copy

1. struct resource {  

2.     resource_size_t start;  资源起始地址     

3.     resource_size_t end;   资源结束地址  

4.     const char *name;        

5.     unsigned long flags;   区分是资源什么类型的  

6.     struct resource *parent, *sibling, *child;  

7. };  

8.   

9. #define IORESOURCE_MEM        0x00000200  

10. #define IORESOURCE_IRQ        0x00000400     


flags 指资源类型,我们常用的是 IORESOURCE_MEM、IORESOURCE_IRQ  这两种。start 和 end 的含义会随着 flags而变更,如


a -- flags为IORESOURCE_MEM 时,start 、end 分别表示该platform_device占据的内存的开始地址和结束值; 

b -- flags为 IORESOURCE_IRQ   时,start 、end 分别表示该platform_device使用的中断号的开始地址和结束值; 


下面看一个实例:


[cpp] view plain copy

1. static struct  resource beep_resource[] =  

2. {  

3.     [0] = {  

4.             .start = 0x114000a0,  

5.         .end = 0x114000a0+0x4,  

6.             .flags = IORESOURCE_MEM,  

7.     },  

8.   

9.     [1] = {  

10.             .start = 0x139D0000,  

11.             .end = 0x139D0000+0x14,  

12.             .flags = IORESOURCE_MEM,  

13.     },  

14. };   


好酒好礼,五粮液十五酱!(点击进入)




4、将字符设备添加到platform的driver中


前面我们提到platform 驱动只是在字符设备驱动外套一层platform_driver 的外壳,下面我们看一下添加的过程:


[cpp] view plain copy

1. static struct file_operations hello_ops=  

2. {  

3.     .open = hello_open,  

4.     .release = hello_release,  

5.     .unlocked_ioctl = hello_ioctl,  

6. };  

7.   

8. static int hello_remove(struct platform_device *pdev)  

9. {  

10.     注销分配的各种资源  

11. }  

12.   

13. static int hello_probe(struct platform_device *pdev)  

14. {  

15.     1.申请设备号  

16.     2.cdev初始化注册,&hello_ops  

17.     3.从pdev读出硬件资源  

18.     4.对硬件资源初始化,ioremap,request_irq( )  

19. }  

20.   

21. static int hello_init(void)  

22. {  

23.     只注册 platform_driver  

24. }  

25.   

26. static void hello_exit(void)  

27. {  

28.     只注销 platform_driver  

29. }  


可以看到,模块加载和卸载函数仅仅通过paltform_driver_register()、paltform_driver_unregister() 函数进行 platform_driver 的注册和注销,而原先注册和注销字符设备的工作已经被移交到 platform_driver 的 probe() 和 remove() 成员函数中。



5、platform是如何匹配device和driver


这时就该总线出场了,系统为platform总线定义了一个bus_type 的实例platform_bus_type,其定义如下:


[cpp] view plain copy

1. struct bus_type platform_bus_type = {  

2.     .name        = "platform",  

3.     .dev_groups    = platform_dev_groups,  

4.     .match        = platform_match,  

5.     .uevent        = platform_uevent,  

6.     .pm        = &platform_dev_pm_ops,  

7. };  


其又是怎样工作的呢?在platform.c (e:\linux-3.14-fs4412\drivers\base)    31577    2014/3/31 中可以看到



[cpp] view plain copy

1. __platform_driver_register()  

2. {  

3.     drv->driver.bus = &platform_bus_type;     536行  

4. }  



在platform_bus_type 中调用 了platform_match:


[cpp] view plain copy

1. static int platform_match(struct device *dev, struct device_driver *drv)  

2. {  

3.     struct platform_device *pdev = to_platform_device(dev);  

4.     struct platform_driver *pdrv = to_platform_driver(drv);  

5.   

6.     匹配设备树信息,如果有设备树,就调用 of_driver_match_device() 函数进行匹配  

7.     if (of_driver_match_device(dev, drv))  

8.         return 1;  

9.   

10.   

11.     匹配id_table  

12.     if (pdrv->id_table)  

13.         return platform_match_id(pdrv->id_table, pdev) != NULL;  

14.   

15.     最基本匹配规则  

16.     return (strcmp(pdev->name, drv->name) == 0);  

17. }  



 6、解决问题

现在可以回答这两个问题了

a -- 为什么要用 platform 驱动?不用platform驱动可以吗?

b -- 设备驱动中引入platform 概念有什么好处?


引入platform模型符合Linux 设备模型 —— 总线、设备、驱动,设备模型中配套的sysfs节点都可以用,方便我们的开发;当然你也可以选择不用,不过就失去了一些platform带来的便利;


设备驱动中引入platform 概念,隔离BSP和驱动。在BSP中定义platform设备和设备使用的资源、设备的具体匹配信息,而在驱动中,只需要通过API去获取资源和数据,做到了板相关代码和驱动代码的分离,使得驱动具有更好的可扩展性和跨平台性。

 


三、实例



这是一个蜂鸣器的驱动,其实前面已经有解析 Linux 字符设备驱动开发基础(二)—— 编写简单 PWM 设备驱动, 下面来看一下,套上platform 外壳后的程序:



1、device.c



[cpp] view plain copy

1. #include <linux/module.h>  

2. #include <linux/device.h>  

3. #include <linux/platform_device.h>  

4. #include <linux/ioport.h>  

5.   

6. static struct resource beep_resource[] =  

7. {  

8.     [0] ={  

9.         .start = 0x114000a0,  

10.         .end =  0x114000a0 + 0x4,  

11.         .flags = IORESOURCE_MEM,  

12.     },  

13.   

14.     [1] ={  

15.         .start = 0x139D0000,  

16.         .end =  0x139D0000 + 0x14,  

17.         .flags = IORESOURCE_MEM,  

18.     }  

19. };  

20.   

21. static void hello_release(struct device *dev)  

22. {  

23.     printk("hello_release\n");  

24.     return ;  

25. }  

26.   

27.   

28.   

29. static struct platform_device hello_device=  

30. {  

31.     .name = "bigbang",  

32.     .id = -1,  

33.     .dev.release = hello_release,  

34.     .num_resources = ARRAY_SIZE(beep_resource),  

35.     .resource = beep_resource,  

36. };  

37.   

38. static int hello_init(void)  

39. {  

40.     printk("hello_init");  

41.     return platform_device_register(&hello_device);  

42. }  

43.   

44. static void hello_exit(void)  

45. {  

46.     printk("hello_exit");  

47.     platform_device_unregister(&hello_device);  

48.     return;  

49. }  

50.   

51. MODULE_LICENSE("GPL");  

52. module_init(hello_init);  

53. module_exit(hello_exit);  


 


2、driver.c



[cpp] view plain copy

1. #include <linux/module.h>  

2. #include <linux/fs.h>  

3. #include <linux/cdev.h>  

4. #include <linux/device.h>  

5. #include <linux/platform_device.h>  

6. #include <asm/io.h>  

7.   

8. static int major = 250;  

9. static int minor=0;  

10. static dev_t devno;  

11. static struct class *cls;  

12. static struct device *test_device;  

13.            

14. #define TCFG0         0x0000                 

15. #define TCFG1         0x0004                              

16. #define TCON          0x0008               

17. #define TCNTB0        0x000C            

18. #define TCMPB0        0x0010             

19.   

20. static unsigned int *gpd0con;  

21. static void *timer_base;  

22.   

23. #define  MAGIC_NUMBER    'k'  

24. #define  BEEP_ON    _IO(MAGIC_NUMBER    ,0)  

25. #define  BEEP_OFF   _IO(MAGIC_NUMBER    ,1)  

26. #define  BEEP_FREQ   _IO(MAGIC_NUMBER   ,2)  

27.   

28. static void fs4412_beep_init(void)  

29. {     

30.     writel ((readl(gpd0con)&~(0xf<<0)) | (0x2<<0),gpd0con);  

31.     writel ((readl(timer_base +TCFG0  )&~(0xff<<0)) | (0xff <<0),timer_base +TCFG0);   

32.     writel ((readl(timer_base +TCFG1 )&~(0xf<<0)) | (0x2 <<0),timer_base +TCFG1 );   

33.   

34.     writel (500, timer_base +TCNTB0  );  

35.     writel (250, timer_base +TCMPB0 );  

36.     writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x2 <<0),timer_base +TCON );   

37. }  

38.   

39. void fs4412_beep_on(void)  

40. {  

41.     writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x9 <<0),timer_base +TCON );  

42. }  

43.   

44. void fs4412_beep_off(void)  

45. {  

46.     writel ((readl(timer_base +TCON )&~(0xf<<0)) | (0x0 <<0),timer_base +TCON );  

47. }  

48.   

49. static void beep_unmap(void)  

50. {  

51.         iounmap(gpd0con);  

52.         iounmap(timer_base);  

53. }  

54.   

55. static int beep_open (struct inode *inode, struct file *filep)  

56. {  

57.     fs4412_beep_on();  

58.     return 0;  

59. }  

60.   

61. static int beep_release(struct inode *inode, struct file *filep)  

62. {  

63.      fs4412_beep_off();  

64.      return 0;  

65. }  

66.   

67. #define BEPP_IN_FREQ 100000  

68. static void beep_freq(unsigned long arg)  

69. {  

70.     writel(BEPP_IN_FREQ/arg, timer_base +TCNTB0  );  

71.     writel(BEPP_IN_FREQ/(2*arg), timer_base +TCMPB0 );  

72.   

73. }  

74.   

75. static long beep_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)  

76. {  

77.     switch(cmd)  

78.     {  

79.         case BEEP_ON:  

80.             fs4412_beep_on();  

81.             break;  

82.         case BEEP_OFF:  

83.             fs4412_beep_off();  

84.             break;  

85.         case BEEP_FREQ:  

86.             beep_freq( arg );  

87.             break;  

88.         default :  

89.             return -EINVAL;  

90.     }  

91.     return 0;  

92. }  

93.   

94. static struct file_operations beep_ops=  

95. {  

96.     .open     = beep_open,  

97.     .release = beep_release,  

98.     .unlocked_ioctl      = beep_ioctl,  

99. };  

100.   

101. static int beep_probe(struct platform_device *pdev)  

102. {  

103.     int ret;      

104.     printk("match ok!");  

105.       

106.     gpd0con = ioremap(pdev->resource[0].start,pdev->resource[0].end - pdev->resource[0].start);  

107.     timer_base = ioremap(pdev->resource[1].start, pdev->resource[1].end - pdev->resource[1].start);  

108.   

109.     devno = MKDEV(major,minor);  

110.     ret = register_chrdev(major,"beep",&beep_ops);  

111.   

112.     cls = class_create(THIS_MODULE, "myclass");  

113.     if(IS_ERR(cls))  

114.     {  

115.         unregister_chrdev(major,"beep");  

116.         return -EBUSY;  

117.     }  

118.   

119.     test_device = device_create(cls,NULL,devno,NULL,"beep");//mknod /dev/hello  

120.     if(IS_ERR(test_device))  

121.     {  

122.         class_destroy(cls);  

123.         unregister_chrdev(major,"beep");  

124.         return -EBUSY;  

125.     }  

126.       

127.     fs4412_beep_init();  

128.       

129.     return 0;  

130. }  

131.   

132. static int beep_remove(struct platform_device *pdev)  

133. {  

134.     beep_unmap();  

135.     device_destroy(cls,devno);  

136.     class_destroy(cls);   

137.     unregister_chrdev(major,"beep");  

138.   

139.     return 0;  

140. }  

141.   

142.   

143. static struct platform_driver beep_driver=  

144. {  

145.     .driver.name = "bigbang",  

146.     .probe = beep_probe,  

147.     .remove = beep_remove,  

148. };  

149.    

150.   

151. static int beep_init(void)  

152. {  

153.     printk("beep_init");  

154.       

155.     return platform_driver_register(&beep_driver);  

156. }  

157.   

158. static void beep_exit(void)  

159. {  

160.     printk("beep_exit");  

161.     platform_driver_unregister(&beep_driver);  

162.       

163.     return;  

164. }  

165.   

166.   

167. MODULE_LICENSE("GPL");  

168. module_init(beep_init);  

169. module_exit(beep_exit); 




3、makefile   



[cpp] view plain copy

1. ifneq  ($(KERNELRELEASE),)  

2. obj-m:=device.o driver.o  

3. $(info "2nd")  

4. else  

5. #KDIR := /lib/modules/$(shell uname -r)/build  

6. KDIR := /home/fs/linux/linux-3.14-fs4412  

7. PWD:=$(shell pwd)  

8. all:  

9.     $(info "1st")  

10.     make -C $(KDIR) M=$(PWD) modules  

11. clean:  

12.     rm -f *.ko *.o *.symvers *.mod.c *.mod.o *.order  

13. endif  


 


4、test.c




[cpp] view plain copy

1. #include <sys/types.h>  

2. #include <sys/stat.h>  

3. #include <fcntl.h>  

4. #include <stdio.h>  

5.   

6. main()  

7. {  

8.     int fd,i,lednum;  

9.   

10.     fd = open("/dev/beep",O_RDWR);  

11.     if(fd<0)  

12.     {  

13.         perror("open fail \n");  

14.         return ;  

15.     }  

16.       

17.     sleep(10);  

18.     close(fd);  

19. } 


  来源:玩转单片机


免责声明:本文系网络转载,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请第一时间告知,我们将根据您提供的证明材料确认版权并按国家标准支付稿酬或立即删除内容!本文内容为原作者观点,并不代表本公众号赞同其观点和对其真实性负责。

 
  

为您发布产品,请点击“阅读原文”

传感器技术 制造业的未来是智能化,智能化的基础就是传感器; 互联网的方向是物联网,物联网的基石也是传感器; 关注传感器技术,获得技术资讯、产品应用、市场机会,掌握最黑科技,为中国工业导航。
评论
  • 2024年12月09日 环洋市场咨询机构出版了一份详细的、综合性的调研分析报告【全球电机控制系统芯片 (SoC)行业总体规模、主要厂商及IPO上市调研报告,2024-2030】。本报告研究全球电机控制系统芯片 (SoC)总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析电机控制系统芯片 (SoC)市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从电机控制系统芯片 (SoC)产品类型细分、应用细分、企业、地区等角度,进行定量和定性分析,包括产量、产值、均价
    GIRtina 2024-12-09 11:32 166浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-10 16:13 63浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-09 08:53 97浏览
  • 在驾驶培训与考试的严谨流程中,EST580驾培驾考系统扮演着至关重要的数据角色。它不仅集成了转速监控、车速管理、转向角度测量、转向灯光控制以及手刹与安全带状态检测等多项功能,还通过高精度的OBD数据采集器实时捕捉车辆运行状态,确保学员在模拟及实际驾驶中的每一步操作都精准无误。EST580驾培驾考转速车速转向角转向灯光手刹安全带OBD数据采集器系统的重要性及其功能:1、提高评判效率:通过原车CAN协议兼容,不同车型通过刷写固件覆盖,不仅提高了考试的数字化、自动化程度,还减少了人为干预的安装需要,从
    lauguo2013 2024-12-09 16:51 97浏览
  • 我的一台很多年前人家不要了的九十年代SONY台式组合音响,接手时只有CD功能不行了,因为不需要,也就没修,只使用收音机、磁带机和外接信号功能就够了。最近五年在外地,就断电闲置,没使用了。今年9月回到家里,就一个劲儿地忙着收拾家当,忙了一个多月,太多事啦!修了电气,清理了闲置不用了的电器和电子,就是一个劲儿地扔扔扔!几十年的“工匠式”收留收藏,只能断舍离,拆解不过来的了。一天,忽然感觉室内有股臭味,用鼻子的嗅觉功能朝着臭味重的方向寻找,觉得应该就是这台组合音响?怎么会呢?这无机物的东西不会腐臭吧?
    自做自受 2024-12-10 16:34 68浏览
  •         在有电流流过的导线周围会感生出磁场,再用霍尔器件检测由电流感生的磁场,即可测出产生这个磁场的电流的量值。由此就可以构成霍尔电流、电压传感器。因为霍尔器件的输出电压与加在它上面的磁感应强度以及流过其中的工作电流的乘积成比例,是一个具有乘法器功能的器件,并且可与各种逻辑电路直接接口,还可以直接驱动各种性质的负载。因为霍尔器件的应用原理简单,信号处理方便,器件本身又具有一系列的du特优点,所以在变频器中也发挥了非常重要的作用。  &nb
    锦正茂科技 2024-12-10 12:57 43浏览
  • 进入11月中下旬,智能手机圈再度热闹起来。包括华为、小米、OPPO、vivo等诸多手机厂商,都在陆续预热发布新机,其中就包括华为Mate 70、小米Redmi K80、vivo的S20,IQOO Neo10等热门新机,这些热门新机的集中上市迅速吸引了全行业的目光。而在诸多手机厂商集体发布新机的背后,是智能手机行业的“触底反弹”。据机构数据显示,2024年第三季度,中国智能手机市场出货量约为6878万台,同比增长3.2%,连续四个季度保持同比增长,显然新一轮手机换机潮已在加速到来。憋了三年,国内智
    刘旷 2024-12-09 10:43 104浏览
  • 肖特基具有很多的应用场景, 可以做同步整流,防止电流倒灌和电源反接等,但是随着电源电流的增大,肖特基导通正向压降0.3~0.7v的劣势也越发明显,产生了很多的热,对于工程师的散热设计是个考验,增加了工程师的设计难度和产品成本,目前一种新的理想二极管及其控制器,目前正在得到越来越广泛的应用- BMS,无人机,PLC,安防,家电,电动工具,汽车等都在快速普及理想二极管有三种架构,内置电荷泵的类似无锡明芯微MX5050T这种,驱动能力会弱点,静态功耗200uA,外置电荷泵MX74700T的这种驱动能力
    王萌 2024-12-10 08:51 79浏览
  • 开发板在默认情况下,OpenHarmony系统开机后 30 秒会自动息屏,自动息屏会让不少用户感到麻烦,触觉智能教大家两招轻松取消自动息屏。使用触觉智能Purple Pi OH鸿蒙开发板演示,搭载了瑞芯微RK3566四核处理器,Laval鸿蒙社区推荐开发板,已适配全新OpenHarmony5.0 Release系统,SDK源码全开放!SDK源码中修改修改以下文件参数:base/powermgr/power_manager/services/native/profile/power_mode_co
    Industio_触觉智能 2024-12-09 11:39 108浏览
  • 本文介绍Linux系统(Ubuntu/Debian通用)挂载exfat格式U盘的方法,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。修改对应的内核配置文件# 进入sdk目录cdrk3562_linux# 编辑内核配置文件vi./kernel-5.10/arch/arm64/configs/rockchip_linux_defconfig注:不清楚内核使用哪个defc
    Industio_触觉智能 2024-12-10 09:44 78浏览
  • 全球知名半导体制造商ROHM Co., Ltd.(以下简称“罗姆”)宣布与Taiwan Semiconductor Manufacturing Company Limited(以下简称“台积公司”)就车载氮化镓功率器件的开发和量产事宜建立战略合作伙伴关系。通过该合作关系,双方将致力于将罗姆的氮化镓器件开发技术与台积公司业界先进的GaN-on-Silicon工艺技术优势结合起来,满足市场对高耐压和高频特性优异的功率元器件日益增长的需求。氮化镓功率器件目前主要被用于AC适配器和服务器电源等消费电子和
    电子资讯报 2024-12-10 17:09 50浏览
  • 智能汽车可替换LED前照灯控制运行的原理涉及多个方面,包括自适应前照灯系统(AFS)的工作原理、传感器的应用、步进电机的控制以及模糊控制策略等。当下时代的智能汽车灯光控制系统通过车载网关控制单元集中控制,表现特殊点的有特斯拉,仅通过前车身控制器,整个系统就包括了灯光旋转开关、车灯变光开关、左LED前照灯总成、右LED前照灯总成、转向柱电子控制单元、CAN数据总线接口、组合仪表控制单元、车载网关控制单元等器件。变光开关、转向开关和辅助操作系统一般连为一体,开关之间通过内部线束和转向柱装置连接为多,
    lauguo2013 2024-12-10 15:53 50浏览
  •         霍尔传感器是根据霍尔效应制作的一种磁场传感器。霍尔效应是磁电效应的一种,这一现象是霍尔(A.H.Hall,1855—1938)于1879年在研究金属的导电机构时发现的。后来发现半导体、导电流体等也有这种效应,而半导体的霍尔效应比金属强得多,利用这现象制成的各种霍尔元件,广泛地应用于工业自动化技术、检测技术及信息处理等方面。霍尔效应是研究半导体材料性能的基本方法。通过霍尔效应实验测定的霍尔系数,能够判断半导体材料的导电类型、载流子浓度及载流子
    锦正茂科技 2024-12-10 11:07 49浏览
  • 概述 通过前面的研究学习,已经可以在CycloneVGX器件中成功实现完整的TDC(或者说完整的TDL,即延时线),测试结果也比较满足,解决了超大BIN尺寸以及大量0尺寸BIN的问题,但是还是存在一些之前系列器件还未遇到的问题,这些问题将在本文中进行详细描述介绍。 在五代Cyclone器件内部系统时钟受限的情况下,意味着大量逻辑资源将被浪费在于实现较大长度的TDL上面。是否可以找到方法可以对此前TDL的长度进行优化呢?本文还将探讨这个问题。TDC前段BIN颗粒堵塞问题分析 将延时链在逻辑中实现后
    coyoo 2024-12-10 13:28 58浏览
  • 【萤火工场CEM5826-M11测评】OLED显示雷达数据本文结合之前关于串口打印雷达监测数据的研究,进一步扩展至 OLED 屏幕显示。该项目整体分为两部分: 一、框架显示; 二、数据采集与填充显示。为了减小 MCU 负担,采用 局部刷新 的方案。1. 显示框架所需库函数 Wire.h 、Adafruit_GFX.h 、Adafruit_SSD1306.h . 代码#include #include #include #include "logo_128x64.h"#include "logo_
    无垠的广袤 2024-12-10 14:03 50浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦