本文转载自:https://blog.csdn.net/lxllinux/article/details/80885331
一、关于PWM:
PWM(Pulse Width Modulation)——脉宽调制,它是利用微控制器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等许多领域。
![](https://i-blog.csdnimg.cn/blog_migrate/ea73398cea5e46ddc31e079d59fa8d27.png)
通过S3C2440底板原理图可知蜂鸣器接2440的GPB0/TOUT0.即我们的蜂鸣器是通过GPB0 IO口使用PWM信号驱动工作的,而且GPB0口是一个复用的IO口,要使用它得把他设置成TOUT0 PWM输出模式。
蜂鸣器可以发声,靠的不仅仅是蜂鸣器硬件的驱动,还有Linux下的PWM(脉冲宽度调制)这种变频技术,靠改变脉冲宽度来控制输出电压,通过改变周期来控制其输出频率。通过改变频率可以使蜂鸣器发出不同的声音。
二、修改设备树
-
beeper {
-
compatible = "pwm-beeper";
-
pwms = <&pwm 0 1000000 0>;
-
pinctrl-names = "default";
-
pinctrl -0 = <&pwm0_pin>;
-
};
四、修改配置文件:
[yangni@yangni linux-3.0.54]$make menuconfig
SystemType --->
[ * ] PWM device support
DeviceDrivers --->
Input device support --->
[* ] Miscellaneous devices --->
< * > PWM beeper support
配置完成以后就可以make了,然后将重新编译好的内核下载到开发板上,开发板启动的时候会听到“滴”的一声响。并且,在开发板会打印出如下相关的信息:
![](https://i-blog.csdnimg.cn/blog_migrate/2880c51cc7551e78e315d76e40ec978d.png)
五、测试程序:
首先得查找出事件编号。因为后来移植过按键驱动,所以按键驱动被分配为input0了,导致后来再运行打开不了,所以测试程序写的时候,open的时候要open对。
cat proc/bus/input/devices
![](https://i-blog.csdnimg.cn/blog_migrate/be2afb66becf0b8a5cf18a0691610f31.png)
-
/*********************************************************************************
-
* Copyright: (C) 2017 qicheng
-
* All rights reserved.
-
*
-
* Filename: beer_test.c
-
* Description: This file
-
*
-
* Version: 1.0.0(04/19/2017)
-
* Author: yangni <497049229@qq.com>
-
* ChangeLog: 1, Release initial version on "04/19/2017 11:44:58 AM"
-
*
-
********************************************************************************/
-
-
-
-
-
-
-
-
int main(int argc, char *argv[])
-
{
-
int fd, version, ret;
-
int i;
-
struct input_event event;
-
if ((fd = open( "/dev/event1", O_RDWR)) < 0) {
-
perror( "beep test");
-
return 1;
-
}
-
event.type = EV_SND;
-
event.code = SND_TONE;
-
if(! strcmp (argv[ 1], "1"))
-
{
-
for(i= 0;i<= 7;i++)
-
{
-
event.value = 2000; //打开蜂鸣器
-
ret = write(fd, &event, sizeof(struct input_event));
-
sleep( 0.5);
-
event.value = 0; //关闭蜂鸣器
-
ret = write(fd, &event, sizeof(struct input_event));
-
}
-
}
-
else if(! strcmp (argv[ 1], "0"))
-
{
-
event.value = 0;
-
ret = write(fd, &event, sizeof(struct input_event));
-
}
-
close(fd);
-
return 0;
-
}
如果为SND_BELL,不管input_event.value为多少,最终的value只能为1000或0,即不能改变蜂鸣器的频率。1000表示蜂鸣器打开,0表示蜂鸣器关闭。
如果为SND_TONE,则可以通过改变input_event.value的值来调整蜂鸣器的频率,从而发出各种不同的音调。
六、驱动程序分析:
该驱动程序位于:drivers/input/misc/pwm-beeper.c
[yangni@yangni linux-3.0.54]$ vim drivers/input/misc/pwm-beeper.c
-
/* Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
-
* PWM beeper driver
-
*
-
* This program is free software; you can redistribute it and/or modify it
-
* under the terms of the GNU General Public License as published by the
-
* Free Software Foundation; either version 2 of the License, or (at your
-
* option) any later version.
-
*
-
* You should have received a copy of the GNU General Public License along
-
* with this program; if not, write to the Free Software Foundation, Inc.,
-
* 675 Mass Ave, Cambridge, MA 02139, USA.
-
*
-
*/
-
-
-
-
-
-
-
struct pwm_beeper {
-
struct input_dev *input;
-
struct pwm_device *pwm;
-
unsigned long period;
-
};
-
-
//事件处理函数
-
static int pwm_beeper_event(struct input_dev *input,
-
unsigned int type, unsigned int code, int value)
-
{
-
int ret = 0;
-
struct pwm_beeper *beeper = input_get_drvdata(input);
-
unsigned long period;
-
if (type != EV_SND || value < 0)
-
return -EINVAL; //若input_event.type不是EV_SND或input_event.value小于0,则退出
-
switch (code) {
-