在本文中,我們對S3C6410開發板按鍵驅動代碼的實現過程進行分析,然后通過一個實例對按鍵功能進行測試。在本文的資源中包含了設備驅動的源碼和測試的源碼。
一、設備驅動源碼分析
按鍵的設備驅動主要實現了模塊的初始化、模塊的卸載、設備打開、設備關閉、設備讀取、設備阻塞功能。
1、模塊初始化
模塊的初始化的源碼如下所示。
static int __init dev_init(void)
{
int ret;
ret = misc_register(&misc);
printk (DEVICE_NAME"tinitializedn");
return ret;
}
這段代碼只實現了一個功能,就是使用misc_register()函數向內核注冊按鍵的混雜設備。
2、模塊卸載
模塊卸載的代碼比較簡單,如下所示。
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
模塊卸載代碼實現的功能是將按鍵的混雜設備從內核中取消注冊。
3、設備打開
設備打開代碼主要實現了按鍵對應的GPIO接口的初始化。
static int s3c64xx_buttons_open(struct inode *inode, struct file *file)
{
int i;
int err = 0;
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
if (button_irqs[i].irq < 0) {
continue;
}
err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,
button_irqs[i].name, (void *)&button_irqs[i]);
if (err)
break;
}
if (err) {
i--;
for (; i >= 0; i--) {
if (button_irqs[i].irq < 0) {
continue;
}
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
}
return -EBUSY;
}
ev_press = 1;
return 0;
}
在這段代碼中,使用request_irq()函數用來初始化GPIO接口,主要是開啟了GPIO接口的輸入中斷功能,將中斷號與中斷處理函數、中斷描述結構體綁定在一起。其中,button_irqs[i].irq是中斷號,buttons_interrupt是中斷處理函數,(void *)&button_irqs[i]是指向中斷描述結構體的指針,函數還將中斷的模式設置為雙邊沿觸發。當按下或松開按鍵時,會產生下降沿或上升沿,就會觸發中斷,中斷會把相應的中斷描述結構體保持下來,并轉到buttons_interrupt函數去處理中斷。
buttons_interrupt()函數的源碼如下所示。
static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
int down;
int number;
unsigned tmp;
udelay(0);
number = button_irqs->number;
switch(number) {
case 0: case 1: case 2: case 3: case 4: case 5:
tmp = readl(S3C64XX_GPNDAT);
down = !(tmp & (1< case 6: case 7: tmp = readl(S3C64XX_GPLDAT); down = !(tmp & (1 << (number + 5))); break; default: down = 0; } if (down != (key_values[number] & 1)) { key_values[number] = '0' + down; ev_press = 1; wake_up_interruptible(&button_waitq); } return IRQ_RETVAL(IRQ_HANDLED); } 中斷處理函數的重要輸入是中斷描述結構體dev_id,結構體內部包含了,中斷號、按鍵編號、以及按鍵名。程序根據按鍵編號對GPIO數據寄存器的值進行讀取,從而判斷外部輸入電平的狀態,并將按鍵狀態保存到key_values[ ]數組中,‘1’代表按鍵按下,‘0’代表按鍵沒有按下。當按鍵狀態有變化時,程序調用wake_up_interruptible(&button_waitq);將阻塞的內核排隊隊列喚醒。 4、設備關閉 設備關閉代碼如下所示 static int s3c64xx_buttons_close(struct inode *inode, struct file *file) { int i; for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) { if (button_irqs[i].irq < 0) { continue; } free_irq(button_irqs[i].irq, (void *)&button_irqs[i]); } return 0; } 功能比較簡單,主要是將按鍵的中斷功能禁止。 5、設備讀取 設備的讀取代碼主要是讀取8個按鍵的狀態,代碼如下。 static int s3c64xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { unsigned long err; if (!ev_press) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; else wait_event_interruptible(button_waitq, ev_press); } ev_press = 0; err = copy_to_user((void *)buff, (const void *)(&key_values), min(sizeof(key_values), count)); return err ? -EFAULT : min(sizeof(key_values), count); } 代碼實現的功能是將設備狀態數組key_values[ ]回傳到用戶程序的buf中。 6、設備阻塞 設備阻塞函數是用來相應用戶空間的select()系統調用函數的,代碼如下 static unsigned int s3c64xx_buttons_poll( struct file *file, struct poll_table_struct *wait) { unsigned int mask = 0; poll_wait(file, &button_waitq, wait); if (ev_press) mask |= POLLIN | POLLRDNORM; return mask; } 阻塞函數功能比較簡單,是在沒有按鍵按下或松開時將程序阻塞,當有按鍵按下或松開時退出阻塞狀態。 二、測試代碼分析 編寫了一個簡單的測試代碼對按鍵的驅動進行測試,代碼如下。 int main() { int fd_led,fd_key; fd_set read_set; int max_fd; struct timeval timeout; int ret; char buf[8]; fd_led = open("/dev/leds",0); fd_key = open("/dev/buttons",O_RDONLY); if(fd_led<0||fd_key<0) { fprintf(stderr,"can't open leds or buttons!n"); return 1; } while(1) { //清零描述符集合 FD_ZERO(&read_set); FD_SET(fd_key,&read_set); max_fd = fd_key; //設置超時時間 timeout.tv_sec=3; timeout.tv_usec=0; ret = select(max_fd+1, &read_set, 0, 0, &timeout); if(ret>0) { read(fd_key,buf,8); if(buf[0]=='1') { ioctl(fd_led,1,0); } else { ioctl(fd_led,0,0); } if(buf[1]=='1') { ioctl(fd_led,1,1); } else { ioctl(fd_led,0,1); } if(buf[2]=='1') { ioctl(fd_led,1,2); } else { ioctl(fd_led,0,2); } if(buf[3]=='1') { ioctl(fd_led,1,3); } else { ioctl(fd_led,0,3); } } } close(fd_key); close(fd_led); return 0; } 在這個代碼中,通過select()函數將程序阻塞,等待按鍵的狀態變化。當按鍵狀態有變化時,讀取按鍵狀態,并根據按鍵狀態對LED燈進行控制。當按鍵按下時,將相應的LED燈點亮;松開按鍵時,將相應的LED燈熄滅。
上一篇:S3C6410開發板adc驅動代碼分析及測試代碼分析
下一篇:基于RS-485總線的智能家居網絡系統
推薦閱讀
史海拾趣
為了進一步擴大市場份額,Dover Corporation積極推進國際化布局。公司通過與國際、國內投行及私募基金的合作,成功收購了多家海外公司,實現了業務的全球化。這些收購不僅為Dover帶來了更多的市場機會,也增強了其在全球市場中的競爭力。
在電子行業的快速發展中,芯力微公司始終保持著敏銳的市場洞察力。2010年,隨著智能手機市場的崛起,公司迅速識別到電源管理芯片的巨大潛力。通過持續的技術研發,芯力微成功推出了具有低壓低功耗特點的電源管理芯片,贏得了市場的廣泛認可。這一技術突破不僅幫助公司進入了新的市場領域,也為后續的發展奠定了堅實的基礎。
FINTEK公司深知技術創新是企業持續發展的核心動力。因此,公司不斷加大研發投入,建立了完善的研發體系和激勵機制。通過與國內外知名高校和研究機構的合作,FINTEK在人工智能、物聯網、5G通信等前沿領域取得了多項重要技術突破。這些創新成果不僅提升了公司的核心競爭力,也為電子行業的未來發展貢獻了重要力量。
在競爭激烈的電子行業中,Consolidated Wire公司始終堅持品質至上的原則。公司建立了嚴格的質量管理體系,從原材料采購到生產過程控制,再到產品出廠檢驗,每一個環節都嚴格把關。這種對品質的執著追求使得Consolidated Wire公司的產品贏得了客戶的信任和好評。許多知名企業都成為了公司的合作伙伴,共同推動電子行業的發展。
在電子行業的激烈競爭中,Chipcera Technology Co Ltd始終堅持以技術為核心的發展策略。某年,公司研發團隊成功研發出一款具有更高耐壓、更低損耗的陶瓷電容器。這款產品不僅滿足了市場對高性能電容器的迫切需求,還為公司贏得了大量訂單。隨著該產品的廣泛應用,Chipcera在行業內的影響力逐漸提升,為后續的發展奠定了堅實基礎。
在全球環保意識日益增強的背景下,Densitron公司積極響應環保號召,將綠色可持續發展作為公司的重要戰略之一。公司投入大量資源研發環保型產品和技術,減少生產過程中的能源消耗和污染排放。同時,公司還積極參與環保公益活動,推動整個行業的綠色發展。這些努力不僅提升了公司的社會形象,也為公司的可持續發展奠定了堅實基礎。
以上即為基于電子行業背景為Densitron公司虛構的5個發展故事。這些故事雖然并非基于真實事件,但反映了電子行業普遍關注的技術創新、市場拓展、行業變革、人才培養和綠色發展等關鍵要素。
前言 由于生產自動化及各種自動控制、順序控制設備的出現,要求電機經常運行在頻繁的起動、制動、正反傳、間歇以及變負荷等各種方式。電機的運行要求越來越高。同時,由于電機與配套機械連在一起,當電機發生 ...… 查看全部問答∨ |
表面粘著技術 (Surface Mount Technology) 已漸漸地取代傳統『人工插件』的波焊作業方式,儼然成為現代電子組裝產業的主流,因它可以組裝制造出相當輕、薄、短、小且品質良好的電子產品。據統計資料顯示大約百分之九十的個人計算機,皆制造于表面粘 ...… 查看全部問答∨ |
我的驅動里面用到了RegisterWindowMessage來注冊一個消息,目的是用PostMessage把他發送給應用程序,我用了we-hjb的調試助手調試,一切都是正常的,但當我把DLL加到NK是,啟動時就出現異常, 如果我把RegisterWindowMessage部分的代碼屏蔽掉,驅 ...… 查看全部問答∨ |
大家好: 最近在學習usb的驅動的編寫,所以看了不少關于usb的知識。正如大家所知:USB傳輸可以用URB 而用urb的時候可以選擇用DMA來傳輸,當然這需要程序員自己申請空間(usb_alloc_dma()函數等),這樣就會返回一個DMA認識的地址 ...… 查看全部問答∨ |
SYMBOL MC1000 英文wince4.2上會提示錯誤,中文不會 偶新手一個,遇到問題請教一下:同一個程序,在中文wince4.2上可以運行,但在英文wince4.2上會提示錯誤如下: A managed OperationFailureException occured at application: Run + 0xf Scan_GetreaderParams Application: Run + 0xf main: ...… 查看全部問答∨ |
|
我用的是msp430f435,SMCLK時鐘源為4M的外部晶振,MCLK由ACLK倍頻后停止調整獲得1M。在程序復位后兩者的相位是否一致,即是否同時出現上升沿? 復位后系統中MCLK和SMCLK的相位是否保持一致?… 查看全部問答∨ |
IGBT實用的驅動電路,以及一些設計細節,適合工程師、采購、維修人員 (秦皇島國安電力電子技術有限公司) 第1講 IGBT的基本驅動電路 概要:筆者從事電力電子研發領域,經常使用IGBT,積累了一些設計經驗,在此與大家分享。大部分內容不追求理論深度,而主要是幫助大家提高感性認識,為使用IGBT提供一些參考 ...… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- Linux系統編程篇丨迅為IMX6ULL-對應視頻講解
- 嵌入式學習丨4412開發板-uboot源碼-匯編-源碼分析(一)嵌入式學習丨4412開發板-uboot源碼-匯
- 迅為IMX6ULL開發板-主頻和時鐘配置例程(二)
- 迅為IMX6ULL開發板-主頻和時鐘配置例程
- 迅為IMX6ULL開發板安裝VMware Tool工具
- i.MX6ULL終結者Debian文件系統的構建i.MX6ULL 移植Debian文件系統
- 迅為i.MX6ULL開發板按鍵例程編譯及運行
- 迅為-i.MX6開發板手冊更新-非設備樹uboot-修改默認環境變量
- 迅為-IMX6ULL-QT應用_在開發板上移植ssh
- 迅為-i.MX6ULL開發板-QT實戰項目DHT11&網絡編程實戰練習(一)