Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / Mini2440开发板PWM驱动与测试程序简要分析

先看下电路原理图 #include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/interrupt.h>#include <linux/gpio.h> #include <asm/irq.h>#include <asm/io.h>#include <asm/uaccess.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <plat/regs-timer.h>#include <mach/regs-irq.h>#include <asm/mach/time.h>#include <linux/clk.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/miscdevice.h> #define DEVICE_NAME    "pwm" #define PWM_IOCTL_SET_FREQ              1    //设置pwm的频率#define PWM_IOCTL_STOP                        0    //停止pwm static struct semaphore lock;           //定义信号量,此处的信号量是一个互斥信号量,用于PWM设备之多只能被一个进程打开 /* freq:  pclk/50/16/65536 ~ pclk/50/16  * if pclk = 50MHz, freq is 1Hz to 62500Hz  * human ear : 20Hz~ 20000Hz  */static void PWM_Set_Freq( unsigned long freq ){        unsigned long tcon;        unsigned long tcnt;        unsigned long tcfg1;        unsigned long tcfg0;         struct clk *clk_p;        unsigned long pclk;         //set GPB0 as tout0, pwm output        s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);//功能配置         tcon = __raw_readl(S3C2410_TCON);    //获得定时器控制寄存器的数值        tcfg1 = __raw_readl(S3C2410_TCFG1);  //获得定时器配置寄存器0的值        tcfg0 = __raw_readl(S3C2410_TCFG0);  //获得定时器配置寄存器1的值         //prescaler = 50        tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;        tcfg0 |= (50 - 1);         //mux = 1/16        tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;        tcfg1 |= S3C2410_TCFG1_MUX0_DIV16;         __raw_writel(tcfg1, S3C2410_TCFG1);        __raw_writel(tcfg0, S3C2410_TCFG0);         clk_p = clk_get(NULL, "pclk");        pclk  = clk_get_rate(clk_p);        tcnt  = (pclk/50/16)/freq;               __raw_writel(tcnt, S3C2410_TCNTB(0));        __raw_writel(tcnt/2, S3C2410_TCMPB(0));                                           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);} static void PWM_Stop(void){        s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);        s3c2410_gpio_setpin(S3C2410_GPB(0), 0);} static int s3c24xx_pwm_open(struct inode *inode, struct file *file){        if (!down_trylock(&lock))//判断是否设备已经打开,已打开返回EBUSY                  return 0;        else                  return -EBUSY;}  static int s3c24xx_pwm_close(struct inode *inode, struct file *file){        PWM_Stop();//停止PWM        up(&lock);//释放信号量    return 0;}  static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){        //printk("ioctl pwm: %x %lx ", cmd, arg);        switch (cmd) {        case PWM_IOCTL_SET_FREQ:                  if (arg == 0)                            return -EINVAL;                  PWM_Set_Freq(arg);                  break;         case PWM_IOCTL_STOP:                  PWM_Stop();                  break;        }         return 0;}  static struct file_operations dev_fops = {    .owner  =  THIS_MODULE,    .open    =  s3c24xx_pwm_open,    .release =  s3c24xx_pwm_close,    .ioctl  =  s3c24xx_pwm_ioctl,}; static struct miscdevice misc = {        .minor = MISC_DYNAMIC_MINOR,        .name = DEVICE_NAME,        .fops = &dev_fops,}; static int __init dev_init(void){        int ret;         init_MUTEX(&lock);        ret = misc_register(&misc);         printk (DEVICE_NAME" initialized ");            return ret;} static void __exit dev_exit(void){        misc_deregister(&misc);} module_init(dev_init);module_exit(dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("FriendlyARM Inc.");MODULE_DESCRIPTION("S3C2410/S3C2440 PWM Driver");