/**************************************************************************** * OK335xS pwm buzzer Linux driver hacking * 声明: * 本文仅仅是为了知道如何使用pwm来控制buzzer,已达到控制不同声音的频率。 * * 2015-10-7 雨 深圳 南山平山村 曾剑锋 ***************************************************************************/ #include <linux/init.h> #include <linux/export.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/errno.h> #include <linux/miscdevice.h> #include <linux/types.h> #include <linux/io.h> #include <linux/pwm/pwm.h> #include <linux/fs.h> #define DEBUG #if defined(DEBUG) #define DPRINTK(fmt,arg...) printk(fmt,##arg); #else #define DPRINTK(fmt,arg...) #endif #define BUZZER_FREQENCY 1 #define DEV_NAME "buzzer" /*pwm for this buzzer*/ struct pwm_device *pwm = NULL; static int buzzer_open(struct inode *inode, struct file *filp) { if(pwm != NULL) return -EBUSY; /** * 申请一个pwm设备 */ pwm = pwm_request("ecap.1", -1, "buzzer"); if ( pwm == NULL ) { printk("buzzer open error.\n"); } printk("buzzer open\n"); return 0; } static int buzzer_release(struct inode *inode, struct file *filp) { /** * 关闭、注销一个pwm设备 */ pwm_stop(pwm); pwm_release(pwm); pwm = NULL; printk("buzzer release\n"); return 0; } static long buzzer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { if(pwm == NULL) return -EINVAL; if(arg > 20000 || arg < 0) return -EINVAL; switch (cmd) { case BUZZER_FREQENCY: // 设置频率 if(arg==0) pwm_stop(pwm); else { pwm_set_period_ns(pwm, 1000000000/arg); pwm_set_duty_ns(pwm, 25000); pwm_start(pwm); } break; default: break; } return 0; } static struct file_operations buzzer_fops = { .owner = THIS_MODULE, .unlocked_ioctl = buzzer_ioctl, .open = buzzer_open, .release = buzzer_release, }; static struct miscdevice buzzer_miscdev = { .minor = MISC_DYNAMIC_MINOR, .name = DEV_NAME, .fops = &buzzer_fops, }; static int __init buzzer_init(void) { /** * 注册杂项设备 */ misc_register(&buzzer_miscdev); return 0; } static void __exit buzzer_exit(void) { misc_deregister(&buzzer_miscdev); } module_init(buzzer_init); module_exit(buzzer_exit);