驱动开发,控制pwm蜂鸣器!
蜂鸣器有多种类型,一种是给电就叫,另一种给电了还不行,还需要freq才会叫。大概称作有源和无源吧!
我们此时将buzzer的驱动加入到内核中去。
/*
* linux/drivers/char/smart210_pwm.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
#define DEVICE_NAME "pwm-buzzer"
#define PWM_IOCTL_STOP 0
#define PWM_IOCTL_SET_FREQ 1
#define PWM_IOCTL_SET_DUTY 2
#define NS_IN_1HZ (1000000000UL)
#define BUZZER_PWM_ID 0
#define BUZZER_PMW_GPIO S5PV210_GPD0(0)
static struct pwm_device *pwm0buzzer;
static struct semaphore lock;
static void pwm_set_freq(unsigned long freq) {
int period_ns = NS_IN_1HZ / freq;
pwm_config(pwm0buzzer, period_ns / 2, period_ns);
pwm_enable(pwm0buzzer);
s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_SFN(2));
}
static void pwm_stop(void) {
s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_OUTPUT);
pwm_config(pwm0buzzer, 0, NS_IN_1HZ / 100);
pwm_disable(pwm0buzzer);
}
static int smart210_pwm_open(struct inode *inode, struct file *file) {
if (!down_trylock(&lock))
return 0;
else
return -EBUSY;
}
static int smart210_pwm_close(struct inode *inode, struct file *file) {
up(&lock);
return 0;
}
static long smart210_pwm_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
{
switch (cmd) {
case PWM_IOCTL_SET_FREQ:
if (arg == 0)
return -EINVAL;
pwm_set_freq(arg);
break;
case PWM_IOCTL_STOP:
case PWM_IOCTL_SET_DUTY:
default:
pwm_stop();
break;
}
return 0;
}
static struct file_operations smart210_pwm_ops = {
.owner = THIS_MODULE,
.open = smart210_pwm_open,
.release = smart210_pwm_close,
.unlocked_ioctl = smart210_pwm_ioctl,
};
static struct miscdevice smart210_misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &smart210_pwm_ops,
};
static int __init smart210_pwm_dev_init(void) {
int ret;
ret = gpio_request(BUZZER_PMW_GPIO, DEVICE_NAME);
if (ret) {
printk("request GPIO %d for pwm failed\n", BUZZER_PMW_GPIO);
return ret;
}
gpio_set_value(BUZZER_PMW_GPIO, 0);
s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_OUTPUT);
pwm0buzzer = pwm_request(BUZZER_PWM_ID, DEVICE_NAME);
if (IS_ERR(pwm0buzzer)) {
printk("request pwm %d for %s failed\n", BUZZER_PWM_ID, DEVICE_NAME);
return -ENODEV;
}
pwm_stop();
sema_init(&lock, 1);
ret = misc_register(&smart210_misc_dev);
printk(DEVICE_NAME "\tinitialized\n");
return ret;
}
static void __exit smart210_pwm_dev_exit(void) {
pwm_stop();
misc_deregister(&sma