在SMDK210.C中添加如下beeper_device 结构体

static struct platform_device beeper_device = {
.name = "pwm_buzzer",
.id         =  1,
.dev = {
.parent
= &s3c_device_timer[1].dev, //PWM1是定时器1
.platform_data
= 0,
},
};

然后在smdkv210_devices中添加该结构体

static struct platform_device *smdkv210_devices[] __initdata = {

&s3c_device_fb,
&s3c_device_adc,
&s3c_device_cfcon,
&s3c_device_hsmmc0,
&s3c_device_hsmmc1,
&s3c_device_hsmmc2,
&s3c_device_hsmmc3,
&s3c_device_i2c0,
&s3c_device_i2c1,
&s3c_device_i2c2,

&s3c_device_timer[1], //add
&beeper_device, //add

}

一、硬件分析
对蜂鸣器的操作,主要是通过S5PV210的PWM来实现的,因为在OK210上,连接的是一个无源蜂鸣器,必须通过外部的驱动信号,才能控制其的“鸣叫”。
首先从OK210的底板原理图中可知,OK210开发板上的蜂鸣器连接通过一个三极管组成的放大电路连接到了核心板的XpwmTOUT[1]引脚上,如下图所示:

而XpwmTOUT[1]引脚由S5PV210用户手册,可知,该引脚位于GPD0[1]引脚上,默认为GPI,即当作通用输入端口使用,如下图所示:

 

但的第一功能名为TOUT_0,继续查阅,可知,该功能可作为PWM输出使用,如下所示,

 

所以,我们要对蜂鸣器进行操作,就是通过对XpwmTOUT[1]引脚的设置,即将其设置为TOUT_0功能,通过配置PWM的波形来实现蜂鸣器的鸣叫。
二、软件基础
如上所述,无源蜂鸣器没有自带震荡电路,必须外部提供2-5Khz左右的方波,才能驱动其发声,而要想产生方波,就会用到S5PV210的PWM模块。
S5PV210共有5个32bit的PWM定时器,其中定时器0、1、2、3有PWM功能,定时器4没有输出引脚。这些定时器都可产生中断。每个定时器可选择输入时钟为PCLK或SCLK_PWM。对PWM的操作,主要通过几个寄存器来完成,操作步骤如下:
1、设置TCFG0寄存器:配置定时器的一级分频值
2、设置TCFG1寄存器:配置定时器的二级分频值
3、设置TCNTBn寄存器:递减计数器缓冲寄存器
4、设置TCMPBn寄存器:比较缓冲寄存器
5、设置TCON寄存器:
(1)手动更新on(执行后,CPU会把TCNTBn的值加载到递减计数器中)
(2)手动更新off、自动重载、启动定时器
不过在Linux内核中,三星公司和飞凌公司已经为我们配置好了对这些PWM模块的使用,具体参见源码目录下 arch/arm/plat-s3c/的pwm.c文件,在驱动编程中,主要使用pwm_config()、pwm_enable()、pwm_disable(pwm4buzzer)这三个函数。另外,也可参见另一篇博文【S5PV210
PWM】。

驱动编程
有图有真相,按照如下运行后,即可听到“鸣叫”。

1
驱动程序

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/platform_device.h>
  5. #include <linux/fb.h>
  6. #include <linux/backlight.h>
  7. #include <linux/err.h>
  8. #include <linux/pwm.h>
  9. #include <linux/slab.h>
  10. #include <linux/miscdevice.h>
  11. #include <linux/delay.h>
  12. #include <mach/gpio.h>
  13. #include <mach/regs-gpio.h>
  14. #include <plat/gpio-cfg.h>
  15. #define DEVICE_NAME                                "pwm_buzzer"
  16. #define PWM_IOCTL_SET_FREQ                1
  17. #define PWM_IOCTL_STOP                        0
  18. #define NS_IN_1HZ                                (1000000000UL)
  19. #define BUZZER_PWM_ID                        0
  20. #define BUZZER_PMW_GPIO                        S5PV210_GPD0(0)
  21. static struct pwm_device *pwm4buzzer;
  22. static struct semaphore lock;
  23. static void pwm_set_freq(unsigned long freq) {
  24. int period_ns = NS_IN_1HZ / freq;
  25. pwm_config(pwm4buzzer, period_ns / 2, period_ns);
  26. pwm_enable(pwm4buzzer);
  27. }
  28. static void pwm_stop(void) {
  29. pwm_config(pwm4buzzer, 0, NS_IN_1HZ / 100);
  30. pwm_disable(pwm4buzzer);
  31. }
  32. static int my_pwm_open(struct inode *inode, struct file *file) {
  33. if (!down_trylock(&lock))
  34. return 0;
  35. else
  36. return -EBUSY;
  37. }
  38. static int my_pwm_close(struct inode *inode, struct file *file) {
  39. up(&lock);
  40. return 0;
  41. }
  42. static long my_pwm_ioctl(struct file *filep, unsigned int cmd,unsigned long arg)
  43. {
  44. switch (cmd) {
  45. case PWM_IOCTL_SET_FREQ:
  46. if (arg == 0)
  47. return -EINVAL;
  48. pwm_set_freq(arg);
  49. break;
  50. case PWM_IOCTL_STOP:
  51. default:
  52. pwm_stop();
  53. break;
  54. }
  55. return 0;
  56. }
  57. static struct file_operations my_pwm_ops = {
  58. .owner                        = THIS_MODULE,
  59. .open                        = my_pwm_open,
  60. .release                = my_pwm_close,
  61. .unlocked_ioctl        = my_pwm_ioctl,
  62. };
  63. static struct miscdevice my_misc_dev = {
  64. .minor = MISC_DYNAMIC_MINOR,
  65. .name = DEVICE_NAME,
  66. .fops = &my_pwm_ops,
  67. };
  68. static int __init my_pwm_dev_init(void) {
  69. int ret;
  70. printk(DEVICE_NAME " my_pwm_dev_init\n");
  71. ret = gpio_request(BUZZER_PMW_GPIO, DEVICE_NAME);
  72. if (ret) {
  73. printk("request GPIO %d for pwm failed\n", BUZZER_PMW_GPIO);
  74. return ret;
  75. }
  76. gpio_set_value(BUZZER_PMW_GPIO, 0);
  77. s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_OUTPUT);
  78. pwm4buzzer = pwm_request(BUZZER_PWM_ID, DEVICE_NAME);
  79. if (IS_ERR(pwm4buzzer)) {
  80. printk("request pwm %d for %s failed\n", BUZZER_PWM_ID, DEVICE_NAME);
  81. return -ENODEV;
  82. }
  83. pwm_stop();
  84. s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_SFN(2));
  85. gpio_free(BUZZER_PMW_GPIO);
  86. init_MUTEX(&lock);
  87. ret = misc_register(&my_misc_dev);
  88. return ret;
  89. }
  90. static void __exit my_pwm_dev_exit(void) {
  91. printk(DEVICE_NAME " my_pwm_dev_exit\n");
  92. pwm_stop();
  93. misc_deregister(&my_misc_dev);
  94. }
  95. module_init(my_pwm_dev_init);
  96. module_exit(my_pwm_dev_exit);
  97. MODULE_LICENSE("GPL");
  98. MODULE_AUTHOR("gjianw217@163.com");
  99. MODULE_DESCRIPTION("PWM Driver");

复制代码

2 应用程序

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <sys/ioctl.h>
  7. #include <fcntl.h>
  8. #define PWM_IOCTL_SET_FREQ 1
  9. #define PWM_IOCTL_STOP 0
  10. int main(int argc ,char* argv[])
  11. {
  12. int m_fd=0;//
  13. m_fd = open("/dev/pwm", O_RDONLY);
  14. int freq=1000;
  15. if(argc>1)
  16. freq=atoi(argv[1]);
  17. printf("%d \t\t",freq);
  18. ioctl(m_fd, PWM_IOCTL_STOP);
  19. ioctl(m_fd, PWM_IOCTL_SET_FREQ,freq);
  20. getchar();
  21. ioctl(m_fd, PWM_IOCTL_STOP);
  22. close(m_fd);
  23. return 0;
  24. }

复制代码

3 Makefile文件

  1. #pwm Makefile
  2. ARCH=arm
  3. CROSS_COMPILE=/home/ok210/arm-2009q3/bin/arm-none-linux-gnueabi-
  4. APP_COMPILE=/home/ok210/arm-2009q3/bin/arm-none-linux-gnueabi-
  5. #obj-m := app-drv.o
  6. obj-m := pwm-drv.o
  7. #KDIR := /path/to/kernel/linux/
  8. KDIR := /home/ok210/android-kernel-samsung-dev/
  9. PWD := $(shell pwd)
  10. default:
  11. make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
  12. app:pwm-app.c
  13. $(APP_COMPILE)gcc -o app pwm-app.c
  14. clean:
  15. $(MAKE) -C $(KDIR) M=$(PWD) clean

复制代码

最新文章

  1. 如何在web中实现类似excel的表格控件
  2. plsql查找不到带中文的纪录
  3. Tomcat安装后,远程IP无法访问的问题。
  4. maven 搜索不到想从本地仓库依赖的jar包--重建本地maven仓库索引
  5. 上海SAP代理商 服装行业ERP系统 达策SAP金牌代理商
  6. 网易音乐API
  7. memory model
  8. 【HDFS API编程】jUnit封装-改写创建文件夹
  9. [Swift]Alamofire:设置网络请求超时时间【timeout】的两种方式
  10. LeetCode算法扫题系列83
  11. MC9SD64单片机快速入门 I/O寄存器
  12. Pandas聚合
  13. Java NIO -- 缓冲区(Buffer)的数据存取
  14. Nginx 学习笔记(四)nginx-module-vts模块
  15. vue-生存周期
  16. vue组件--TagsInput
  17. WebGL学习笔记五
  18. 利用VMware在虚拟机上安装Zookeeper集群
  19. 处理函数和数组声明[条款17]---《C++必知必会》
  20. hdu 6040 Hints of sd0061(stl: nth_element(arr,arr+k,arr+n))

热门文章

  1. IntelliJ IDEA SpringBoot 使用第三方Tomcat以及部署
  2. [PAT] 1140 Look-and-say Sequence(20 分)
  3. hdu 4632(区间dp)
  4. python资源合集
  5. 五种WordPress防止垃圾评论方法-过滤垃圾评论提高WP运行效率
  6. git------删除Repository
  7. ELK系列--justniffer0.5.12安装报错解决方法
  8. vue-music 关于基础组件 (Tab组件)
  9. 第K短路模板【POJ2449 / 洛谷2483 / BZOJ1975 / HDU6181】
  10. Codeforces 714B. Filya and Homework