歡迎您光臨本站 註冊首頁

求串口驅動幫助!!!

←手機掃碼閱讀     火星人 @ 2014-03-24 , reply:0

我剛開始自學嵌入式Linux,對其入門函數LED修改為了8位流水燈,下面是一些個人理解,如有不當之處,望各位大俠們能給予指正,謝謝!另外,我現在使用的是mini2440開發板使用2.6.29的內核版本,在接觸串口程序時有些手足無措的感覺,對串口的應用程序還有一點皮毛的認識,但是它的驅動程序卻怎麼也看不懂,尋遍了許多網站也沒找到有關此串口驅動的解釋,現在迫切望各位大俠們能指點一些學習驅動程序的好方法。我目前有較多的應用程序開發書籍,對驅動的學習多依賴網路。若大俠們誰能抽出一點時間幫助在下,小弟感激不盡!!!
我的QQ:843013501

一、應用程序:在main()函數之前,自己編寫了一個小的延時程序,方便觀察流水燈的流動效果。在main()函數里,先用使用open函數打開設備8weiled0,並將打開成功與否的返回值賦給文件描述符fd,接著進行判斷:若打開失敗,會繼續打開設備8weiled,若打開失敗,則會將錯誤輸出到標準錯誤中,同時程序退出。若打開設備文件成功,則程序繼續向下執行能實現流水燈效果的無限循環語句。進入循環后,會依次為要操作的led賦予亮或滅的狀態,通過ioctl()函數調用驅動函數,完成對led操作,然後調用延時子函數,並依次向後做循環操作,最終實現流水燈的效果。在這個無限循環語句的後面,是關閉文件的close()函數,和最終的退出語句。
#include
#include
#include
#include

static int fd; //led設備文件描述符的變數

int yanshi(unsigned int a) //延時子函數
{
unsigned int ys1,ys2,ys3; //延時參數
for(;a>0;a--){
for(ys1=0;ys1<200;ys1++){
for(ys2=0;ys2<200;ys2++){
for(ys3=0;ys3<200;ys3++);
}
}
}
}

int main(void)
{
int zt; //定義led的狀態,0或者1;
int led_no; //定義控制哪個LED,0-7,一共八個
int fd; //LED設備文件描述符
fd = open("/dev/8weiled0", 0); //若成功打開設備8weiled0,則fd值為1,反之為-1。
if (fd < 0) {
fd = open("/dev/8weiled", 0); //若成功打開設備8weiled,則fd值為1,反之為-1。
}
if (fd < 0) {
perror("open device 8weiled"); //將錯誤輸出到標準輸出錯誤裡面。
exit(1);
}
for(;;){
//LED流水燈的調用和延時部分,通過ioctl函數完成對
//單個LED的操作,第二個for循環作延時用。
for(led_no=0;led_no<8;led_no++){
zt=1; //led亮
ioctl(fd, zt, led_no);
yanshi(2);
zt=0; //led滅
ioctl(fd, zt, led_no);
yanshi(2);
}
}
close(fd); //關閉led_no
return 0;
}

二、驅動程序:先宏定義驅動程序的設備名為「8weiled」,后定義八個控制led的GPIO口的管腳,並將這些管腳設置為輸出狀態。接著為應用程序中的ioctl函數調用的驅動程序中的ioctl函數設置屬性,包括索引節點、打開文件的路徑、定義指令鍵和控制哪個led的自變數,對應用程序中ioctl函數控制led狀態的自變數的識別是通過switch語句來判斷的,對要操作的led的編號識別是用if語句加以判斷的,如果命令輸入正確,則會進一步掉用內核中相應的指令,最終顯示出被操作的led狀態。後面是這個操作文件的一些屬性及設備相關信息,還有內核載入函數的聲明、初始化,最後是卸載。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


#define DEVICE_NAME "8weiled" // 定義設備名為'8weiled'

static unsigned long led_table [] = { //定義八個控制led的GPIO口管腳
S3C2410_GPF0,
S3C2410_GPF1,
S3C2410_GPF2,
S3C2410_GPF3,
S3C2410_GPF4,
S3C2410_GPF5,
S3C2410_GPF6,
S3C2410_GPG0,
};

static unsigned int led_cfg_table [] = { //GPIO口的狀態為輸出
S3C2410_GPF0_OUTP,
S3C2410_GPF1_OUTP,
S3C2410_GPF2_OUTP,
S3C2410_GPF3_OUTP,
S3C2410_GPF4_OUTP,
S3C2410_GPF5_OUTP,
S3C2410_GPF6_OUTP,
S3C2410_GPG0_OUTP,
};

static int sbc2440_leds_ioctl( // I/O口的控制
struct inode *inode, //索引節點,即程序在磁碟中的存放處
struct file *file, //打開文件的路徑
unsigned int cmd, //定義指令鍵
unsigned long arg) //定義自變數
{
switch(cmd) { //led的狀態(cmd的值為0,滅;為1,亮)
case 0: //滅
case 1: //亮
if (arg > 8) {
return -EINVAL;
}
s3c2410_gpio_setpin(led_table[arg], !cmd);
//為gpio口設置引腳(第幾個led,此led的亮滅狀態)
return 0; //程序正確執行完
default: //否則(即出錯處理)
return -EINVAL;
}
}

static struct file_operations dev_fops = { //對文件的操作,{}內為屬性
.owner = THIS_MODULE, //此處為一個宏,指向編譯模塊時自動創建的_ _this_module變數
.ioctl = sbc2440_leds_ioctl,
};

static struct miscdevice misc = { //記錄混合設備的一些信息
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};

static int __init dev_init(void) //內核模塊載入函數聲明,初始化
{
int ret;

int i;

for (i = 0; i < 8; i++) {
s3c2410_gpio_cfgpin(led_table, led_cfg_table); //(第幾個led,led的配置)
s3c2410_gpio_setpin(led_table, 0); //設置引腳的輸出電平
}

ret = misc_register(&misc); //註冊設備名

printk (DEVICE_NAME"\tinitialized\n");

return ret;
}

static void __exit dev_exit(void) //內核模塊卸載函數
{
misc_deregister(&misc);
}

module_init(dev_init); //內核模塊載入函數,初始化
module_exit(dev_exit); //內核模塊卸載
MODULE_LICENSE("GPL"); //遵循的協議
MODULE_AUTHOR("FriendlyARM Inc."); //作者

[火星人 ] 求串口驅動幫助!!!已經有303次圍觀

http://coctec.com/docs/linux/show-post-141015.html