加入收藏 | 设为首页 | 会员中心 | 我要投稿 江门站长网 (https://www.0750zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Mini2440开发板PWM驱动与测试程序简要详解

发布时间:2021-11-21 21:27:12 所属栏目:教程 来源:互联网
导读:先看下电路原理图 #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 <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 %lxn", 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"tinitializedn");
 
            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");

(编辑:江门站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读