[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字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...
随机推荐
- HDU-2487
Ugly Windows Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- git报错The authenticity of host 'github.com (13.229.188.59)' can't be established. RSA key fingerprint is。。。
额,记录下,.ssh/rsa_pub的内容都加到githup.com配置来,为什么还是报这个错呢. 最后发现是个小白问题,如下图 只需要输入yes就ok.
- 手机端调试console.log,直接引入一个js文件
http://files.cnblogs.com/files/lwwen/mConsole.js 这是我写的一个原生js文件 直接引入即可,可以把html上面的需要打印的东西打印出来 <!DOC ...
- CentOS7.5安装配置conky(极简)
1.安装epel源 下载地址:http://dl.fedoraproject.org/pub/epel/ 找到epel-release-XXXXXXX.rpm文件,下载解压 rpm -ivh epel ...
- hdu 5117 数学公式展开 + dp
题目大意:有n个灯泡,m个按钮,(1 <= n, m <= 50),每个按钮和ki 个灯泡相关, 按下后,转换这些灯泡的状态,问你所有2^m的按下按钮的 组合中亮着的灯泡的数量的三次方的和 ...
- Windows 上面优秀的工具软件推荐
Windows 上面优秀的工具软件推荐 一.下载软件 1.速盘 - 度盘神器 简介: 使百度网盘保持全速下载免受限速困扰! 下载: speedpan 2.http下载工具 百度网盘破解下载器:prox ...
- 动若脱兔:深入浅出angr--初步理解符号执行以及angr架构
一:概论 angr作为符号执行的工具,集成了过去的许多分析方式,它不仅能进行动态符号执行,而且还能进行很多静态分析,他在分析二进制程序中能发挥很大的作用,下面为一些应用: 1:利用符号执行探究执行路径 ...
- UML动态模型(顺序图、协作图、状态图)
顺序图:用来表示用例中的行为顺序,当执行一个用例行为时,顺序图中的每条信息 对应了一个类操作或状态机中引起转换的事件.顺序图展示对象之间的交互,这些交互是指在场景或用例的时间六中发生的,顺序图属于动态 ...
- 安卓 应用app启动过程
韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha 313134555@qq.com 从用户点击 Launcher 上的 App 图标,到显示出 App 界面时主要发生的事情.知晓以 ...
- 【UOJ #131】【NOI 2015】品酒大会
http://uoj.ac/problem/131 求出后缀数组和height数组后,从大到小扫相似度进行合并,每次相当于合并两个紧挨着的区间. 合并区间可以用并查集来实现,每个区间的信息都记录在这个 ...