led和蜂鳴器驅(qū)動(廣州龍芯中科1B開發(fā)板)培訓(xùn)講學(xué)_第1頁
led和蜂鳴器驅(qū)動(廣州龍芯中科1B開發(fā)板)培訓(xùn)講學(xué)_第2頁
led和蜂鳴器驅(qū)動(廣州龍芯中科1B開發(fā)板)培訓(xùn)講學(xué)_第3頁
led和蜂鳴器驅(qū)動(廣州龍芯中科1B開發(fā)板)培訓(xùn)講學(xué)_第4頁
led和蜂鳴器驅(qū)動(廣州龍芯中科1B開發(fā)板)培訓(xùn)講學(xué)_第5頁
已閱讀5頁,還剩40頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Good is good, but better carries it.精益求精,善益求善。led和蜂鳴器驅(qū)動(廣州龍芯中科1B開發(fā)板)TOCo1-3huHYPERLINKl_Toc46311.前言PAGEREF_Toc46313HYPERLINKl_Toc30862.硬件電路PAGEREF_Toc30863HYPERLINKl_Toc142852.1.LED引腳PAGEREF_Toc142853HYPERLINKl_Toc5332.2.LED原理分析PAGEREF_Toc5334HYPERLINKl_Toc111042.3.蜂鳴器引腳PAGEREF_Toc111045HYPERLINKl_T

2、oc12862.4.蜂鳴器原理分析PAGEREF_Toc12865HYPERLINKl_Toc280773.GPIO相關(guān)分析PAGEREF_Toc280776HYPERLINKl_Toc123833.1.閱讀CPU手冊PAGEREF_Toc123836HYPERLINKl_Toc66633.2.Linux內(nèi)核源碼分析PAGEREF_Toc66636HYPERLINKl_Toc42964.點亮一個ledPAGEREF_Toc42969HYPERLINKl_Toc303504.1.源碼PAGEREF_Toc303509HYPERLINKl_Toc306064.2.運行結(jié)果PAGEREF_Toc30

3、60613HYPERLINKl_Toc277155.手動指定那個led亮PAGEREF_Toc2771513HYPERLINKl_Toc150945.1.源碼PAGEREF_Toc1509413HYPERLINKl_Toc196055.2.運行結(jié)果PAGEREF_Toc1960519HYPERLINKl_Toc209986.蜂鳴器驅(qū)動PAGEREF_Toc2099820HYPERLINKl_Toc144586.1.源碼PAGEREF_Toc1445820HYPERLINKl_Toc285997.參考資料PAGEREF_Toc2859920修訂歷史版本號更新日期更新內(nèi)容V1.02013.9.13

4、創(chuàng)建前言由于龍芯資料較少,現(xiàn)在又有點時間,寫了兩句,僅供初學(xué)者入門時參考,還望高手多多指教。硬件電路LED引腳先把電路圖貼出來我們選擇LED9作為本次實驗的對象。LED9接到龍芯1B的引腳T12再查龍芯1B處理器的用戶手冊v1.9如下圖即CAN0_RX為GPIO38.,同理可得Led6接GPIO39;led7接GPIO40;led8接GPIO41。如原理圖所示注意:這里有GPIO0,GPIO1,。GPIO38,GPIO39。到底表示什么意思?。總€人認為第一列的GPIO1,GPIO2,為原理圖中的編號,而第三列的GPIO38,GPIO39為CPU引腳編號,可以再CPU手冊中找到。如前面的led9

5、所示。這幾個引腳可以在源碼中定義為宏,詳細請見后面代碼,這里只貼出相關(guān)部分。LED原理分析LED又叫發(fā)光二極管,有正負兩個極,只要在正負兩極之間接上合適的正電壓,LED就導(dǎo)通,并發(fā)光。這里只需要讓CPU的GPIO引腳輸出低電平,對應(yīng)的LED就被點亮。比如GPIO38輸出低電平,即可點亮LED9。蜂鳴器引腳LED7接在CAN1_RX上,CAN1_RX經(jīng)過電阻后接蜂鳴器,如下圖所示所以LED7和蜂鳴器共用一個引腳GPIO40。蜂鳴器原理分析蜂鳴器通過NPN三極管提供所需的大電流,當(dāng)GPIO40輸出低電平時,NPN三極管截止,蜂鳴器不響;當(dāng)輸出高電平時,NPN三極管導(dǎo)通,蜂鳴器響。由于LED7和蜂鳴

6、器共用同一個引腳,并且為了開機后蜂鳴器不響(想起來煩人,哈哈)。所以引腳GPIO40必須輸出低電平,恰好低電平使LED導(dǎo)通,所以LED7在開機后一直亮著。GPIO相關(guān)分析閱讀CPU手冊首先看龍芯1B處理器的手冊,其中對GPIO相關(guān)的寄存器有:配置寄存器,輸入使能寄存器,輸入寄存器,配置輸出寄存器,MUX寄存器。根據(jù)經(jīng)驗,一般都是先配置GPIO為輸入還是輸出,然后讀輸入寄存器或者寫輸出寄存器實現(xiàn)輸入輸出功能。V1.9版的手冊中寫得還不是很清楚,我們這里也只能猜了。貼上手冊中的截圖作為對比參考,我把其它CPU的截圖也貼上相比較而言,龍芯1B處理器手冊寫得太簡單了,以至于沒有說清楚。Linux內(nèi)核源

7、碼分析現(xiàn)在我們來看一下linux內(nèi)核中GPIO相關(guān)代碼。源碼路徑“l(fā)inux內(nèi)核根目錄/arch/mips/loongson/ls1x/gpio.c”。我們想實現(xiàn)的功能就是簡單的在GPIO口輸出高低電平。源文件gpio.c中有個函數(shù)ls1b_gpio_direction_output(),從函數(shù)名字上看好像能實現(xiàn)這個功能。具體分析一下。/*函數(shù)功能:直接在某個GPIO輸出高電平或者低電平入?yún)ⅲ簊tructgpio_chip*chip可以為空指針unsignedgpioGPIO的序號intlevel電平值。1-高電平;0-低電平*/intls1b_gpio_direction_output(st

8、ructgpio_chip*chip,unsignedgpio,intlevel)u32temp;u32mask;/入?yún)z查:判斷是否超過最大的GPIO個數(shù),即GPIO的合法性檢查if(gpio=STLS1B_N_GPIO)return-EINVAL;/把高低電平值寫到輸出寄存器中g(shù)pio_set_value(gpio,level);/由于寄存器是32位的,一個寄存器最多可以控制32個GPIO/就比如:配置寄存器,就有配置寄存器0和配置寄存器1/所以這里分開處理if(gpio=32)/獲取鎖,執(zhí)行原子操作spin_lock(&gpio_lock);mask=1(gpio-32);/配置GPIO

9、引腳為GPIO功能temp=LOONGSON_GPIOCFG1;temp|=mask;LOONGSON_GPIOCFG1=temp;/配置GPIO引腳為輸出temp=LOONGSON_GPIOIE1;temp&=(mask);LOONGSON_GPIOIE1=temp;/釋放鎖spin_unlock(&gpio_lock);elsespin_lock(&gpio_lock);mask=1=STLS1B_N_GPIO)_gpio_set_value(gpio,state);return;/對不同GPIO操作不同的寄存器if(gpio=32)mask=1(gpio-32);/獲取鎖spin_loc

10、k(&gpio_lock);/把高低電平值寫到輸出寄存器中val=LOONGSON_GPIOOUT1;if(state)val|=mask;elseval&=(mask);LOONGSON_GPIOOUT1=val;/釋放鎖spin_unlock(&gpio_lock);elsemask=1gpio;spin_lock(&gpio_lock);val=LOONGSON_GPIOOUT0;if(state)val|=mask;elseval&=mask;LOONGSON_GPIOOUT0=val;spin_unlock(&gpio_lock);經(jīng)過以上分析,要讓GPIO輸出高低電平,首先寫輸出寄

11、存器,然后把引腳配置為GPIO,最后設(shè)置為輸出。點亮一個led源碼源碼包含一個驅(qū)動源程序、一個應(yīng)用源程序和一個Makefile。rootlocalhostled#catMakefile#ifKERNELRELEASEisdefined,wevebeeninvokedfromthe#kernelbuildsystemandcanuseitslanguage.ifneq($(KERNELRELEASE),)obj-m:=ls1b_led_driver.o#otherwisewewerecalleddirectlyfromthecommand#line;invokethekernelbuildsys

12、tem.elseKERNELDIR=/home/dev/develop/1b-linux-3.0-d8b47bbPWD:=$(shellpwd)default:$(MAKE)-C$(KERNELDIR)M=$(PWD)modulescp./ls1b_led_driver.ko/nfsramdisk/LS1Brootfs/testmipsel-linux-gccls1b_led_app.c-ols1b_led_appcpls1b_led_app/nfsramdisk/LS1Brootfs/testclean:rm*.o*.mod.c*.order*.symvers*.koendif這個Makef

13、ile是參考linuxdevicedriver修改的。也是比較通用的,只需要修改一個linux內(nèi)核路徑和驅(qū)動模塊文件名就可以了。這里把應(yīng)用程序的編譯也放在了一起。這樣執(zhí)行make時,驅(qū)動和應(yīng)用一起編譯。rootlocalhostled#catls1b_led_driver.c#include#include#include#include#include#include#include#include#include#include#include#include#defineLS1B_LED_1_ON(0)#defineLS1B_LED_1_OFF(1)intls1b_led_major=0

14、;intls1b_led_minor=0;structcdevls1b_led_devs;intls1b_led_open(structinode*inode,structfile*filp)printk(KERN_DEBUG%s:openn,_FUNCTION_);return0;intls1b_led_release(structinode*inode,structfile*file)printk(KERN_DEBUG%s:closen,_FUNCTION_);return0;ssize_tls1b_led_set(structfile*filp,constchar_user*buff,s

15、ize_tcount,loff_t*offp)ls1b_gpio_direction_output(NULL,38,0);printk(KERN_DEBUG%s:led9onn,_FUNCTION_);return0;structfile_operationsls1b_led_ops=.owner=THIS_MODULE,.open=ls1b_led_open,.release=ls1b_led_release,.write=ls1b_led_set,;MODULE_AUTHOR(caogoscaogos);MODULE_LICENSE(DualBSD/GPL);intls1b_led_ini

16、t(void)intresult;dev_tdevno;structcdev*dev=&ls1b_led_devs;structfile_operations*fops=&ls1b_led_ops;result=alloc_chrdev_region(&devno,0,1,ls1b_led);if(0result)printk(KERN_WARNINGls1b_led:unabletogetamjorn);returnresult;ls1b_led_major=MAJOR(devno);printk(KERN_DEBUGls1b_led:major=%dn,ls1b_led_major);cd

17、ev_init(dev,fops);dev-ops=fops;result=cdev_add(dev,devno,1);if(result)printk(KERN_NOTICEError%daddingls1b_led,result);returnresult;printk(KERN_DEBUGls1b_leddeviceinstalled.withmajor%dn,ls1b_led_major);return0;voidls1b_led_exit(void)cdev_del(&ls1b_led_devs);unregister_chrdev_region(MKDEV(ls1b_led_maj

18、or,0),1);printk(ls1b_leddeviceuninstalledn);module_init(ls1b_led_init);module_exit(ls1b_led_exit);這個驅(qū)動程序必linuxdevicedriver中的HelloWorldModule要稍微復(fù)雜點。不過已經(jīng)是非常簡單的字符設(shè)備驅(qū)動了。這個驅(qū)動程序的核心就是函數(shù)ls1b_led_set()。其中的ls1b_gpio_direction_output(NULL,38,0);的功能是讓GPIO38輸出低電平。然后把函數(shù)ls1b_led_set()作為該驅(qū)動structfile_operationsls1b

19、_led_ops的寫函數(shù),即應(yīng)用程序中調(diào)用write()函數(shù),就會對應(yīng)調(diào)用驅(qū)動的函數(shù)ls1b_led_set()。注意:函數(shù)ls1b_led_set()沒有對入?yún)⑦M行分別處理,只要應(yīng)用程序調(diào)用write()函數(shù),不管write什么內(nèi)容,都執(zhí)行GPIO38輸出低電平的操作。rootlocalhostled#catls1b_led_app.c#include#include#include#include#include#include#includeintmain(void)intdev_fd;charbuff2=0;dev_fd=open(/dev/led,O_RDWR|O_NONBLOCK)

20、;if(-1=dev_fd)printf(Canntopenfile/dev/ledn);return-1;write(dev_fd,buff,1);close(dev_fd);return0;這個應(yīng)用程序簡單來說就是打開設(shè)備文件,并執(zhí)行寫操作。即調(diào)用驅(qū)動中的函數(shù)ls1b_led_set()點亮LED。友情提示:內(nèi)核頂層配置中*Enableloadablemodulesupport一定要選上。運行結(jié)果/test#lsls1b_led_appls1b_led_driver.ko/test#echo8/proc/sys/kernel/printk/test#insmodls1b_led_drive

21、r.kols1b_led:major=253ls1b_leddeviceinstalled.withmajor253/test#mknod/dev/ledc2530/test#./ls1b_led_appls1b_led_open:openls1b_led_set:led9onls1b_led_release:close/test#當(dāng)然開發(fā)板上的LED9肯定被點亮。經(jīng)過前面分析可知,打印信息“l(fā)s1b_led_set:led9on”為驅(qū)動程序打印出來的。命令“echo8/proc/sys/kernel/printk”是將內(nèi)核打印級別調(diào)到最低。為了能把所有驅(qū)動中的printk打印信息打印出來。命

22、令“mknod/dev/ledc2530”新建設(shè)備節(jié)點。否則,應(yīng)用中open()會失敗。253為主設(shè)備號,根據(jù)前面的打印“l(fā)s1b_leddeviceinstalled.withmajor253”獲得的。手動指定那個led亮源碼在前面led驅(qū)動的基礎(chǔ)上改進了一下,現(xiàn)在可以手動輸入led序號,然后制定序號的led被點亮。驅(qū)動程序源碼ls1b_led_driver.c#include#include#include#include#include#include#include#include#include#include#include#include/led正極接3.3v,負極接cpu引腳/

23、cpu輸出低電平,led導(dǎo)通,亮#defineLS1B_LED_ON(0)/cpu輸出高電平,led截止,滅#defineLS1B_LED_OFF(1)/led引腳#defineLS1B_PIN_LED_9(38)/gpio38#defineLS1B_PIN_LED_6(39)/gpio39#defineLS1B_PIN_LED_7(40)/gpio40#defineLS1B_PIN_LED_8(41)/gpio41/led主次設(shè)備號,動態(tài)申請intls1b_led_major=0;intls1b_led_minor=0;structcdevls1b_led_devs;intls1b_led_

24、open(structinode*inode,structfile*filp)printk(KERN_DEBUG%s:openn,_FUNCTION_);return0;intls1b_led_release(structinode*inode,structfile*file)printk(KERN_DEBUG%s:closen,_FUNCTION_);return0;/*功能:將led序號轉(zhuǎn)換為對應(yīng)的引腳入?yún)?unsignedintled_indexled序號出參:無返回值:unsignedintled_gpioled引腳*/unsignedintls1b_led_index_to_pin(

25、unsignedintled_index)switch(led_index)case9:returnLS1B_PIN_LED_9;case6:returnLS1B_PIN_LED_6;case7:returnLS1B_PIN_LED_7;case8:returnLS1B_PIN_LED_8;default:return0;/*功能:熄滅指定led入?yún)?unsignedintled_indexled序號出參:無返回值:無*/voidls1b_led_off(unsignedintled_index)ls1b_gpio_direction_output(NULL,ls1b_led_index_to

26、_pin(led_index),LS1B_LED_OFF);/*功能:點亮指定led入?yún)?unsignedintled_indexled序號出參:無返回值:無*/voidls1b_led_on(unsignedintled_index)ls1b_gpio_direction_output(NULL,ls1b_led_index_to_pin(led_index),LS1B_LED_ON);/*功能:關(guān)閉所有l(wèi)ed入?yún)?無出參:無返回值:無*/voidls1b_led_off_all()ls1b_led_off(9);/關(guān)閉led9ls1b_led_off(6);ls1b_led_off(7);

27、ls1b_led_off(8);ssize_tls1b_led_set(structfile*filp,constchar_user*buff,size_tcount,loff_t*offp)charinputbuff10=0;unsignedintled_index=0;unsignedinttmp=0;/關(guān)閉所有l(wèi)edls1b_led_off_all();/打開指定ledcopy_from_user(inputbuff,buff,1);/一次只處理一個ledled_index=(unsignedint)(inputbuff0);ls1b_led_on(led_index);printk(K

28、ERN_DEBUG%s:led%donn,_FUNCTION_,led_index);return0;structfile_operationsls1b_led_ops=.owner=THIS_MODULE,.open=ls1b_led_open,.release=ls1b_led_release,.write=ls1b_led_set,;MODULE_AUTHOR(caogoscaogos);MODULE_LICENSE(DualBSD/GPL);intls1b_led_init(void)intresult;dev_tdevno;structcdev*dev=&ls1b_led_devs;

29、structfile_operations*fops=&ls1b_led_ops;result=alloc_chrdev_region(&devno,0,1,ls1b_led);if(0result)printk(KERN_WARNINGls1b_led:unabletogetamjorn);returnresult;ls1b_led_major=MAJOR(devno);printk(KERN_DEBUGls1b_led:major=%dn,ls1b_led_major);cdev_init(dev,fops);dev-ops=fops;result=cdev_add(dev,devno,1

30、);if(result)printk(KERN_NOTICEError%daddingls1b_led,result);returnresult;printk(KERN_DEBUGls1b_leddeviceinstalled.withmajor%dn,ls1b_led_major);return0;voidls1b_led_exit(void)cdev_del(&ls1b_led_devs);unregister_chrdev_region(MKDEV(ls1b_led_major,0),1);printk(ls1b_leddeviceuninstalledn);module_init(ls

31、1b_led_init);module_exit(ls1b_led_exit);應(yīng)用程序源碼#include#include#include#include#include#include#includeintmain(void)intdev_fd;charbuff2=0;unsignedinttmp=0;dev_fd=open(/dev/led,O_RDWR|O_NONBLOCK);if(-1=dev_fd)printf(Canntopenfile/dev/ledn);return-1;/根據(jù)用戶輸入,點亮指定的ledbuff0=getchar()-0;write(dev_fd,buff,1

32、);/由于led7和蜂鳴器接在同一個引腳上/避免蜂鳴器一直響,最后把蜂鳴器關(guān)了sleep(1);buff0=7;write(dev_fd,buff,1);close(dev_fd);return0;Makefilerootlocalhostled#catMakefile#ifKERNELRELEASEisdefined,wevebeeninvokedfromthe#kernelbuildsystemandcanuseitslanguage.ifneq($(KERNELRELEASE),)obj-m:=ls1b_led_driver.o#otherwisewewerecalleddirectly

33、fromthecommand#line;invokethekernelbuildsystem.elseKERNELDIR=/home/dev/develop/1b-linux-3.0-d8b47bbPWD:=$(shellpwd)default:$(MAKE)-C$(KERNELDIR)M=$(PWD)modulescp./ls1b_led_driver.ko/nfsramdisk/LS1Brootfs/testmipsel-linux-gccls1b_led_app.c-ols1b_led_appcpls1b_led_app/nfsramdisk/LS1Brootfs/test/clean:rm*.o*.mod.c*.order*.symvers*.kols1b_led_appendifrootl

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論