在 linux 驅(qū)動(dòng)中字符設(shè)備驅(qū)動(dòng)是必須掌握的,本章主要介紹字符設(shè)備應(yīng)用的程序,無(wú)論是學(xué)習(xí)了后面的知識(shí)自己寫的字符驅(qū)動(dòng),還是已有的字符驅(qū)動(dòng),都需要能夠?qū)懸恍┖?jiǎn)單的應(yīng)用程序。即使從事 Linux 驅(qū)動(dòng)方面的工作,Linux 驅(qū)動(dòng)寫出來(lái)之后,也需要由驅(qū)動(dòng)程序員編寫簡(jiǎn)單的應(yīng)用程序來(lái)進(jìn)行測(cè)試的。 另外,關(guān)于驅(qū)動(dòng)部分,迅為電子有專門的驅(qū)動(dòng)實(shí)驗(yàn)教程提供給大家學(xué)習(xí),大家有了這些基礎(chǔ)之后再去學(xué)習(xí)底層的知識(shí)就會(huì)很容易了。 在本手冊(cè)的 10.22 章節(jié),大家可以看到這些 C 程序也是可以在 Android 下面運(yùn)行的,只不過(guò)沒(méi)有圖形界面。 本章配套視頻為: “視頻 06_01 字符設(shè)備控制之 main 函數(shù)傳參數(shù)” “視頻 06_02 字符設(shè)備控制之 led 燈” “視頻 06_03 字符設(shè)備控制之 buzzer 蜂鳴器” “視頻 06_04 字符設(shè)備控制之 ADC 模數(shù)轉(zhuǎn)換” 17.1 入口 main 函數(shù)的參數(shù) 在和用戶交流的過(guò)程中,雖然所有人都學(xué)習(xí)過(guò) C 語(yǔ)言,但是對(duì) C 語(yǔ)言中的 main 函數(shù)的用法并不是很清楚。由于后面的實(shí)驗(yàn)需要用到這部分知識(shí),這里就占用一個(gè)小節(jié),先簡(jiǎn)單介紹一下 main 函數(shù)。 main 函數(shù)簡(jiǎn)介 main 函數(shù)作為應(yīng)用程序的入口,在頭文件“#include int main(int argc,char **argv) 參數(shù) argc,表示參數(shù)的個(gè)數(shù) 參數(shù)**argv,存儲(chǔ)輸入字符的數(shù)組,argv[0]表示程序名稱,argv[1]——argv[n]輸入的參數(shù) 不傳參數(shù)的時(shí)候定義為 int main(void) 函數(shù) main 的返回值為類型為 int,用于判斷程序執(zhí)行成功還是失敗 main 函數(shù)例程 編寫簡(jiǎn)單的 argvc.c 文件測(cè)試 main 函數(shù)。 ![]() 如上圖所示,將輸入的參數(shù)第一個(gè)和第二個(gè)轉(zhuǎn)換成 int 類型,賦值給 i 和 j,最后輸出打印。 其中 argv[0]為程序名稱,這里就是后面要編譯的目標(biāo)文件“argvc”。 編譯運(yùn)行測(cè)試 在 Ubuntu 系統(tǒng)下,如下圖所示,進(jìn)入前面實(shí)驗(yàn)創(chuàng)建的目錄“/home/linuxsystemcode/”,使用命令“mkdircharcontrol”新建 charcontrol 文件夾,將源碼 argvc.c 拷貝進(jìn)去,進(jìn)入新建的文件夾 charcontrol,如下圖所示。 ![]() 使用命令“arm-none-linux-gnueabi-gcc -o argvc argvc.c -static”編譯 argvc 文件, 如下圖所示,使用命令“l(fā)s”可以看到生成了 argvc 可執(zhí)行文件。 ![]() 這里介紹 U 盤拷貝代碼的方法,也可以編譯進(jìn)文件系統(tǒng),具體方法參考 10.3.5 小節(jié)。 將編譯成的可執(zhí)行文件 argvc,拷貝到 U 盤,啟動(dòng)開(kāi)發(fā)板,插入 U 盤,加載 U 盤,運(yùn)行程序如下。 ![]() 如上圖所示,程序成功運(yùn)行,打。 the Program name is ./mnt/udisk/argvc。 因?yàn)檫\(yùn)行的程序就是“./mnt/udisk/argvc”,這是第一個(gè)參數(shù) The command line has 2 argument: 10,11。 輸入的參數(shù)是 10 和 11,對(duì)應(yīng) argv[2]和 argv[2]。 17.2 字符類 led 燈 在前面介紹 open 函數(shù)的時(shí)候,已經(jīng)提到過(guò)如何打開(kāi)字符類設(shè)備,獲得句柄的方法和一般文件都是一樣。 Led 燈的設(shè)備節(jié)點(diǎn)在/dev 目錄下,如下圖所示,在超級(jí)終端可以使用 ls 命令查找。 ![]() 由于涉及到硬件知識(shí),這里簡(jiǎn)單介紹一下硬件原理,如下圖所示,led 小燈的硬件原理很簡(jiǎn)單。 ![]() 如上圖所示,給 KP_COL0 和 VDD50_EN 網(wǎng)絡(luò)高電平,三極管 L9014 就會(huì)導(dǎo)通,電源 VSYS 就會(huì)將電壓加到電阻 R 和 led 小燈上,小燈就會(huì)亮。 給 KP_COL0 和 VDD50_EN 網(wǎng)絡(luò)低電平,三極管 L9014 就會(huì)截止,形成斷路,小燈滅。 在前面介紹過(guò),如果要給文件進(jìn)行寫操作,那么使用的是 write 函數(shù)。對(duì)于 led 小燈的操作,使用寫函數(shù),理論上也是可以的。但是對(duì)于 IO 口(這里的 IO 口指的是硬件上的 IO 口, 不是指 IO 文件)的 操作,Linux 專門設(shè)計(jì)了一個(gè)高效的函數(shù) ioctl。 這個(gè)函數(shù)在頭文件#include int ioctl( int fd, int request, int cmd); 參數(shù) fd,函數(shù) open 返回的句柄。 參數(shù) request 和參數(shù) cmd,由內(nèi)核驅(qū)動(dòng)決定具體操作,例如 request 可以代表那個(gè) IO 口,cmd 代表對(duì) IO 進(jìn)行什么樣的操作,也可以反過(guò)來(lái)。具體的含義由驅(qū)動(dòng)工程師在驅(qū)動(dòng)中 switch 決定。 返回值:返回 0 成功;返回-1,出錯(cuò)。 小燈測(cè)試?yán)?/strong> 編寫簡(jiǎn)單的 leds.c 文件測(cè)試小燈。首先添加頭文件,如下圖所示。 通過(guò) main 參數(shù)傳過(guò)來(lái)的參數(shù)是 char 字符格式的,如果要傳遞給 ioctl 函數(shù),需要用到數(shù)值轉(zhuǎn)化函數(shù)atoi,添加了頭文件#include 接著由于小燈的數(shù)量和命令都是 2,所以對(duì)小燈數(shù)量和操作數(shù)進(jìn)行宏定義 #define LED_NUM 2 #define LED_C 2。 ![]() 然后 main 函數(shù)如下圖所示。 ![]() 如上圖所示。 第 33 行,調(diào)用了 ioctl 函數(shù),將 main 函數(shù)的第一個(gè)和第二個(gè)參數(shù)傳入驅(qū)動(dòng)。 第 19 行,解釋那個(gè)參數(shù)具體代表什么含義,"argv1 is cmd;argv2 is io”,參數(shù) 1 對(duì)應(yīng)命令,參數(shù) 2 對(duì)應(yīng)具體那個(gè) led 燈。 第 36 行,將打開(kāi)的設(shè)備節(jié)點(diǎn)"/dev/leds"關(guān)閉。 編譯運(yùn)行測(cè)試 在 Ubuntu 系統(tǒng)下,如下圖所示,進(jìn)入前面實(shí)驗(yàn)創(chuàng)建的目錄“/home/linuxsystemcode/charcontrol”,將源碼 leds.c 拷貝進(jìn)去,如下圖所示。 ![]() 使用命令“arm-none-linux-gnueabi-gcc -o leds leds.c -static”編譯 leds 文件,如下圖所示,使用命令“l(fā)s”可以看到生成了 leds 可執(zhí)行文件。 ![]() 這里介紹 U 盤拷貝代碼的方法,也可以編譯進(jìn)文件系統(tǒng),具體方法參考實(shí)驗(yàn) 02 將編譯成的可執(zhí)行文件 open,拷貝到 U 盤,啟動(dòng)開(kāi)發(fā)板,插入 U 盤,加載 U 盤,運(yùn)行程序如下。 如下圖所示,如果不加參數(shù)會(huì)有提示,然后報(bào)錯(cuò)。 ![]() 如下圖所示,使用命令“./mnt/udisk/leds 0 0”運(yùn)行,可以看到靠近蜂鳴器的小燈滅了。 ![]() 所有參數(shù)對(duì)小燈的控制如下: 0 0 靠近蜂鳴器的小燈滅; 0 1 靠近按鍵的小燈滅; 1 0 靠近蜂鳴器的小燈亮; 1 1 靠近按鍵的小燈亮。用戶可以自行測(cè)試一下。 ![]() |