您的位置 首页 电子

PWM在ARM Linux中的原理和蜂鸣器驱动实例开发

1.什么是PWM?PWM(脉冲宽度调制)简单的讲是一种变频技术之一,是靠改变脉冲宽度来控制输出电压,通过改变周期来控制其输出频率。如果还…

1. 什么是PWM

PWM(脉冲宽度调制)简略的讲是一种变频技能之一,是靠改动脉冲宽度来操控输出电压,经过改动周期来操控其输出频率。假如还不是很清楚,好吧,来看看咱们实际生活中的比如,咱们的电电扇为什么扭一下按扭,电扇的转速就会产生变化;调一下收音机的声响按钮,声响的巨细就会产生变化;还有待会儿咱们要讲的蜂鸣器也会依据不同的输入值而宣布不同频率的叫声等等!!这些都是PWM的运用,都是经过PWM输出的频率信号进行操控的。

2. ARM Linux中的PWM

依据S3C2440的手册介绍,S3C2440A内部有5个16位的定时器,定时器0、1、2、3都带有脉冲宽度调制功用(PWM),定时器4是一个没有输出引脚的内部定时器,定时器0有一个用于大电流设备的死区生成器。看下图解说吧!!

由S3C2440的技能手册和上面这幅结构图,咱们来总结一下2440内部定时器模块的特性吧:

1)共5个16位的定时器,定时器0、1、2、3都带有脉冲宽度调制功用(PWM);
2)每个定时器都有一个比较缓存存放器(TCMPB)和一个计数缓存存放器(TCNTB);
3)定时器0、1同享一个8位的预分频器(预定标器),定时器2、3、4同享另一个8位的预分频器(预定标器),其值规模是0~255;
4)定时器0、1同享一个时钟分频器,定时器2、3、4同享另一个时钟分频器,这两个时钟分频器都能产生5种不同的分频信号值(即:1/2、1/4、1/8、1/16和TCLK);
5)两个8位的预分频器是可编程的且依据装载的值来对PCLK进行分频,预分频器和钟分频器的值别离存储在定时器装备存放器TCFG0和TCFG1中;
6)有一个TCON操控存放器操控着一切定时器的特点和状况,TCON的第0~7位操控着定时器0、第8~11位操控着定时器1、第12~15位操控着定时器2、第16~19位操控着定时器3、第20~22位操控着定时器4。

仍是依据S3C2440手册的描绘和上图的结构,要开端一个PWM定时器功用的过程如下(假定运用的是第一个定时器):

1)别离设置定时器0的预分频器值和时钟分频值,以供定时器0的比较缓存存放器和计数缓存存放器用;
2)设置比较缓存存放器TCMPB0和计数缓存存放器TCNTB0的初始值(即定时器0的输出时钟频率);
3)封闭定时器0的死区生成器(设置TCON的第4位);
4)敞开定时器0的主动重载(设置TCON的第3位);
5)封闭定时器0的反相器(设置TCON的第2位);
6)敞开定时器0的手动更新TCNTB0&TCMPB0功用(设置TCON的第1位);
7)发动定时器0(设置TCON的第0位);
8)铲除定时器0的手动更新TCNTB0&TCMPB0功用(设置TCON的第1位)。

由此能够看到,PWM的输出频率跟比较缓存存放器和计数缓存存放器的取值有关,而比较缓存存放器和计数缓存存放器的值又跟预分频器和时钟分频器的值有关;要运用PWM功用其实也便是对定时器的相关存放器进行操作。手册上也有一个公式:定时器输出频率 = PCLK / {预分频器值 + 1} / 时钟分频值。下面咱们来经过一个蜂鸣器的实例来阐明PWM功用的运用。

三、蜂鸣器驱动实例

1. 蜂鸣器的品种和作业原理

蜂鸣器首要分为压电式蜂鸣器和电磁式蜂鸣器两品种型。

压电式蜂鸣器首要由多谐振动器、压电蜂鸣片、阻抗匹配器及共识箱、外壳等组成。有的压电式蜂鸣器外壳上还装有发光二极管。多谐振动器由晶体管或%&&&&&%构成。当接通电源后(1.5~15V直流作业电压),多谐振动器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推进压电蜂鸣片发声。

电磁式蜂鸣器由振动器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振动器产生的音频信号电流经过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

有源蜂鸣器和无源蜂鸣器的差异:这个“源”字是不是指电源,而是指震动源,即有源蜂鸣器内有振动源而无源蜂鸣器内部没有振动源。有振动源的通电就能够发声,没有振动源的需求脉冲信号驱动才干发声。

额定常识:简略蜂鸣器的制作办法
1)制备电磁铁M:在长约6厘米的铁螺栓上绕100圈导线,线端留下5厘米作引线,用通明胶布把线圈粘好,避免线圈松开,再用胶布把它粘在一个盒子上,电磁铁就做好了;
2)制备弹片P:从铁罐头盒上剪下一条宽约2厘米的长铁片,弯成直角,把电磁铁的一条引线接在弹片上,再用胶布把弹片紧贴在木板上;
3)用曲别针做触头Q,用书把曲别针垫高,用胶布粘牢,引出一条导线,如图连接好电路;
4)调理M与P之间的间隔(经过移动盒子),使电磁铁能招引弹片,调理触点与弹片之间的间隔,使它们能刚好触摸,通电后就能够听到蜂鸣声。
2. 开发板上蜂鸣器原理图分析
由原理图能够得知,蜂鸣器是经过GPB0 IO口运用PWM信号驱动作业的,而GPB0口是一个复用的IO口,要运用它得先把他设置成TOUT0 PWM输出形式。

3. 编写适宜开发板的蜂鸣器驱动程序,文件名:my2440_pwm.c

/*
================================================
Name : my2440_pwm.c
Author : Huang Gang
Date : 25/11/09
Copyright : GPL
Description : my2440 pwm driver
================================================
*/

#include#include#include#include#include#include#include#include
#include
#include
#include

#definePWM_MAJOR 0//主设备号
#definePWM_NAME”my2440_pwm”//设备称号

staticintdevice_major=PWM_MAJOR;//体系动态生成的主设备号

//翻开设备
staticintpwm_open(structinode*inode,structfile*file)
{
//对GPB0复用口进行复用功用设置,设置为TOUT0 PWM输出
s3c2410_gpio_cfgpin(S3C2410_GPB0,S3C2410_GPB0_TOUT0);

return0;
}

//封闭设备
staticintpwm_close(structinode*inode,structfile*file)
{
return0;
}

//对设备进行操控
staticintpwm_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)
{
if(cmd<=0)//假如输入的参数小于或等于0的话,就让蜂鸣器中止作业
{
//这儿又康复GPB0口为IO口输出功用,由原理图可知直接给低电平可让蜂鸣器中止作业
s3c2410_gpio_cfgpin(S3C2410_GPB0,S3C2410_GPB0_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB0,0);
}
else//假如输入的参数大于0,就让蜂鸣器开端作业,不同的参数,蜂鸣器的频率也不一样
{
//界说一些局部变量
unsignedlongtcon;
unsignedlongtcnt;
unsignedlongtcfg1;
unsignedlongtcfg0;

structclk*clk_p;
unsignedlongpclk;

//以下对各存放器的操作结合上面讲的开端一个PWM定时器的过程和2440手册PWM存放器操作部分来看就比较简单了解
tcfg1=__raw_readl(S3C2410_TCFG1);//读取定时器装备存放器1的值
tcfg0=__raw_readl(S3C2410_TCFG0);//读取定时器装备存放器0的值

tcfg0&=~S3C2410_TCFG_PRESCALER0_MASK;
tcfg0|=(50-1);//设置tcfg0的值为49

tcfg1&=~S3C2410_TCFG1_MUX0_MASK;
tcfg1|=S3C2410_TCFG1_MUX0_DIV16;//设置tcfg1的值为0x0011即:1/16

__raw_writel(tcfg1,S3C2410_TCFG1);//将值tcfg1写入定时器装备存放器1中
__raw_writel(tcfg0,S3C2410_TCFG0);//将值tcfg0写入定时器装备存放器0中

clk_p=clk_get(NULL,”pclk”);
pclk=clk_get_rate(clk_p);//从体系渠道时钟行列中获取pclk的时钟频率,在include/linux/clk.h中界说
tcnt=(pclk/50/16)/cmd;//核算定时器0的输出时钟频率(pclk/{prescaler0 + 1}/divider value)

__raw_writel(tcnt,S3C2410_TCNTB(0));//设置定时器0计数缓存存放器的值
__raw_writel(tcnt/2,S3C2410_TCMPB(0));//设置定时器0比较缓存存放器的值

tcon=__raw_readl(S3C2410_TCON);//读取定时器操控存放器的值

tcon&=~0x1f;
tcon|=0xb;//封闭死区、主动重载、关反相器、更新TCNTB0&TCMPB0、发动定时器0
__raw_writel(tcon,S3C2410_TCON);//设置定时器操控存放器的0-4位,即对定时器0进行操控

tcon&=~2;
__raw_writel(tcon,S3C2410_TCON);//铲除定时器0的手动更新位
}

return0;
}

//设备操作结构体
staticstructfile_operations pwm_fops=
{
.owner=THIS_MODULE,
.open=pwm_open,
.release=pwm_close,
.ioctl=pwm_ioctl,
};

//界说一个设备类
staticstructclass*pwm_class;

staticint__init pwm_init(void)
{
//注册为字符设备,主设备号为0让体系主动分配,设备名为my2440_pwm,注册成功回来动态生成的主设备号
device_major=register_chrdev(PWM_MAJOR,PWM_NAME,&pwm_fops);

if(device_major<0)
{
printk(PWM_NAME” register falid!/n”);
returndevice_major;
}

//注册一个设备类,使mdev能够在/dev/目录下主动树立设备节点
pwm_class=class_create(THIS_MODULE,PWM_NAME);

if(IS_ERR(pwm_class))
{
printk(PWM_NAME” register class falid!/n”);
return-1;
}

//创立一个设备节点,设备名为PWM_NAME,即:my2440_pwm
device_create(pwm_class,NULL,MKDEV(device_major,0),NULL,PWM_NAME);

return0;
}

staticvoid__exit pwm_exit(void)
{
//刊出设备
unregister_chrdev(device_major,PWM_NAME);

//删去设备节点
device_destroy(pwm_class,MKDEV(device_major,0));

//刊出设备类
class_destroy(pwm_class);
}

module_init(pwm_init);
module_exit(pwm_exit);

MODULE_L%&&&&&%ENSE(“PGL”);
MODULE_AUTHOR(“Huang Gang”);
MODULE_DESCRIPTION(“my2440 pwm driver”);

4. 将PWM蜂鸣器驱动代码布置到内核中。

#cp -f my2440_pwm.c /linux-2.6.30.4/drivers/char //把驱动源码到内核驱动的字符设备下

#gedit /linux-2.6.30.4/drivers/char/Kconfig //增加PWM蜂鸣器设备装备

config MY2440_PWM_BEEP
tristate”My2440 PWM Beep Device”
dependsonARCH_S3C2440
default y
—help—
My2440 PWM Beep

#gedit /linux-2.6.30.4/drivers/char/Makefile //增加PWM蜂鸣器设备装备

obj-$(CONFIG_MY2440_PWM_BEEP) +=my2440_pwm.o

5.装备内核,挑选PWM蜂鸣器设备选项

#make menuconfig

Device Drivers —>
Character devices —>
<*> My2440 PWM Beep Device (NEW)

6. 编译内核并下载到开发板上。这儿要注意,现在咱们不需求手动的在开发板上创立设备的节点了,由于咱们现在运用了mdev进行管理了(运用办法请看:设备文件体系分析与运用),在驱动程序中也增加了对类设备接口的支撑。之前讲的一些驱动都没有,今后咱们都运用这种办法。现在能够查看到/dev目录下主动创立好的my2440_pwm设备节点,就直接能够运用它了。

7. 编写PWM蜂鸣器驱动的测验程序。文件名:pwm_test.c

/*
==============================================
Name : pwm_test.c
Author : Huang Gang
Date : 25/11/2009
Copyright : GPL
Description : my2440 pwm driver test
==============================================
*/

#include
#include
#include
#include

intmain(intargc,char**argv)
{
inttmp;
intfd;
inti;

//翻开蜂鸣器设备
fd=open(“/dev/my2440_pwm”,O_RDWR);

if(fd<0)
{
printf(“Open PWM Device Faild!/n”);
exit(1);
}

//提示用户输入一个参数来对蜂鸣器进行调频,0表明中止作业
printf(“please enter the times number(0 is stop):/n”);

while(1)
{
//输入参数
scanf(“%d”,&tmp);
printf(“times = %d/n”,tmp);

//IO操控
ioctl(fd,tmp);

if(tmp<=0)
{
break;
}
}

//封闭设备
close(fd);

return0;
}

8. 在开发主机上穿插编译测验运用程序,并到文件体系的/usr/sbin目录下,然后从头编译文件体系下载到开发板上。

#arm-linux-gcc -o pwm_test pwm_test.c

9. 在开发板上运转测验程序。能够看到依据你输入参数的巨细,蜂鸣器也会产生不同频率的叫声,输入0蜂鸣器中止鸣叫。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/dianzi/277371.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部