[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字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...
随机推荐
- 关于获取android6.0的mac地址
原文:http://blog.csdn.net/suziluo123/article/details/51382410 最近接触6.0,发现使用单纯的wifiManager.getConnection ...
- python版本管理(python环境隔离)
这将是一篇比较短的文章. 我发文向来注重文章质量,营养不够的宁可不发,但是我相信很多人需要这篇文章. 之所以要去搞清楚这个问题,是我在把 vscode 的 inspector 设置为 pipenv 生 ...
- 六十二 Web开发 使用模板
Web框架把我们从WSGI中拯救出来了.现在,我们只需要不断地编写函数,带上URL,就可以继续Web App的开发了. 但是,Web App不仅仅是处理逻辑,展示给用户的页面也非常重要.在函数中返回一 ...
- ubuntu16.04编译安装GPAC
参考:http://blog.csdn.net/tianlong_hust/article/details/9273875 1.获取gpac的源代码 sudo apt-get install subv ...
- (1)go 环境搭建
1 .下载安装 https://golang.org/ 2.环境变量配置 安装后会自动配置三个环境变量 (1) GOROOT: (2) PATH: (3) GOPATH GOPATH 从1.8开始,w ...
- 1. Maven - 开始
今天开始记录Maven的学习过程. ☞ 相关明细 操作系统:win7 参考书籍:<maven-definitive-guide_zh>(Maven权威指南) maven版本:3.3.3 ☞ ...
- 34、Flask实战第34天:修改邮箱
修改邮箱页面布局 新建cms/cms_resetemail.html {% extends 'cms/cms_base.html' %} {% block title %}修改邮箱-CMS管理系统{% ...
- 【manacher】HDU3068-最长回文
[题目大意] 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. [manacher知识点] ①mx - i > P[j] 的时候,以S[j]为中心的回文子串 ...
- CSS3新增
1 CSS3 的选择器 1.1 基本选择器 tagName .className #idName * slector,selector,selector 1.2 层级选择器 selector1 sel ...
- [NOI2017]整数
[NOI2017]整数 题目大意: \(n(n\le10^6)\)次操作维护一个长度为\(30n\)的二进制整数\(x\),支持以下两种操作: 将这个整数加上\(a\cdot2^b(|a|\le10^ ...