蜂鸣器驱动程序设计.docx

上传人:b****2 文档编号:1903877 上传时间:2023-05-02 格式:DOCX 页数:22 大小:527.56KB
下载 相关 举报
蜂鸣器驱动程序设计.docx_第1页
第1页 / 共22页
蜂鸣器驱动程序设计.docx_第2页
第2页 / 共22页
蜂鸣器驱动程序设计.docx_第3页
第3页 / 共22页
蜂鸣器驱动程序设计.docx_第4页
第4页 / 共22页
蜂鸣器驱动程序设计.docx_第5页
第5页 / 共22页
蜂鸣器驱动程序设计.docx_第6页
第6页 / 共22页
蜂鸣器驱动程序设计.docx_第7页
第7页 / 共22页
蜂鸣器驱动程序设计.docx_第8页
第8页 / 共22页
蜂鸣器驱动程序设计.docx_第9页
第9页 / 共22页
蜂鸣器驱动程序设计.docx_第10页
第10页 / 共22页
蜂鸣器驱动程序设计.docx_第11页
第11页 / 共22页
蜂鸣器驱动程序设计.docx_第12页
第12页 / 共22页
蜂鸣器驱动程序设计.docx_第13页
第13页 / 共22页
蜂鸣器驱动程序设计.docx_第14页
第14页 / 共22页
蜂鸣器驱动程序设计.docx_第15页
第15页 / 共22页
蜂鸣器驱动程序设计.docx_第16页
第16页 / 共22页
蜂鸣器驱动程序设计.docx_第17页
第17页 / 共22页
蜂鸣器驱动程序设计.docx_第18页
第18页 / 共22页
蜂鸣器驱动程序设计.docx_第19页
第19页 / 共22页
蜂鸣器驱动程序设计.docx_第20页
第20页 / 共22页
亲,该文档总共22页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

蜂鸣器驱动程序设计.docx

《蜂鸣器驱动程序设计.docx》由会员分享,可在线阅读,更多相关《蜂鸣器驱动程序设计.docx(22页珍藏版)》请在冰点文库上搜索。

蜂鸣器驱动程序设计.docx

蜂鸣器驱动程序设计

 

蚌埠学院

嵌入式系统开发技术

课程设计

 

专业:

电子信息科学与技术(嵌入式)

班级:

电子信息2班

学号:

00000000000

姓名:

设计题目:

蜂鸣器驱动程序设计

 

2014年9月

1.绪论

1.1概要

linux驱动在本质上就是一种软件程序,上层软件可以在不用了解硬件特性的情况下,通过驱动提供的接口,和计算机硬件进行通信。

系统调用是内核和应用程序之间的接口,而驱动程序是内核和硬件之间的接口,也就是内核和硬件之间的桥梁。

它为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。

linux驱动程序是内核的一部分,管理着系统中的设备控制器和相应的设备。

它主要完成这么几个功能:

对设备初始化和释放;传送数据到硬件和从硬件读取数据;检测和处理设备出现的错误。

一般来说,一个驱动可以管理一种类型的设备。

例如不同的U盘都属于massstorage设备,我们不需要为每一个U盘编写驱动,而只需要一个驱动就可以管理所有这些massstorage设备。

为方便我们加入各种驱动来支持不同的硬件,内核抽象出了很多层次结构,这些层次结构是linux设备驱动的上层。

它们抽象出各种的驱动接口,驱动只需要填写相应的回调函数,就能很容易把新的驱动添加到内核。

一般来说,linux驱动可以分为三类,就是块设备驱动,字符设备驱动和网络设备驱动。

块设备的读写都有缓存来支持,并且块设备必须能够随机存取。

块设备驱动主要用于磁盘驱动器。

而字符设备的I/O操作没有通过缓存。

字符设备操作以字节为基础,但不是说一次只能执行一个字节操作。

例如对于字符设备我们可以通过mmap一次进行大量数据交换。

字符设备实现比较简单和灵活。

1.2设计内容

本次设计是简单的字符设备驱动设计,基于mini2440的蜂鸣器的驱动设计。

2.开发环境的搭建

2.1Redhat的安装

创建一个虚拟机:

点击菜单栏File->New->Virtualmachine。

点击下一步。

选择Typical选项。

选择Linux下的RedHatLinux

填写虚拟机的命名和存储地址。

选择磁盘大小

2.2安装arm-linux-gcc交叉编译器

将arm-linux-gcc-4.5.1.tgz复制到虚拟机的root目录下

解压文件:

tarzxvfarm-linux-gcc-4.5.1.tgz

在bash_profile里添加路径:

gedit~/.bash_profiel

路径/root/usr/local/arm/4.5.1/bin

source~/.bash_profile使更改生效

2.3安装及编译linux-2.6.29-mini2440-20090708内核

复制内核到root目录下

解压内核文件tarzxvflinux-2.6.29-mini2440-20090708.tgz

使内核文件生效:

cpconfig_mini2440_n35.config

使用make命令完成编译

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;

}

3.5字符设备驱动结构

 

4.蜂鸣器原理

4.1蜂鸣器的种类和工作原理

蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。

  压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。

有的压电式蜂鸣器外壳上还装有发光二极管。

多谐振荡器由晶体管或集成电路构成。

当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。

  电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。

接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。

振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

  有源蜂鸣器和无源蜂鸣器的区别:

这个“源”字是不是指电源,而是指震荡源,即有源蜂鸣器内有振荡源而无源蜂鸣器内部没有振荡源。

有振荡源的通电就可以发声,没有振荡源的需要脉冲信号驱动才能发声。

4.2开发板上蜂鸣器原理图分析

由原理图可以得知,蜂鸣器是通过GPB0IO口使用PWM信号驱动工作的,而GPB0口是一个复用的IO口,要使用它得先把他设置成TOUT0PWM输出模式。

4.3GPB0参数

 

 

5.总体设计

5.1设计思路

Linux设备驱动属于内核的一部分,Linux内核的一个模块可以以两种方式被编译和加载:

(1)直接编译进Linux内核,随同Linux启动时加载;

(2)编译成一个可加载和删除的模块,使用insmod加载(modprobe和insmod命令类似,但依赖于相关的配置文件),rmmod删除。

这种方式控制了内核的大小,而模块一旦被插入内核,它就和内核其他部分一样。

这次的蜂鸣器驱动就采用动态模块加载的方式

5.2设计步骤

Ø编写简单的字符设别驱动程序框架

Ø编写控制蜂鸣器控制开关函数

Ø编译模块,生成.ko

Ø编写用户层测试程序

Ø编译用户层测试程序,生成可执行程序beep_test

Ø将生成的.ko模块和应用层测试程序beep_test下载到目标板

Ø用insmod装载模块

Ø创建设备节点

mknod/dev/beepc2530

Ø运行用户层测试程序beep_test

#./beep_test

如果你的beep_test的属性不是可执行的,可以用chmod777beep_test将其设置成可执行

程序。

6.驱动及测试程序

6.1beep.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#defineBEEP_MAJOR201

#defineBEEP_START_CMD0x0

#defineBEEP_STOP_CMD0x1

staticintbeep_major=BEEP_MAJOR;

staticstructcdevBeepDevs;

staticintbeep_open(structinode*inode,structfile*filp)

{

return0;

}

staticintbeep_relesae(structinode*inode,structfile*filp)

{

return0;

}

staticvoidbeep_stop(void)

{

s3c2410_gpio_cfgpin(S3C2410_GPB(0),S3C2410_GPIO_OUTPUT);

s3c2410_gpio_setpin(S3C2410_GPB(0),0);

printk("stop\n");

}

staticvoidbeep_start(void)

{

s3c2410_gpio_cfgpin(S3C2410_GPB(0),S3C2410_GPIO_OUTPUT);

s3c2410_gpio_setpin(S3C2410_GPB(0),1);

printk("start\n");

}

staticintbeep_ioctl(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg)

{

switch(cmd)

{

caseBEEP_START_CMD:

printk("beep_strat\n");

beep_start();

break;

caseBEEP_STOP_CMD:

printk("beep_stop\n");

beep_stop();

break;

default:

printk("default\n");

break;

}

return0;

}

staticstructfile_operationsbeep_remap_ops={

.owner=THIS_MODULE,

.open=beep_open,

.release=beep_relesae,

.ioctl=beep_ioctl,

};

staticvoidbeep_setup_cdev(structcdev*dev,intminor,structfile_operations*fops)

{

interr,devno=MKDEV(beep_major,minor);

cdev_init(dev,fops);

dev->owner=THIS_MODULE;

dev->ops=fops;

err=cdev_add(dev,devno,1);

if(err)

{

printk("error%daddingbeep%d\n",err,minor);

}

}

staticint__initbeep_init(void)

{

intresult;

dev_tdev=MKDEV(beep_major,0);

if(beep_major)

{

result=register_chrdev_region(dev,1,"beep");

}

else

{

result=alloc_chrdev_region(&dev,0,1,"beep");

beep_major=MAJOR(dev);

}

if(result<0)

{

printk("beep:

unabletogetmajor%d\n",beep_major);

returnresult;

}

if(beep_major==0)

{

beep_major=result;

}

beep_setup_cdev(&BeepDevs,0,&beep_remap_ops);

printk("beepdevicesinstalled,withmajor%d",beep_major);

return0;

}

staticvoid__exitbeep_exit()

{

cdev_del(&BeepDevs);

unregister_chrdev_region(MKDEV(beep_major,0),1);

printk("beepdeviceuninstalled\n");

}

MODULE_AUTHOR("xdq");

MODULE_LICENSE("GPL");

module_init(beep_init);

module_exit(beep_exit);

6.2beep_tset.c

#include

#include

#include

#include

#include

intmain()

{

intdev_fd;

charc;

dev_fd=open("/dev/beep",O_WRONLY|O_NONBLOCK);

if(dev_fd==-1)

{

printf("connotflie\n");

exit(0);

}

ioctl(dev_fd,0x0,0);

getchar();

getchar();

ioctl(dev_fd,0x1,0);

getchar();

getchar();

close(dev_fd);

return0;

}

7.运行结果及截图

传输beep.ko,ls命令查看文件。

传输beep_test可执行文件。

使用./beep_test命令运行测试程序

beep_stat,蜂鸣器响了,按下键盘一键,beep_stop,蜂鸣器停止

综合设计总结与思考

这是一次在易嵌的培训实习,我选择了做嵌入式驱动设计。

虽然自己的基础有点薄弱,但我相信努力认真就会有成功。

做嵌入式驱动设计需要学习的知识比较的多。

首先需要安装一个编译环境,我在电脑上安装了linux系统,进行之后的代码编译。

起初,经过老师的一些讲解,首先熟悉做该项目需要知道和掌握的知识,深入起来觉得还是蛮难的。

因为自己的编程有点薄弱,所以在一开始的操作中,会有一点费时间,经过老师和同学们的帮助下,我也逐渐熟练起来了。

做驱动需要掌握几个内核函数和几个模块函数,把这几个联系起来一起运用到所编的代码中,就实现了。

在这次实习中,发现学校里学习的书面知识是很重要的基础知识,需要掌握、巩固、强化,将所学知识融汇到实践操作中,才是自己真正的突破。

实习中,学到了很多,提高了自己只是掌握,技能运用,实践操作,各方各面都获益不浅。

教师评阅

考勤情况

设计态度

设计完成情况

实验报告

成绩:

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

当前位置:首页 > 人文社科

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

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