[S5PV210 Linux字符驱动之PWM蜂鸣器驱动
在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
驱动程序
- #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 <mach/gpio.h>
- #include <mach/regs-gpio.h>
- #include <plat/gpio-cfg.h>
- #define DEVICE_NAME "pwm_buzzer"
- #define PWM_IOCTL_SET_FREQ 1
- #define PWM_IOCTL_STOP 0
- #define NS_IN_1HZ (1000000000UL)
- #define BUZZER_PWM_ID 0
- #define BUZZER_PMW_GPIO S5PV210_GPD0(0)
- static struct pwm_device *pwm4buzzer;
- static struct semaphore lock;
- static void pwm_set_freq(unsigned long freq) {
- int period_ns = NS_IN_1HZ / freq;
- pwm_config(pwm4buzzer, period_ns / 2, period_ns);
- pwm_enable(pwm4buzzer);
- }
- static void pwm_stop(void) {
- pwm_config(pwm4buzzer, 0, NS_IN_1HZ / 100);
- pwm_disable(pwm4buzzer);
- }
- static int my_pwm_open(struct inode *inode, struct file *file) {
- if (!down_trylock(&lock))
- return 0;
- else
- return -EBUSY;
- }
- static int my_pwm_close(struct inode *inode, struct file *file) {
- up(&lock);
- return 0;
- }
- static long my_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:
- default:
- pwm_stop();
- break;
- }
- return 0;
- }
- static struct file_operations my_pwm_ops = {
- .owner = THIS_MODULE,
- .open = my_pwm_open,
- .release = my_pwm_close,
- .unlocked_ioctl = my_pwm_ioctl,
- };
- static struct miscdevice my_misc_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &my_pwm_ops,
- };
- static int __init my_pwm_dev_init(void) {
- int ret;
- printk(DEVICE_NAME " my_pwm_dev_init\n");
- 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);
- pwm4buzzer = pwm_request(BUZZER_PWM_ID, DEVICE_NAME);
- if (IS_ERR(pwm4buzzer)) {
- printk("request pwm %d for %s failed\n", BUZZER_PWM_ID, DEVICE_NAME);
- return -ENODEV;
- }
- pwm_stop();
- s3c_gpio_cfgpin(BUZZER_PMW_GPIO, S3C_GPIO_SFN(2));
- gpio_free(BUZZER_PMW_GPIO);
- init_MUTEX(&lock);
- ret = misc_register(&my_misc_dev);
- return ret;
- }
- static void __exit my_pwm_dev_exit(void) {
- printk(DEVICE_NAME " my_pwm_dev_exit\n");
- pwm_stop();
- misc_deregister(&my_misc_dev);
- }
- module_init(my_pwm_dev_init);
- module_exit(my_pwm_dev_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("gjianw217@163.com");
- MODULE_DESCRIPTION("PWM Driver");
复制代码
2 应用程序
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- #define PWM_IOCTL_SET_FREQ 1
- #define PWM_IOCTL_STOP 0
- int main(int argc ,char* argv[])
- {
- int m_fd=0;//
- m_fd = open("/dev/pwm", O_RDONLY);
- int freq=1000;
- if(argc>1)
- freq=atoi(argv[1]);
- printf("%d \t\t",freq);
- ioctl(m_fd, PWM_IOCTL_STOP);
- ioctl(m_fd, PWM_IOCTL_SET_FREQ,freq);
- getchar();
- ioctl(m_fd, PWM_IOCTL_STOP);
- close(m_fd);
- return 0;
- }
复制代码
3 Makefile文件
- #pwm Makefile
- ARCH=arm
- CROSS_COMPILE=/home/ok210/arm-2009q3/bin/arm-none-linux-gnueabi-
- APP_COMPILE=/home/ok210/arm-2009q3/bin/arm-none-linux-gnueabi-
- #obj-m := app-drv.o
- obj-m := pwm-drv.o
- #KDIR := /path/to/kernel/linux/
- KDIR := /home/ok210/android-kernel-samsung-dev/
- PWD := $(shell pwd)
- default:
- make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
- app:pwm-app.c
- $(APP_COMPILE)gcc -o app pwm-app.c
- clean:
- $(MAKE) -C $(KDIR) M=$(PWD) clean
复制代码
[S5PV210 Linux字符驱动之PWM蜂鸣器驱动的更多相关文章
- linux驱动开发之九鼎板载蜂鸣器驱动测试【转】
本文转载自:http://whylinux.blog.51cto.com/10900429/1932491 字符设备驱动用的fileopretion结构体. 1.板载蜂鸣器的驱动测试 我手里有一个BS ...
- at91sam9x5 linux 4.1.0下使能蜂鸣器驱动
测试环境: CPU: AT91SAM9X35 Linux: Atmel提供的linux-at91-linux4sam_5.3 (Linux-4.1.0) 转载请注明: 凌云物网智科嵌入式实 ...
- Linux字符设备驱动框架
字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l ...
- 深入理解Linux字符设备驱动
文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...
- Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】
本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...
- Smart210学习记录----beep linux字符设备驱动
今天搞定了beep linux字符设备驱动,心里还是很开心的,哈哈...但在完成的过程中却遇到了一个非常棘手的问题,花费了我大量的时间,,,, 还是把问题描述一下吧,好像这个问题很普遍的,网上许多解决 ...
- Linux 字符设备驱动及一些简单的Linux知识
一.linux系统将设备分为3类:字符设备.块设备.网络设备 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面向流的设备,常见 ...
- 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl
基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl 0. 导语 在嵌入式的道路上寻寻觅觅很久,进入嵌入式这个行业也有几年的时间了,从2011年后 ...
- Linux字符设备驱动实现
Linux字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...
随机推荐
- linux命令(10):ps命令
1.查看mysql进程数: ps -ef | grep "mysql" | grep -v "grep" | wc –l 2.监控CPU状态:ps –au 3. ...
- 查询 IDE 的版本 方便安装第三方的时候选择
TMD 很多第三方软件 的版本 定义 与 delphi是不一致的. 1.有的是以这个为准.
- LockSupport学习
LockSupport工具类定义了一组的公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能.Java锁和同步器框架的核心工具类AQS:AbstractQueueSynchronizer,就是通过调 ...
- 解决报错:Access denied for user 'root'@'xxx' ,MySQL不允许从远程访问的方法 .
原文地址:传送门 例如,你想myuser使用mypassword从任何主机连接到mysql服务器的话. GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%' IDEN ...
- CentOS 7 上搭建 ownCloud 私有云
所需软件 & 环境 操作系统:CentOS 7.3.1711 最小安装 (已关闭 SELinux 和防火墙) 应用软件: Nginx .MariaDB .PHP .ownCloud 10 ...
- CentOS6安装后的常见基础优化
1.SSH优化 编辑/etc/ssh/sshd_config配置文件 //全部都应该设置为no /etc/ssh/sshd_config //服务端配置文件 /etc/ssh/ssh_config / ...
- nodejs安装sharp出错的问题
PS D:\report\source\lpd-planning-allocation> yarn yarn install v1.3.2 [/] Resolving packages... [ ...
- thinkjphp 模板中获取url中的action
<if condition="ACTION_NAME eq 'add'">新增<else/>编辑</if>
- 【转载】CoordinatorLayout源码解析
源码地址:https://github.com/desmond1121/AndroidSdkSourceAnalysis/blob/master/article/CoordinatorLayout%E ...
- oracle中clob字段怎么查询非空列_20180517
select * from uap_groupsynlogvo a where a.log_msg is not null ; 附加demo的建表脚本跟业务数据. 链接:https://pan.bai ...