企业见习报告arm板蜂鸣器驱动开发DOC.docx
《企业见习报告arm板蜂鸣器驱动开发DOC.docx》由会员分享,可在线阅读,更多相关《企业见习报告arm板蜂鸣器驱动开发DOC.docx(27页珍藏版)》请在冰豆网上搜索。
企业见习报告arm板蜂鸣器驱动开发DOC
嵌入式系统开发技术
企业见习
专业:
计算机科学与技术
班级:
2011级计算机软件
学号:
姓名:
设计题目:
蜂鸣器驱动程序设计
2014年06月
目录
1.绪论1
1.1概要1
1.2设计内容1
2.开发环境的搭建2
2.1Redhat的安装2
2.2安装arm-linux-gcc交叉编译器4
2.3安装及编译linux-2.6.35.7-Tiny210-20120301内核6
3.字符设备驱动相关知识8
3.1模块机制8
3.2字符设备开发基本步骤9
3.3主设备号和次设备号10
3.4实现字符驱动程序11
4.蜂鸣器原理13
4.1蜂鸣器的种类和工作原理13
4.2开发板上蜂鸣器原理图分析13
5.总体设计14
5.1设计思路14
5.2设计步骤14
6.驱动及测试程序16
6.1buzzer驱动代码16
6.2buzzer驱动测试代码18
7.运行结果及截图20
8、Tiny210开发板调试22
综合设计总结与思考23
1.绪论
1.1概要
Linux是一套免费使用和自由传播的类Unix操作系统,它主要用于基于Intelx86系列CPU的计算机上。
Linux以它的高效性和灵活性著称。
它能够在PC计算机上实现全部的Unix特性,具有多任务、多用户的能力。
Linux是在GNU公共许可权限下免费获得的,是一个符合POSIX标准的操作系统。
Linux操作系统软件包不仅包括完整的Linux操作系统,而且还包括了文本编辑器、高级语言编译器等应用软件。
它还包括带有多个窗口管理器的X-Windows图形用户界面,如同我们使用WindowsNT一样,允许我们使用窗口、图标和菜单对系统进行操作。
而linux驱动是直接和硬件打交道的软件程序。
层次结构上,它处于操作系统和硬件之间。
系统调用是操作系统内核与应用程序之间的接口,设备驱动程序是操作系统内核与机器硬件之间的接口。
设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件折本进行操作。
设备驱动程序是内核的一部分,它主要完成这么几个功能:
对设备初始化和释放;传送数据到硬件和从硬件读取数据;检测和处理设备出现的错误。
一般来说,linux驱动可以分为三类,就是块设备驱动,字符设备驱动和网络设备驱动。
块设备的读写都有缓存来支持,并且块设备必须能够随机存取。
块设备驱动主要用于磁盘驱动器。
1.2设计内容
本次设计是简单的字符设备驱动设计,基于Tiny210的蜂鸣器的驱动设计。
2.开发环境的搭建
2.1Redhat的安装
使用VirtualBox创建一个虚拟机:
点击菜单栏File->New->Virtualmachine。
填写虚拟机名称,选择系统类型和版本,然后点击下一步。
配置虚拟机内存为1024M,然后点击下一步
创建虚拟硬盘,下一步。
配置完成后的虚拟机配置
2.2安装arm-linux-gcc交叉编译器
1、下载文件:
安装包:
arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz
2、开始安装,打开终端输入cd,进入home目录后,
输入命令:
tarxvzfarm-linux-gcc-4.5.1-v6-vfp-20120301.tgz如图:
2.解压完成后在终端中输入cd./opt/FriendlyARM/toolschain/4.5.1/bin/,然后pwd查看当前路径;
3.修改环境变量,把交叉编译器的路径加入到PATH:
利用tab键的补齐功能进入该路径。
输入pwd命令,查看当前路径的绝对路径/home/cf/ARM/opt/FriendlyARM/toolschain/4.5.1/bin如图:
然后输入如下命令:
vi~/.bash_profile
修改下列PATH
PATH=$PATH:
$HOME/bin:
/sbin:
~/opt/FriendlyARM/toolschain/4.5.1/bin
然后输入如下命令,更新环境变量
source~/.bash_profile
4、检查是否将路径加入到PATH:
接下来利用命令echo$PATH查看环境变量是否添加成功,若
环境变量中出现了刚才添加的路径就成功了。
5、测试是否安装成功
$arm-linux-gcc-v输入命令会显示arm-linux-gcc信息和版本.
2.3安装及编译linux-2.6.35.7-Tiny210-20120301内核
复制内核到root目录下
解压内核文件tarzxvflinux-2.6.35.7-Tiny210-20120301.tgz
使内核文件生效:
cpconfig_Tiny210_n35.config
使用make命令完成编译解压内核文件tarzxvflinux-2.6.35.7-20120301.tgz
使内核文件生效:
cpmini210-tvp5150_linux_defconfig.config并且使用make命令完成编译
编辑Makefile文件
3.字符设备驱动相关知识
3.1模块机制
Linux提供了机制被称为模块(Module)的机制
提供了对许多模块支持,包括但不限于,设备驱动
每个模块由目标代码组成(没有连接成一个完整可执行程序)
insmod将模块动态加载到正在运行内核
rmmod程序移除模块
Linux内核模块的程序结构
●module_init()---模块加载函数(必须)
通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成模块的相关初始化工作
●module_exit()---模块卸载函数(必须)
当通过rmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块装载函数相反的功能
●MODULE_LICENSE()---模块许可证声明(必须)
模块许可证(LICENSE)声明描述内核模块的许可权限
如果不声明LICENSE,模块被加载时,将收到内核被污染(kerneltainted)的警告
●module_param()---模块参数(可选)
模块参数是模块被加载的时候可以被传递给它的值,它本身对应模块内部的全局变量。
●EXPORT_SYMBOL()---模块导出符号(可选)
内核模块可以导出符号(symbol,对应于函数或变量)到内核
其他模块可以使用本模块中的变量或函数
●其他一些声明MODULE_XXXXX()---模块声明(可选)
模块加载函数
staticint__initinitialization_function(void)
{
/*初始化代码*/
}
module_init(initialization_function);
模块卸载函数
staticvoid__exitcleanup_function(void)
{
/*释放资源*/
}
module_exit(cleanup_function);
3.2字符设备开发基本步骤
●确定主设备号和次设备号
●实现字符驱动程序
实现file_operations结构体
实现初始化函数,注册字符设备
实现销毁函数,释放字符设备
●创建设备文件节点
3.3主设备号和次设备号
●主设备号是内核识别一个设备的标识。
整数(占12bits),范围从0到4095,通常使用1到255
●次设备号由内核使用,用于正确确定设备文件所指的设备。
整数(占20bits),范围从0到1048575,一般使用0到255
●设备编号的内部表达
dev_t类型(32位):
用来保存设备编号(包括主设备号(12位)和次设备号(20位))
从dev_t获得主设备号和次设备号:
MAJOR(dev_t);
MINOR(dev_t);
将主设备号和次设备号转换成dev_t类型:
MKDEV(intmajor,intminor);
●分配主设备号
手工分配主设备号:
找一个内核没有使用的主设备号来使用。
#include
intregister_chrdev_region(dev_tfirst,unsignedintcount,char*name);
●动态分配主设备号:
#include
intalloc_chrdev_resion(dev_t*dev,unsignedintfirstminor,unsignedintcount,char*name);
●释放设备号
voidunregister_chrdev_region(dev_tfirst,unsignedintcount);
3.4实现字符驱动程序
●cdev结构体
structcdev
{
structkobjectkobj;/*内嵌的kobject对象*/
structmodule*owner;/*所属模块*/
structfile_operations*ops;/*文件操作结构体*/
structlist_headlist;
dev_tdev;/*设备号*/
unsignedintcount;
};
●file_operations结构体
字符驱动和内核的接口:
在include/linux/fs.h定义
字符驱动只要实现一个file_operations结构体
并注册到内核中,内核就有了操作此设备的能力。
●file_operations的主要成员:
structmodule*owner:
指向模块自身
open:
打开设备
release:
关闭设备
read:
从设备上读数据
write:
向设备上写数据
ioctl:
I/O控制函数
llseek:
定位读写指针
mmap:
映射设备空间到进程的地址空间
●ioctl函数
为设备驱动程序执行“命令”提供了一个特有的入口点
用来设置或者读取设备的属性信息。
intioctl(structinode*inode,structfile*filp,
unsignedintcmd,unsignedlongarg);
●cmd参数的定义
不推荐用0x1,0x2,0x3之类的值
Linux对ioctl()的cmd参数有特殊的定义
构造命令编号的宏:
_IO(type,nr)用于构造无参数的命令编号;
_IOR(type,nr,datatype)用于构造从驱动程序中读取数据的命令编号;
_IOW(type,nr,datatype)用于写入数据的命令;
_IOWR(type,nr,datatype)用于双向传输。
type和number位字段通过参数传入,而size位字段通过对datatype参数取sizeof获得。
●Ioctl函数模板
intxxx_ioctl(structinode*inode,structfile*filp,unsignedintcmd,
unsignedlongarg)
{
...
switch(cmd)
{
caseXXX_CMD1:
...
break;
caseXXX_CMD2:
...
break;
default:
///*不能支持的命令*/
return-ENOTTY;
}
return0;
}
4.蜂鸣器原理
4.1蜂鸣器的种类和工作原理
蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。
有的压电式蜂鸣器外壳上还装有发光二极管。
多谐振荡器由晶体管或集成电路构成。
当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。
电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。
接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。
振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
有源蜂鸣器和无源蜂鸣器的区别:
这个“源”字是不是指电源,而是指震荡源,即有源蜂鸣器内有振荡源而无源蜂鸣器内部没有振荡源。
有振荡源的通电就可以发声,没有振荡源的需要脉冲信号驱动才能发声。
4.2开发板上蜂鸣器原理图分析
由原理图可以得知,蜂鸣器是通过GPD0IO口使用PWM信号驱动工作的,而GPD0口是一个复用的IO口,要使用它得先把他设置成TOUT0PWM输出模式。
5.总体设计
5.1设计思路
Linux设备驱动属于内核的一部分,Linux内核的一个模块可以以两种方式被编译和加载:
(1)直接编译进Linux内核,随同Linux启动时加载;
(2)编译成一个可加载和删除的模块,使用insmod加载(modprobe和insmod命令类似,但依赖于相关的配置文件),rmmod删除。
这种方式控制了内核的大小,而模块一旦被插入内核,它就和内核其他部分一样。
这次的蜂鸣器驱动就采用动态模块加载的方式
5.2设计步骤
Ø编写简单的字符设别驱动程序框架
Ø编写控制蜂鸣器控制开关函数
Ø编译模块,生成beep.ko
Ø编写用户层测试程序
Ø编译用户层测试程序,生成可执行程序test
Ø将生成的beep.ko模块和应用层测试程序test下载到目标板
Ø用insmod装载模块
Ø创建设备节点
mknod/dev/beepc2500
Ø运行用户层测试程序test
#./test
如果你的test的属性不是可执行的,可以用chmod777test将其设置成可执行
程序。
6.驱动及测试程序
6.1蜂鸣器驱动代码
#include
#include//includefile_operations
#include
#include
#include
#include
#include//includeioread32,iowrite32;
dev_tgeek_num;
structcdevgeek_cdev;//字符设备结构体
//structfile_operationsgeek_ops;//
unsignedint*address;//addressforGPD_CON
voidbeep_start(void){
unsignedintdata;
address=ioremap(0xE02000A0,8);
data=ioread32(address+1);
data|=0x1<<0;//bit0set1;
iowrite32(data,address+1);
}
voidbeep_stop(void){
unsignedintdata;
address=ioremap(0xE02000A0,8);
data=ioread32(address+1);
data&=~0x1<<0;//bit0set0;
iowrite32(data,address+1);
}
staticintgeek_open(structinode*node,structfile*fp){
unsignedintdata;//initate
address=ioremap(0xE02000A0,8);
data=ioread32(address);
data&=~0x1<<3;//bit3set0;
data&=~0x1<<2;//bit2set0;
data&=~0x1<<1;//bit1set0;
data|=0x1<<0;//bit0set1;
iowrite32(data,address);
printk("\tgeek_open\n");
return0;
}
staticintgeek_release(structinode*node,structfile*fp){
printk("\tgeek_release\n");
return0;
}
staticintgeek_read(structfile*fp,char__user*buf,size_tcount,loff_t*ppos){
printk("\tgeek_read\n");
return0;
}
staticintgeek_write(structfile*fp,constchar__user*buf,size_tcount,loff_t*ppos){
printk("\tgeek_write\n");
return0;
}
staticintgeek_ioctl(structinode*node,structfile*fp,unsignedintcmd,unsignedlongll){
printk("\tgeek_ioctl\n");
switch(cmd){
case0:
{beep_stop();printk("beep_stop");}
break;
case1:
{beep_start();printk("beep_start");}
break;
default:
printk("commandnotfound!
\n");
break;
}
return0;
}
structfile_operationsgeek_ops=//文件描述符,
{
.owner=THIS_MODULE,//
.open=geek_open,
.read=geek_read,
.write=geek_write,
.ioctl=geek_ioctl,
.release=geek_release,
};
staticint__initbeep_init(void)//初始化
{
intmajor;//主设备号
alloc_chrdev_region(&geek_num,0,1,"geek_beep");//设备号,次设备号,分支数,设备名称
major=MAJOR(geek_num);
printk("major:
%d",major);
cdev_init(&geek_cdev,&geek_ops);
geek_cdev.ops=&geek_ops;//指向file_operations
geek_cdev.owner=THIS_MODULE;
cdev_add(&geek_cdev,geek_num,1);//注册设备
return0;
}
staticvoid__exitbeep_exit(void)
{
unregister_chrdev_region(geek_num,1);//
cdev_del(&geek_cdev);//删除
}
module_init(beep_init);//加载
module_exit(beep_exit);//卸载
6.2蜂鸣器驱动测试代码
#include
#include
intmain(){
unsignedn=1;
intfp;
fp=open("/dev/beep",O_RDWR);
if(fp<0){
printf("CantopentheDev!
");
return-1;
}
read(fp,NULL,0);
write(fp,NULL,0);
printf("inputtimeyouwanttobeep:
");
scanf("%d",&n);
while(n--){
ioctl(fp,1,0);
sleep
(1);
ioctl(fp,0,0);
sleep
(1);
}
close(fp);
return0;
}
7.运行结果及截图
传输beep.ko,test测试程序,然后使用ls命令查看文件。
使用insmodbeep.ko加载beep驱动,mknod/dev/beepc2500创建设备结点。
最后使用./test命令运行测试程序
8.Tiny210开发板调试
(1)连接开发板电源。
(2)用串口将PC和Tiny210开发板相连。
(3)打开secureCRT软件,点击快速连接,配置端口
协议:
Serial
端口:
com6(看自己的端口号)
波特率:
115200
数据位:
8
奇偶校验:
none
停止位:
1
勾掉RTS/CTS选项
(4)点击连接
(5)打开开发板电源
(6)secureCRT软件会出现一些选项,选择b,rootsystem
(7)输入指令rz,将beep.ko加载到根文件系统里,再输入指令,将buzzer测试程序加载到根文件系统。
(8)在secureCRT里输入insmodbeep.ko,将驱动程序加载到内核模块中。
(9)在secureCRT里输入chmod777test,改变可执行程序的权限。
(10)在secureCRT里输入./test。
综合设计总结与思考
为期一周的企业见习即将结束,在大三快要结束时学校给我们安排了这次企业见习非常有用。
一方面是对我们这学期所开设的《嵌入式linux应用开发》的一次巩固,另一方面也让我们深入了解了嵌入式linux开发,让我们有机会动手亲自体验linux开发,为以后的实际工作奠定了良好的基础。
同时也让我们知道了,linux开发并不是一件简单的事,并不是一门单纯的学科,需要综合领悟并贯通知识的能力,而且想精通linux开发并不是一朝一夕的事,需要极大的耐心与不懈的努力。
此次企业见习学校给我们安排了南京易嵌教育公司的赵老师,我校与南京易嵌教育有着非常密切而融洽的合作,在去年这个时候学校同样请来了赵老师给我们指导企业见习。
做的项目是用C语言开发一个电话簿。
赵老师非常认真的为我们授课,答疑解惑。
并在设计中给了我们极大的指导性作用。
那次企业见习让我们对C语言有个更加深刻的认识,也了解了C语言的使用的灵活性与广泛性,为这次企业见习做了一个铺垫。
此次设计的题目是蜂鸣器驱动,蜂鸣器我们并不陌生,在单片机这门课程中我们已经了解了蜂鸣器的工