微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > PWM在ARM Linux中的原理和蜂鸣器驱动实例开发

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

时间:11-09 来源:互联网 点击:

工作的,而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_LICENSE("PGL");
MODULE_AUTHOR("Huang Gang");
MODULE_DESCRIPTION("my2440 pwm driver");

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

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

#gedi

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top