嵌入式试验报告.docx

上传人:b****4 文档编号:4275899 上传时间:2023-05-06 格式:DOCX 页数:20 大小:21.93KB
下载 相关 举报
嵌入式试验报告.docx_第1页
第1页 / 共20页
嵌入式试验报告.docx_第2页
第2页 / 共20页
嵌入式试验报告.docx_第3页
第3页 / 共20页
嵌入式试验报告.docx_第4页
第4页 / 共20页
嵌入式试验报告.docx_第5页
第5页 / 共20页
嵌入式试验报告.docx_第6页
第6页 / 共20页
嵌入式试验报告.docx_第7页
第7页 / 共20页
嵌入式试验报告.docx_第8页
第8页 / 共20页
嵌入式试验报告.docx_第9页
第9页 / 共20页
嵌入式试验报告.docx_第10页
第10页 / 共20页
嵌入式试验报告.docx_第11页
第11页 / 共20页
嵌入式试验报告.docx_第12页
第12页 / 共20页
嵌入式试验报告.docx_第13页
第13页 / 共20页
嵌入式试验报告.docx_第14页
第14页 / 共20页
嵌入式试验报告.docx_第15页
第15页 / 共20页
嵌入式试验报告.docx_第16页
第16页 / 共20页
嵌入式试验报告.docx_第17页
第17页 / 共20页
嵌入式试验报告.docx_第18页
第18页 / 共20页
嵌入式试验报告.docx_第19页
第19页 / 共20页
嵌入式试验报告.docx_第20页
第20页 / 共20页
亲,该文档总共20页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

嵌入式试验报告.docx

《嵌入式试验报告.docx》由会员分享,可在线阅读,更多相关《嵌入式试验报告.docx(20页珍藏版)》请在冰点文库上搜索。

嵌入式试验报告.docx

嵌入式试验报告

嵌入式试验报告

代码分析:

1.GPIO驱动分析:

Write,read,open,release四个函数与前边相同,只有基本操作和调试信息。

Ioctl函数为GPIO口的控制函数,其代码如下:

ssize_tSIMPLE_GPIO_LED_ioctl(structinode*inode,structfile*file,unsignedintcmd,longdata)

{

#ifdefOURS_GPIO_LED_DEBUG

printk("SIMPLE_GPIO_LED_ioctl[--kernel--]\n");//调试信息

#endif

switch(cmd)//io控制,cmd为输入的命令

{

caseLED_ON:

{GPCR3|=0x1;break;}//通过修改寄存器控制GPIO口电平

caseLED_OFF:

{GPSR3|=0x1;break;}

default:

{printk("lcdcontrol:

nocmdrun[--kernel--]\n");return(-EINVAL);//非法命令}

}

return0;

}

操作结构体:

structfile_operationsGPIO_LED_ctl_ops={

open:

SIMPLE_GPIO_LED_open,

read:

SIMPLE_GPIO_LED_read,

write:

SIMPLE_GPIO_LED_write,

ioctl:

SIMPLE_GPIO_LED_ioctl,

release:

SIMPLE_GPIO_LED_release,

};

建立操作映射,注册借口函数。

为应用层提供统一的接口。

驱动模块必须具备两个函数,就是初始化函数和卸载函数,其声明为如下两句:

module_init(pxa270_GPIO_LED_CTL_init);//加载模块时,系统调用pxa270_GPIO_LED_CTL_init函数初始化模块

module_exit(cleanup_GPIO_LED_ctl);//系统将调用该函数来卸载模块

这是linux驱动模块必备的。

初始化函数如下:

staticint__initpxa270_GPIO_LED_CTL_init(void)

{

intret=-ENODEV;//初始化失败将返回次错误信息

//调试信息

#ifdefOURS_GPIO_LED_DEBUG

printk("pxa270_GPIO_LED_CTL_init[--kernel--]\n");

#endif

//调用HW_GPIO_LED_CTL_init函数完成初始化

ret=HW_GPIO_LED_CTL_init();

if(ret)

returnret;

return0;

}

该函数通过调用HW_GPIO_LED_CTL_init函数实现初始化,该函数代码如下:

staticint__initHW_GPIO_LED_CTL_init(void)

{

intret=-ENODEV;

printk("hhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n\n");

showversion();//显示版本信息

//initGPIO

//初始化输出端口

GPDR3|=0x00000001;//设置输出端口模式

GPSR3|=0x00000001;//关闭led灯

//调试信息,显示寄存器信息

#ifdefOURS_GPIO_LED_DEBUG

printk("GPLR3=%x\n",GPLR3);

printk("GPDR3=%x\n",GPDR3);

#endif

//注册设备

ret=devfs_register_chrdev(SIMPLE_GPIO_LED_MAJOR//主设备号,"gpio_led_ctl",&GPIO_LED_ctl_ops//函数映射结构体);

if(ret<0)

{

printk("pxa270:

init_modulefailedwith%d\n[--kernel--]",ret);

returnret;

}

else

{

printk("pxa270gpio_led_driverregistersuccess!

!

!

[--kernel--]\n");

}

returnret;

}

模块卸载函数为cleanup_GPIO_LED_ctl,其代码实现如下:

staticvoid__exitcleanup_GPIO_LED_ctl(void)

{

#ifdefOURS_GPIO_LED_DEBUG

printk("cleanup_GPIO_LED_ctl[--kernel--]\n");

#endif

//注销主设备号,释放设备

devfs_unregister_chrdev(SIMPLE_GPIO_LED_MAJOR,"gpio_led_ctl");

}

 

测试函数:

通过调用ioctl函数实现对led灯的控制。

主函数实现如下:

intmain(void)

{

intfd;

intret;

char*i;

printf("\nstartgpio_led_drivertest\n\n");

fd=open(DEVICE_NAME,O_RDWR);

//系统通过函数映射调用SIMPLE_GPIO_LED_open函数打开设备

printf("fd=%d\n",fd);

if(fd==-1)

{

printf("opendevice%serror\n",DEVICE_NAME);

}

else

{

//通过调用SIMPLE_GPIO_LED_ioctl函数控制led灯

//主循环

while

(1)

{ioctl(fd,LED_OFF);

sleep

(1);//修改sleep时间即可改变led灯点亮的时间,如

sleep(7)即灭7秒

ioctl(fd,LED_ON);

sleep

(1);//sleep(5)亮5秒

}

//close

ret=close(fd);//

printf("ret=%d\n",ret);

printf("closegpio_led_drivertest\n");

}

return0;

}//endmain

通过该实验基本掌握了驱动模块的结构和一些函数的实现,如ioctl函数。

2、中断实验:

中断驱动模块的基本框架和GPIO的驱动模块基本相同,同样是通过module_init和module_exit来分别映射初始化和卸载模块。

具体实现如下:

module_init(pxa270_HELLO_CTL_init);

module_exit(cleanup_HELLO_ctl);

和GPIO驱动相同,加载模块时,系统调用pxa270_HELLO_CTL_init函数初始化模块;卸载模块时,调用cleanup_HELLO_ctl函数来卸载模块,并释放资源。

中断驱动的初始化与GPIO模块略有不同,除了要注册主设备好之外,还要注册中断向量和中断处理函数。

pxa270_HELLO_CTL_init通过调用HW_HELLO_CTL_init函数完成模块初始化。

pxa270_HELLO_CTL_init与GPIO初始化函数相同,HW_HELLO_CTL_init函数如下:

staticint__initHW_HELLO_CTL_init(void)

{

intret=-ENODEV;

//注册主设备号和函数映射

ret=devfs_register_chrdev(SIMPLE_INT_MAJOR,"int_ctl",&INT_ctl_ops);

showversion();

if(ret<0)

{

printk("pxa270init_modulefailedwith%d\n[--kernel--]",ret);

returnret;

}

else

{

printk("pxa270int_driverregistersuccess!

!

!

[--kernel--]\n");

}

//注册中断号和中断函数,定位中断源和irq处理函数

//SIMPLE_INT_IRQ宏定义为int中断的中断号,SIMPLE_INT_interrupt为中断处理函数,SA_INTERRUP表示处理该中断时,其他局部中断不可用

ret=request_irq(SIMPLE_INT_IRQ,&SIMPLE_INT_interrupt,SA_INTERRUPT,"int_ctl",NULL);

printk("\n...............\nret=%x\n...............\n",ret);

returnret;

}

由于产生中断后,系统会转到SIMPLE_INT_interrupt函数执行,所以模块其他函数如read,write,ioctl函数不会被调用

SIMPLE_INT_interrupt函数如下:

staticvoidSIMPLE_INT_interrupt(intnr,void*devid,structpt_regs*regs)

{

//每次中断计数加一

//通过修改该函数即可实现不同的功能,不过该函数最好不要使用复杂的函数,以免中断时间过长

SimpleINT_temp_count++;

printk("NowKeyinterrupt%doccur!

!

!

\n",SimpleINT_temp_count);

//可以将GPIO模块中的IOctl函数移植到该中断函数,便可以通过中断来控制LED的亮灭

}

模块卸载函数为cleanup_HELLO_ctl;

staticvoid__exitcleanup_HELLO_ctl(void)

{

#ifdefOURS_HELLO_DEBUG

printk("cleanup_INT_ctl[--kernel--]\n");

#endif

//注销主设备号

devfs_unregister_chrdev(SIMPLE_INT_MAJOR,"int_ctl");

//释放中断源

free_irq(SIMPLE_INT_IRQ,NULL);

}

3、数码管显示驱动实验

该驱动的初始化以及卸载函数和GPIO驱动模块基本相同,不再重复。

只有初始化模块是,初始化函数出了注册主设备号以外,还会调用gpio_init函数来初始化数码管

该函数如下:

voidgpio_init(void)

{

printk("GPDR2=%x\n",GPDR2);

GPDR2=GPDR2|(0x3<<26);//设置端口模式

printk("GPDR2=%x\n",GPDR2)

}

该模块通过write函数来写入数据,并控制数码管显示;write函数实现如下:

ssize_tSERIAL_LED_write(structfile*file,constchar*buf,size_tcount,loff_t*f_ops)

{

#ifdefOURS_SERIAL_LED_DEBUG

printk("SERIAL_LED_write[--kernel--]\n");

#endif

//输出数据到数码管

write_byte(*buf);

returncount;

}

可以看出,write函数通过同调用write_byte函数控制数码管,该函数如下:

voidwrite_byte(intdata)

{

inti;

for(i=0;i<8;i++)

{

write_bit(data<

}

}

该函数通过循环调用write_bit函数来串行输出每一位数据,一个字节8位,正好输出一个数字到寄存器;由于每次输出最高位,所以通过移位操作来循环输出8位二进制数。

Write_bit函数通过gpio串行输出数据到串并转换寄存器,从而控制数码管,write_bit函数实现如下:

voidwrite_bit(intdata)

{

GPCR2|=(0x1<<27);

if((data&0x80)==0x80)

{

GPSR2|=(0x1<<26);

}

else

{

GPCR2|=(0x1<<26);

}

GPSR2|=(0x1<<27);

}

具体控制流程不清楚。

测试文件:

intmain(void)

{

intfd;

intret;

inti,count;

//数码管显示数据。

十个数字的7段显示器的输入

intbuf[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

//0123456789

intdata[10];

printf("\nstartserial_leddrivertest\n\n");

//打开设备

fd=open(DEVICE_NAME,O_RDWR);

printf("fd=%d\n",fd);

if(fd==-1)

{

printf("opendevice%serror\n",DEVICE_NAME);

}

else

{

while

(1)

{

//循环显示数字

for(count=0;count<10;count++)

{

data[0]=buf[count];

ret=write(fd,data,1);

sleep

(1);

}

}

}

ret=close(fd);

printf("ret=%d\n",ret);

printf("closeserial_leddrivertest\n");

return0;

}//endmain

4、LED点阵驱动程序设计

LED点阵驱动的初始化函数框架和前边几个相同,同样是pxa270_LED_CTL_init函数通过调用HW_LED_CTL_init函数完成LED点阵的初始化。

不过,LED点阵驱动初始化还要获取模块地址和完成点阵的初始化。

代码如下:

ioremap_addr=ioremap(0x0800c000,0x0f);//

outw(0x00ff,ioremap_addr);//openledary,allledon

点亮整个点阵。

同样卸载模块时,也要清除数据,这在cleanup_LED_ctl函数进行,所以该函数要加上如下代码:

outw(0x0000,ioremap_addr);//清除数据

devfs_unregister_chrdev(SIMPLE_LED_MAJOR,"led_ary_ctl");//注销设备

对点阵的操作在SIMPLE_LED_write函数实现,代码如下:

ssize_tSIMPLE_LED_write(structfile*file,constchar*buf,size_tcount,loff_t*f_ops)

{

inttmp_buf;

#ifdefOURS_LED_DEBUG

printk("SIMPLE_LED_write[--kernel--]\n");

#endif

//-------------------------------------------

tmp_buf=buf[1];//行选,低电平有效

tmp_buf=tmp_buf<<8;//左移位,高字节部分为行选

tmp_buf=tmp_buf|buf[0];//低字节部分为列选

#ifdefOURS_LED_DEBUG

printk("tmp=%x\n",tmp_buf);

#endif

outw(tmp_buf,ioremap_addr);//写入到控制存储器

//-------------------------------------------

returncount;

}

由于点阵的控制线对应数据线的低16位,其中低8位为列选,高8位为行选。

停止使用设备后,应清除数据,由SIMPLE_LED_release完成:

ssize_tSIMPLE_LED_release(structinode*inode,structfile*file)

{

#ifdefOURS_LED_DEBUG

printk("SIMPLE_LED_release[--kernel--]\n");

#endif

outw(0x0000,ioremap_addr);//关闭点阵

MOD_DEC_USE_COUNT;

return0;

}

测试文件:

测试文件主循环如下,其他部分和其他测试文件相同.

c=1;

r=1;

for(i=1;i<=8;i++){

buf[0]=c;//列选,高电平有效

buf[1]=~r;//行选,低电平有效

for(j=1;j<=8;j++){

write(fd,buf,2);

printf("buf[0],buf[1]:

[%x,%x]\n",buf[0],buf[1]);

usleep(200000);//sleep0.2second

c=c<<1;//列信号左移,即扫描点逐点行扫描

buf[0]=c;//column

}

c=1;

r=r<<1;//行移位,下移一行

}

5.AD驱动实验

该模块需要ad模块的支持,所以初始化函数会相对比较复杂。

不过初始化函数的结构依旧没有改变,同样是pxa270_AD_CTL_init函数通过调用HW_AD_CTL_init函数完成AD模块的初始化。

staticint__initHW_AD_CTL_init(void)

{

intret=-ENODEV;

showversion();

ad_ucb=ucb1x00_get();//获取AD模块的地址

//注册主设备号

ret=devfs_register_chrdev(ADCTL_MAJOR,"adctl",&adctl_ops);

if(ret<0)

{

printk("adctlinit_modulefailedwith%d\n[--kernel--]",ret);

returnret;

}

else

{

printk("adctlint_driverregistersuccess!

!

!

[--kernel--]\n");

}

//注册AD模块,设定为字符模块

adctl_dev_handle=devfs_register(NULL,"ad_ctl",DEVFS_FL_DEFAULT,ADCTL_MAJOR,0,S_IFCHR,&adctl_ops,NULL);

returnret;

}

同理,卸载模块时就要同时注销主设备号和AD模块。

所以,卸载函数改为:

staticvoid__exitcleanup_AD_ctl(void)

{

devfs_unregister(adctl_dev_handle);//注销AD模块

devfs_unregister_chrdev(ADCTL_MAJOR,"ad_ctl");//注销主设备号

}

AD模块的控制由adctl_ioctl函数实现:

ssize_tadctl_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)

{

intval;

#ifdefOURS_HELLO_DEBUG

//printk("SIMPLE_HELLO_ioctl[--kernel--]\n");

#endif

ucb0x00_adc_enable(ad_ucb);//使能AD转换

//读取AD转换后的数据,其中cmd指定转换通道

val=ucb0x00_adc_read(ad_ucb,cmd,0);

ucb0x00_adc_disable(ad_ucb);//停止AD转换

returnUCB_ADC_DAT(val);//返回转换的数据

}

使用时调用ioctl函数便可以实现数据采集。

可以得到,测试文件的核心部分:

intval0,val1;

char*i;

ioctl(fd);//通过函数映射调用adctl_ioctl函数

/*

for(i=0;i<50;i++)

{

val=ioctl(fd,UCB_ADC_INP_AD0,0);

printf("val=%x\n",val);

usleep(200000);

}

*/

for(i=0;i<50;i++)

{

//通过函数映射调用adctl_ioctl函数读取通道1

val0=ioctl(fd,UCB_ADC_INP_AD1,0);

usleep(100);//等待操作完成

//通过函数映射调用adctl_ioctl函数读取通道0

val1=ioctl(fd,UCB_ADC_INP_AD0,0);

printf("val0=%d\tval1=%d\n",val0,val1);

usleep(500000);

}

测试函数其他部分与其他的测试文件相同

6.DA驱动

DA模块的初始化除了要注册主设备号以外,还要初始化设备地址和初始输出数据,所以其初始化部分与其他模块有一些变化,不过结构依然不变,其主要初始化函数HW_DA_CTL_init如下:

staticint__initHW_DA_CTL_init(void)

{

intret=-

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2