日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

树莓派linux驱动学习之LED控制

發(fā)布時(shí)間:2025/6/15 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 树莓派linux驱动学习之LED控制 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? ? 前面我們編寫了hello world的程序,接下來繼續(xù)研究GPIO功能,通過GPIO來控制LED的亮滅,這在單片機(jī)中應(yīng)該算是十分簡(jiǎn)單的一個(gè)程序了,但是在Linux系統(tǒng)中控制GPIO沒有那么簡(jiǎn)單,難點(diǎn)就在于GPIO地址的獲取,也是我一直在糾結(jié)的問題。

一、GPIO地址

? ? ? ? 我看了中嵌的嵌入式開發(fā)視頻,里面使用三星2440控制LED的亮滅,但是驅(qū)動(dòng)程序中沒有寫清楚具體的底層是如何實(shí)現(xiàn)的,這也是我查找的重點(diǎn)。我首先翻閱了樹莓派CPU(bcm2835)的芯片手冊(cè),查到了GPIO的物理地址:
? ? ? ? 但是在芯片資料的最開始,有提到芯片內(nèi)部已經(jīng)把上圖中的物理總線地址抽象到了面對(duì)操作系統(tǒng)的物理地址:

? ? ? ? 所以,我們?cè)诰帉戲?qū)動(dòng)程序的時(shí)候,IO空間的起始地址是0x20000000,加上GPIO的偏移量2000000,所以GPIO的物理地址應(yīng)該是從0x20200000開始的,然后在這個(gè)基礎(chǔ)上進(jìn)行Linux系統(tǒng)的MMU內(nèi)存虛擬化管理,銀蛇到虛擬地址上。

二、硬件平臺(tái)

? ? ? ? 我在樹莓派的擴(kuò)展口的GPIO 17上接上了一個(gè)LED:

三、編寫驅(qū)動(dòng)代碼

? ? ? ? 一般的設(shè)備驅(qū)動(dòng)我們需要設(shè)置主設(shè)備號(hào)和次設(shè)備號(hào),在編寫應(yīng)用程序的時(shí)候還要生成設(shè)備文件,比較麻煩。Linux針對(duì)像LED這樣的操作,有一種設(shè)備叫做混雜設(shè)備:是一種特殊的字符設(shè)備,雜設(shè)備早已經(jīng)存在,是為了給開發(fā)者一個(gè)較為簡(jiǎn)單的操作方式,因?yàn)椴挥迷僦匦律暾?qǐng)一個(gè)設(shè)備號(hào)了(misc就是混雜設(shè)備的意思)。 ? ? ? ? 驅(qū)動(dòng)代碼: [cpp]?view plaincopy
  • #include?<linux/miscdevice.h>??
  • #include?<linux/delay.h>??
  • #include?<asm/irq.h>??
  • #include?<linux/kernel.h>??
  • #include?<linux/module.h>??
  • #include?<linux/init.h>??
  • #include?<linux/mm.h>??
  • #include?<linux/fs.h>??
  • #include?<linux/types.h>??
  • #include?<linux/delay.h>??
  • #include?<linux/moduleparam.h>??
  • #include?<linux/slab.h>??
  • #include?<linux/errno.h>??
  • #include?<linux/ioctl.h>??
  • #include?<linux/cdev.h>??
  • #include?<linux/string.h>??
  • #include?<linux/list.h>??
  • #include?<linux/pci.h>??
  • #include?<asm/uaccess.h>??
  • #include?<asm/atomic.h>??
  • #include?<asm/unistd.h>??
  • #include?<asm/io.h>??
  • #include?<asm/uaccess.h>??
  • #include?<linux/ioport.h>??
  • ??
  • #include?"bcm2835.h"??
  • ??
  • //?Blinks?on?RPi?Plug?P1?pin?11?(which?is?GPIO?pin?17)??
  • #define?PIN?RPI_GPIO_P1_11??
  • ??
  • int?open_state?=?0;?????????//文件打開狀態(tài)??
  • ??
  • static?int?leds_open(struct?inode?*inode,?struct?file?*filp)??
  • {??
  • ????if(open_state?==?0)????
  • ????{????
  • ????????open_state?=??1;????
  • ????????printk("Open?file?suc!\n");????
  • ????????return?0;????
  • ????}????
  • ????else????
  • ????{????
  • ????????printk("The?file?has?opened!\n");????
  • ????????return?-1;????
  • ????}????
  • }??
  • ??
  • static?int?leds_ioctl(struct?file*filp,?unsigned?int?cmd,?unsigned?long?arg)??
  • {??
  • ????switch(cmd)????
  • ????{????
  • ????????case?0:????
  • ????????????bcm2835_gpio_clr(PIN);??
  • ????????????printk("LED?OFF!\n");??
  • ????????????break;????
  • ????????case?1:????
  • ????????????bcm2835_gpio_set(PIN);??
  • ????????????printk("LED?ON!\n");??
  • ????????????break;????
  • ??
  • ????????default:????
  • ????????????return-EINVAL;????
  • ????}????
  • ??
  • ????return?0;??
  • }??
  • ??
  • static?int?leds_release(struct?inode?*inode,?struct?file?*filp)??
  • {??
  • ????if(open_state?==?1)????
  • ????{????
  • ????????open_state?=??0;????
  • ????????printk("close?file?suc!\n");????
  • ????????return?0;????
  • ????}????
  • ????else????
  • ????{????
  • ????????printk("The?file?has?closed!\n");????
  • ????????return?-1;????
  • ????}????
  • }??
  • ??
  • static?const?struct?file_operations?leds_fops?=?{??
  • ????.owner?=?THIS_MODULE,??
  • ????.open?=?leds_open,??
  • ????.unlocked_ioctl?=?leds_ioctl,??
  • ????.release?=?leds_release,??
  • };??
  • ??
  • static?struct?miscdevice?misc?=?{??
  • ????.minor?=MISC_DYNAMIC_MINOR,??
  • ????.name?="my_leds",??
  • ????.fops?=&leds_fops,??
  • };??
  • ??
  • ??
  • static?int?__init?leds_init(void)??
  • {??
  • ????int?ret;??
  • ??
  • ????//注冊(cè)混雜設(shè)備??
  • ????ret?=misc_register(&misc);??
  • ??
  • ????//配置功能選擇寄存器為輸出??
  • ????bcm2835_gpio_fsel(PIN,?BCM2835_GPIO_FSEL_OUTP);??
  • ??
  • ????//設(shè)置輸出電平為高電平,LED亮??
  • ????bcm2835_gpio_set(PIN);??
  • ??
  • ????printk("ledsinit.\n");??
  • ????return?ret;??
  • }??
  • ??
  • static?void?leds_exit(void)??
  • {??
  • ????//LED滅??
  • ????bcm2835_gpio_clr(PIN);??
  • ??
  • ????misc_deregister(&misc);??????????
  • ??
  • ????printk("leds_exit\n");??
  • }??
  • ??
  • module_init(leds_init);??
  • module_exit(leds_exit);??
  • ??
  • MODULE_AUTHOR("Hu?Chunxu");??
  • MODULE_LICENSE("GPL");??
  • ? ? 硬件相關(guān)操作: [cpp]?view plaincopy
  • #include?<linux/miscdevice.h>??
  • #include?<linux/delay.h>??
  • #include?<asm/irq.h>??
  • #include?<linux/kernel.h>??
  • #include?<linux/module.h>??
  • #include?<linux/init.h>??
  • #include?<linux/mm.h>??
  • #include?<linux/fs.h>??
  • #include?<linux/types.h>??
  • #include?<linux/delay.h>??
  • #include?<linux/moduleparam.h>??
  • #include?<linux/slab.h>??
  • #include?<linux/errno.h>??
  • #include?<linux/ioctl.h>??
  • #include?<linux/cdev.h>??
  • #include?<linux/string.h>??
  • #include?<linux/list.h>??
  • #include?<linux/pci.h>??
  • #include?<asm/uaccess.h>??
  • #include?<asm/atomic.h>??
  • #include?<asm/unistd.h>??
  • #include?<asm/io.h>??
  • #include?<asm/uaccess.h>??
  • #include?<linux/ioport.h>??
  • ??
  • #include?"bcm2835.h"??
  • ??
  • int?bcm2835_gpio_fsel(uint8_t?pin,?uint8_t?mode)??
  • {??
  • ????//初始化GPIOB功能選擇寄存器的物理地址??
  • ????volatile?uint32_t?*?bcm2835_gpio?=?(volatile?uint32_t?*)ioremap(BCM2835_GPIO_BASE,?16);??
  • ????volatile?uint32_t?*?bcm2835_gpio_fsel?=?bcm2835_gpio?+?BCM2835_GPFSEL0/4?+?(pin/10);??
  • ????uint8_t???shift?=?(pin?%?10)?*?3;??
  • ????uint32_t??value?=?mode?<<?shift;??
  • ????*bcm2835_gpio_fsel?=?*bcm2835_gpio_fsel?|?value;??
  • ??
  • ????printk("fsel?address:?0x%lx?:?%x\n",?bcm2835_gpio_fsel,?*bcm2835_gpio_fsel);??
  • ??
  • ????return?0;??
  • }??
  • ??
  • int?bcm2835_gpio_set(uint8_t?pin)??
  • {??
  • ????//GPIO輸出功能物理地址??
  • ????volatile?uint32_t?*?bcm2835_gpio?=?(volatile?uint32_t?*)ioremap(BCM2835_GPIO_BASE,?16);??
  • ????volatile?uint32_t?*?bcm2835_gpio_set?=?bcm2835_gpio?+?BCM2835_GPSET0/4?+?pin/32;??
  • ????uint8_t???shift?=?pin?%?32;??
  • ????uint32_t??value?=?1?<<?shift;??
  • ????*bcm2835_gpio_set?=?*bcm2835_gpio_set?|?value;??
  • ??
  • ????printk("set?address:??0x%lx?:?%x\n",?bcm2835_gpio_set,?*bcm2835_gpio_set);??
  • ??
  • ????return?0;??
  • }??
  • ??
  • int?bcm2835_gpio_clr(uint8_t?pin)??
  • {??
  • ???//GPIO清除功能物理地址??
  • ????volatile?uint32_t?*?bcm2835_gpio?=?(volatile?uint32_t?*)ioremap(BCM2835_GPIO_BASE,?16);??
  • ????volatile?uint32_t?*?bcm2835_gpio_clr?=?bcm2835_gpio?+?BCM2835_GPCLR0/4?+?pin/32;??
  • ????uint8_t???shift?=?pin?%?32;??
  • ????uint32_t??value?=?1?<<?shift;??
  • ????*bcm2835_gpio_clr?=?*bcm2835_gpio_clr?|?value;??
  • ??????
  • ????printk("clr?address:??0x%lx?:?%x\n",?bcm2835_gpio_clr,?*bcm2835_gpio_clr);??
  • ??
  • ????return?0;??
  • }??

  • ? ? ? ? 應(yīng)用測(cè)試程序: [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<stdlib.h>??
  • #include?<unistd.h>??
  • #include?<sys/ioctl.h>??
  • ??
  • int?main(int?argc,?char?**argv)??
  • {??
  • ????int?on;??
  • ????int?fd;??
  • ????if?(argc?!=?2?||?sscanf(argv[1],"%d",?&on)?!=?1?||on?<?0?||?on?>?1?)?{??
  • ????????fprintf(stderr,?"Usage:%s?0|1\n",argv[0]);??
  • ????????exit(1);??
  • ????}??
  • ????fd?=?open("/dev/my_leds",?0);??
  • ????if?(fd?<?0)?{??
  • ????????perror("open?device?leds");??
  • ????????exit(1);??
  • ????}??
  • ????/*通過ioctl來控制燈的亮、滅*/??
  • ????if(on){??
  • ????????printf("turn?on?leds!\n");??
  • ????????ioctl(fd,?1);??
  • ????}??
  • ????else?{??
  • ????????printf("turn?off?leds!\n");??
  • ????????ioctl(fd,?0);??
  • ????}??
  • ????close(fd);??
  • ????return?0;??
  • }??

  • ? ? ? 分別編譯,插入模塊,然后運(yùn)行測(cè)試程序,可以控制LED的亮滅了。

    ----------------------------------------------------------------

    歡迎大家轉(zhuǎn)載我的文章。

    總結(jié)

    以上是生活随笔為你收集整理的树莓派linux驱动学习之LED控制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。