linux PWM蜂鸣器移植以及驱动程序分析【转】

本文详细介绍了如何在Linux下通过PWM驱动蜂鸣器,讲解了设备树、配置文件的修改,以及驱动程序的工作原理,展示了如何通过用户空间程序控制蜂鸣器的开闭和频率,从而产生不同声音。
摘要由CSDN通过智能技术生成

本文转载自:https://blog.csdn.net/lxllinux/article/details/80885331

一、关于PWM:
        PWM(Pulse Width Modulation)——脉宽调制,它是利用微控制器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等许多领域。

        通过S3C2440底板原理图可知蜂鸣器接2440的GPB0/TOUT0.即我们的蜂鸣器是通过GPB0 IO口使用PWM信号驱动工作的,而且GPB0口是一个复用的IO口,要使用它得把他设置成TOUT0 PWM输出模式。

       蜂鸣器可以发声,靠的不仅仅是蜂鸣器硬件的驱动,还有Linux下的PWM(脉冲宽度调制)这种变频技术,靠改变脉冲宽度来控制输出电压,通过改变周期来控制其输出频率。通过改变频率可以使蜂鸣器发出不同的声音。

二、修改设备树

  1. beeper {
  2. compatible = "pwm-beeper";
  3. pwms = <&pwm 0 1000000 0>;
  4. pinctrl-names = "default";
  5. pinctrl -0 = <&pwm0_pin>;
  6. };

四、修改配置文件:

[yangni@yangni linux-3.0.54]$make menuconfig
SystemType  --->
         [ * ] PWM device support
DeviceDrivers  --->
           Input device support  --->
                       [* ] Miscellaneous devices  --->
                                    < * > PWM beeper support
     配置完成以后就可以make了,然后将重新编译好的内核下载到开发板上,开发板启动的时候会听到“滴”的一声响。并且,在开发板会打印出如下相关的信息:
五、测试程序:
     首先得查找出事件编号。因为后来移植过按键驱动,所以按键驱动被分配为input0了,导致后来再运行打开不了,所以测试程序写的时候,open的时候要open对。
   cat proc/bus/input/devices
  1. /*********************************************************************************
  2. * Copyright: (C) 2017 qicheng
  3. * All rights reserved.
  4. *
  5. * Filename: beer_test.c
  6. * Description: This file
  7. *
  8. * Version: 1.0.0(04/19/2017)
  9. * Author: yangni <497049229@qq.com>
  10. * ChangeLog: 1, Release initial version on "04/19/2017 11:44:58 AM"
  11. *
  12. ********************************************************************************/
  13. #include<stdint.h>
  14. #include<string.h>
  15. #include<fcntl.h>
  16. #include<unistd.h>
  17. #include<stdio.h>
  18. #include<linux/input.h>
  19. #include<unistd.h>
  20. int main(int argc, char *argv[])
  21. {
  22. int fd, version, ret;
  23. int i;
  24. struct input_event event;
  25. if ((fd = open( "/dev/event1", O_RDWR)) < 0) {
  26. perror( "beep test");
  27. return 1;
  28. }
  29. event.type = EV_SND;
  30. event.code = SND_TONE;
  31. if(! strcmp (argv[ 1], "1"))
  32. {
  33. for(i= 0;i<= 7;i++)
  34. {
  35. event.value = 2000; //打开蜂鸣器
  36. ret = write(fd, &event, sizeof(struct input_event));
  37. sleep( 0.5);
  38. event.value = 0; //关闭蜂鸣器
  39. ret = write(fd, &event, sizeof(struct input_event));
  40. }
  41. }
  42. else if(! strcmp (argv[ 1], "0"))
  43. {
  44. event.value = 0;
  45. ret = write(fd, &event, sizeof(struct input_event));
  46. }
  47. close(fd);
  48. return 0;
  49. }
从应用程序中得到的input_event.code只能为SND_BELL或SND_TONE,否则退出。
如果为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
  1. /* Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
  2. * PWM beeper driver
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. *
  9. * You should have received a copy of the GNU General Public License along
  10. * with this program; if not, write to the Free Software Foundation, Inc.,
  11. * 675 Mass Ave, Cambridge, MA 02139, USA.
  12. *
  13. */
  14. #include <linux/input.h>
  15. #include <linux/module.h>
  16. #include <linux/kernel.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/pwm.h>
  19. #include <linux/slab.h>
  20. struct pwm_beeper {
  21. struct input_dev *input;
  22. struct pwm_device *pwm;
  23. unsigned long period;
  24. };
  25. #define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
  26. //事件处理函数
  27. static int pwm_beeper_event(struct input_dev *input,
  28. unsigned int type, unsigned int code, int value)
  29. {
  30. int ret = 0;
  31. struct pwm_beeper *beeper = input_get_drvdata(input);
  32. unsigned long period;
  33. if (type != EV_SND || value < 0)
  34. return -EINVAL; //若input_event.type不是EV_SND或input_event.value小于0,则退出
  35. switch (code) {
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式小庄老师

要是觉得不错,就给我点支持吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值