首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于 2.6 内核的 pwm 蜂鸣器驱动设计(4)

基于 2.6 内核的 pwm 蜂鸣器驱动设计(4)

  来自: http://hi.baidu.com/largeji/blog/item/c7cb683ee02386f0828b1351.html
  view plaincopy to clipboardprint? ·····10········20········30········40········50········60········70········80········90········100·······110·······12 ···· 0·······130·······140·······150 /**************************************************************** Copyright(c) 2009-2010,Newkoom Net Tech.Co,.Ltd 模块名称(Filename): beep_s3c2410.c 项目名称(Projectname): RPM(Remote Power Manager System) 版本号(Version): 1.0.0 创建日期(Date): 2009-11-22 作者(Author): ZMF(Zheng meifu) 功能描述(Description): buzzer(beep) driver for linux2.6.14.1 其他说明(Others): 修改记录(History): 调试成功:2009-11-23 2009-12-1:之前只能在定时任务结束后才释放锁,今天改为 设置完 ioctl 后立即释放,以便连续发声。 ****************************************************************/ #include#include
  #include#include#include#include#include #include #include#include #include #include #include #include #include #include #include#include#include#define BEEPDEV_NAME "beep" /*设备名 beep*/ #define PWM_IOCTL_SET_FREQ 1 /*定义宏常量,用于后面的 ioctl 中的 switch case*/ #define PWM_IOCTL_STOP 2 #define SET_RIGHT_ACTION_BEEP 3 // 此处宏数字不能改,和以下 beep_const 序号 相关 #define SET_ERROR_ACTION_BEEP 4 // 同上 #define SET_KEY_PRESS_BEEP 5 // 同上 #define BEON (1<<(sizeof(int)*8-1)) #define BEOF 0 #define PRESET_FREQ 1000 #define KEY_DELAYMS(X) (HZ/(1000/(X))) static struct semaphore lock; /*定义信号量 lock*/ static struct semaphore ioctl_lock; /* freq: pclk/50/16/65536 ~ pclk/50/16 * if pclk = 50MHz, freq is 1Hz to 62500Hz * human ear : 20Hz~ 20000Hz */ const int beep_const[3][8]={ {500|BEON,100|BEOF,0,0,0,0,0,0}, // right {100|BEON,50|BEOF,100|BEON,50|BEOF,100|BEON,50|BEOF,0,0}, // error {100|BEON,50|BEOF,0,0,0,0,0,0}, // key }; struct timer_list beep_timer; static int beep_step;
  static void PWM_Set_Freq(unsigned long freq); static void PWM_Stop(void); static void beep_timer_handler(unsigned long data){ int onofftime=beep_const[data][beep_step++]; if(onofftime !=0){ beep_timer.data = data; mod_timer(&beep_timer, jiffies+ KEY_DELAYMS(onofftime&(~BEON))); if(onofftime&BEON) PWM_Set_Freq(PRESET_FREQ); else PWM_Stop(); }else{ PWM_Stop(); del_timer(&beep_timer); //up(&ioctl_lock); } } static void set_beep_type(int type){ int tmp_time= beep_const[type-3][0]&(~BEON); del_timer(&beep_timer); init_timer(&beep_timer); beep_timer.expires = jiffies + KEY_DELAYMS(tmp_time); beep_timer.function = beep_timer_handler; beep_timer.data = type-3; beep_step=1; add_timer(&beep_timer); PWM_Set_Freq(PRESET_FREQ); } static void PWM_Set_Freq( unsigned long freq ) /*设置 pwm 的频率, 配置各个寄 存器*/ { unsigned long tcon, tcnt, tcfg1, tcfg0,pclk; struct clk *clk_p; /*set GPB0 as tout0, pwm output 设置 GPB0 为 tout0,pwm 输出*/ s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0); tcon = __raw_readl(S3C2410_TCON); /*读取寄存器 TCON 到 tcon*/ tcfg1 = __raw_readl(S3C2410_TCFG1); /*读取寄存器 TCFG1 到 tcfg1*/ tcfg0 = __raw_readl(S3C2410_TCFG0); /*读取寄存器 TCFG0 到 tcfg0*/ //prescaler = 50 tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; /* S3C2410_TCFG_PRESCALER0_MASK 定时器 0 和*/ /* 1 的预分频值的掩码,TCFG[0~8]*/ tcfg0 |= (50 - 1); /* 预分频为 50 */
  //mux = 1/16 tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK; 时器 0 分割值的掩*/
  /*S3C2410_TCFG1_MUX0_MASK 定 /*
  码:TCFG1[0~3]*/ tcfg1 |= S3C2410_TCFG1_MUX0_DIV16; /*定时器 0 进行 16 分割*/ __raw_writel(tcfg1, S3C2410_TCFG1); /*把 tcfg1 的 值 写 到 分 割 寄 存 器 S3C2410_TCFG1 中*/ __raw_writel(tcfg0, S3C2410_TCFG0); /*把 tcfg0 的值写到预分频寄存器 S3C2410_TCFG0 中*/ clk_p = clk_get(NULL, "pclk"); /*得到 pclk*/ pclk = clk_get_rate(clk_p); tcnt = (pclk/50/16)/freq; /*得到定时器的输入时钟, 进而设置 PWM 的调制频率 */ __raw_writel(tcnt, S3C2410_TCNTB(0)); /*PWM 脉宽调制的频率等于定时器的 输入时钟 */ __raw_writel(tcnt/2, S3C2410_TCMPB(0)); /*占空比是 50%*/ tcon &= ~0x1f; tcon |= 0xb; /*disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0*/ __raw_writel(tcon, S3C2410_TCON); tcon &= ~2; /*clear manual update bit*/ __raw_writel(tcon, S3C2410_TCON); /*把 tcon 写到计数器控制寄存器 S3C2410_TCON 中*/ } static void PWM_Stop( void ){ s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP); /*设置 GPB0 为输出*/ s3c2410_gpio_setpin(S3C2410_GPB0, 0); /*设置 GPB0 为低电平,使蜂 鸣器停止*/ } static int s3c24xx_pwm_open(struct inode *inode, struct file *file){ if (!down_trylock(&lock)) /*是否获得信号量,是 down_trylock(&lock)=0,否 则非 0*/ return 0; else return -EBUSY; /*返 回错误信息:请求的资源不可用*/ } static int s3c24xx_pwm_close(struct inode *inode, struct file *file){ up(&lock); /*释放信 号量 lock*/ return 0; } /*cmd 是 1,表示设置频率;cmd 是 2 ,表示停止 pwm*/
返回列表