主题 : Micro2440+3.5LCD开发板上有多少PWM可以使用的? 复制链接 | 浏览器收藏 | 打印
solo man
级别: 新手上路
UID: 9835
精华: 0
发帖: 1
金钱: 10 两
威望: 5 点
综合积分: 2 分
注册时间: 2009-10-15
最后登录: 2009-10-24
楼主  发表于: 2009-10-23 13:16

 Micro2440+3.5LCD开发板上有多少PWM可以使用的?

刚买了一块Micro2440+3.5LCD开发板,现在要用到PWM,但是不知道板上有多少PWM资源可以利用。
我看一些书上说S3C2440这块ARM芯片共有0~4个定时器,定时器4为LINUX系统调度使用,定时器3为DMA使用,定时器2~0可用。但是我看了一下这块Micro2440板子上面定时器1的输出引脚GPB1为LCD显示占用,GPB0为蜂鸣器使用,就GPB2没有使用到。
现在我急需3路PWM输出,但是不知道怎么解决,希望高手帮忙指点一下。
You'll never know entil you try.
这个阶段正是我事业的上升期,我怎么能走得开呢?
级别: 精灵王
UID: 3197
精华: 3
发帖: 770
金钱: 6995 两
威望: 5398 点
综合积分: 1600 分
注册时间: 2008-12-30
最后登录: 2010-12-31
1楼  发表于: 2009-10-23 15:34
GPB1实际是悬空的,可以用作其他用途。如果不需要蜂鸣器,也可以把GPB0当作自留地。
级别: 新手上路
UID: 10097
精华: 0
发帖: 2
金钱: 20 两
威望: 10 点
综合积分: 4 分
注册时间: 2009-10-24
最后登录: 2009-11-09
2楼  发表于: 2009-10-24 10:59

 回 1楼(26672624) 的帖子

高手帮忙看看我这将原先的Buzzer程序该写了,增加了T1,T2,T3的PWM,程序编译没有错误。并且我把重要的一些信息都用printk()给打印出来了,寄存器显示结果分析没什么问题的,但是结果就是GPB0 有PWM ,GPB1 GPB2 GPB3都没有输出。程序源代码如下:
#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 <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.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
#define PWM_IOCTL_STOP            2

static struct semaphore lock;

/*---------------------------------------------------------------------------------------
    Timer 0 Freq=20KHz  Duty=0~100%
  * human ear : 20Hz~ 20KHz
------------------------------------------------------------------------------------------ */
static void PWM_Set(unsigned int duty)
{
    unsigned long tcon;
    unsigned long tcnt;
    unsigned long tcfg1;
    unsigned long tcfg0;
    unsigned long tmp;        //debug

    struct clk *clk_p;
    unsigned long pclk;

    //get cpu clock
    clk_p = clk_get(NULL, "pclk");    
    pclk  = clk_get_rate(clk_p);
    
        /*---------------------------------------------------------
            printk()    //Debug only
        ----------------------------------------------------------*/

        /*---------------------------------------------------------
                    Timer0 pwm output
        --------------------------------------------------------*/

        tcon  = __raw_readl(S3C2410_TCON);
        printk("Tcon=%x\n",tcon);        //Only Timer4 is running
        tcfg1 = __raw_readl(S3C2410_TCFG1);
        printk("Tcfg1=%x\n",tcfg1);        //All mux=1/2
        tcfg0 = __raw_readl(S3C2410_TCFG0);
        printk("Tcfg0=%x\n",tcfg0);        //prescaler0=None,prescaler1=2

        //set GPB0 as tout0, pwm output mode
        s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);
        //prescaler0= 50
        tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
        tcfg0 |= (50 - 1);
        //mux0 = 1/2    
        tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
        tcfg1 |= S3C2410_TCFG1_MUX0_DIV2;
        __raw_writel(tcfg0, S3C2410_TCFG0);
        __raw_writel(tcfg1, S3C2410_TCFG1);
        tcnt  = (pclk/50)/20000;    //Freq=20KHz
        __raw_writel(tcnt, S3C2410_TCNTB(0));            //write to Timer0 TCNTB

        tmp= __raw_readl(S3C2410_TCNTB(0));
        printk("S3C2410_TCNTB(0)=%x\n",tmp);

        __raw_writel(duty*tcnt/100, S3C2410_TCMPB(0));    //write to Timer0 TCMPB

        tmp= __raw_readl(S3C2410_TCMPB(0));
        printk("S3C2410_TCMPB(0)=%x\n",tmp);

        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);
        /*---------------------------------------------------------
                    Timer1 pwm output
        --------------------------------------------------------*/

        tcon  = __raw_readl(S3C2410_TCON);
        printk("Tcon=%x\n",tcon);        //Only Timer4 is running
        tcfg1 = __raw_readl(S3C2410_TCFG1);
        printk("Tcfg1=%x\n",tcfg1);        //All mux=1/2
        tcfg0 = __raw_readl(S3C2410_TCFG0);
        printk("Tcfg0=%x\n",tcfg0);        //prescaler0=None,prescaler1=2

        //set GPB1 as tout1, pwm output mode
        s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_TOUT1);
        //prescaler0= 50
        tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
        tcfg0 |= (50 - 1);
        //mux0 = 1/2    
        tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
        tcfg1 |= S3C2410_TCFG1_MUX0_DIV2;
        __raw_writel(tcfg0, S3C2410_TCFG0);
        __raw_writel(tcfg1, S3C2410_TCFG1);
        tcnt  = pclk/50/20000;    //Freq=20KHz
        __raw_writel(tcnt, S3C2410_TCNTB(1));            //write to Timer0 TCNTB

        tmp= __raw_readl(S3C2410_TCNTB(1));
        printk("S3C2410_TCNTB(1)=%x\n",tmp);

        __raw_writel(duty*tcnt/100, S3C2410_TCMPB(1));    //write to Timer0 TCMPB

        tmp= __raw_readl(S3C2410_TCMPB(1));
        printk("S3C2410_TCMPB(1)=%x\n",tmp);

        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);    
        /*---------------------------------------------------------
                    Timer2 pwm output
        --------------------------------------------------------*/
        tcon  = __raw_readl(S3C2410_TCON);
        printk("Tcon=%x\n",tcon);    //500009    
        tcfg1 = __raw_readl(S3C2410_TCFG1);
        printk("Tcfg1=%x\n",tcfg1);
        tcfg0 = __raw_readl(S3C2410_TCFG0);
        printk("Tcfg0=%x\n",tcfg0);

        //Set GPB2 as TOUT2 ,pwm output mode
        s3c2410_gpio_cfgpin(S3C2410_GPB2, S3C2410_GPB2_TOUT2);
        //prescaler1= 50
//        tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
//        tcfg0 |= (50 - 1)<<8;
        //mux2 = 1/2    
        tcfg1 &= ~S3C2410_TCFG1_MUX2_MASK;
        tcfg1 |= S3C2410_TCFG1_MUX2_DIV2;
//        __raw_writel(tcfg0, S3C2410_TCFG0);
        __raw_writel(tcfg1, S3C2410_TCFG1);
        //Freq & duty Set
        tcnt  = (pclk/50)/2000;    //Freq=20KHz
        __raw_writel(tcnt, S3C2410_TCNTB(2));            //write to Timer0 TCNTB

        tmp= __raw_readl(S3C2410_TCNTB(2));
        printk("S3C2410_TCNTB(2)=%x\n",tmp);

        __raw_writel(duty*tcnt/100, S3C2410_TCMPB(2));    //write to Timer0 TCMPB

        tmp= __raw_readl(S3C2410_TCMPB(2));
        printk("S3C2410_TCMPB(2)=%x\n",tmp);

        //auto-reload ,update TCNTB2&TCMPB2,start timer2
        tcon &= 0xFFBFFF;
        tcon |= 0x9<<12;        
        __raw_writel(tcon, S3C2410_TCON);
        tcon  = __raw_readl(S3C2410_TCON);
        printk("Tcon=%x\n",tcon);
    /*---------------------------------------------------------
                    Timer3 pwm output
        --------------------------------------------------------*/
        tcon  = __raw_readl(S3C2410_TCON);
        printk("Tcon=%x\n",tcon);    //500009    
        tcfg1 = __raw_readl(S3C2410_TCFG1);
        printk("Tcfg1=%x\n",tcfg1);
        tcfg0 = __raw_readl(S3C2410_TCFG0);
        printk("Tcfg0=%x\n",tcfg0);

        //Set GPB3 as TOUT3 ,pwm output mode
        s3c2410_gpio_cfgpin(S3C2410_GPB3, S3C2410_GPB3_TOUT3);
        //prescaler1= 50
//        tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
//        tcfg0 |= (50 - 1)<<8;
        //mux2 = 1/16    
        tcfg1 &= ~S3C2410_TCFG1_MUX3_MASK;
        tcfg1 |= S3C2410_TCFG1_MUX3_DIV16;
//        __raw_writel(tcfg0, S3C2410_TCFG0);
        __raw_writel(tcfg1, S3C2410_TCFG1);
        //Freq & duty Set
        tcnt  = (pclk/50)/2000;    //Freq=20KHz
        __raw_writel(tcnt, S3C2410_TCNTB(3));            //write to Timer0 TCNTB

        tmp= __raw_readl(S3C2410_TCNTB(3));
        printk("S3C2410_TCNTB(3)=%x\n",tmp);

        __raw_writel(duty*tcnt/100, S3C2410_TCMPB(3));    //write to Timer0 TCMPB

        tmp= __raw_readl(S3C2410_TCMPB(3));
        printk("S3C2410_TCMPB(3)=%x\n",tmp);

        //auto-reload ,update TCNTB3&TCMPB3,start timer3
        tcon &= 0xFFBFFF;
        tcon |= 0x9<<12;        
        __raw_writel(tcon, S3C2410_TCON);
        tcon  = __raw_readl(S3C2410_TCON);
        printk("Tcon=%x\n",tcon);
}
/*
void PWM_init(void)
{
    //TOUT0 OUTPUT
    s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
    s3c2410_gpio_setpin(S3C2410_GPB0, 1);
    //TOUT1 OUTPUT
    s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_OUTP);
    s3c2410_gpio_setpin(S3C2410_GPB1, 1);
    //TOUT2 OUTPUT
    s3c2410_gpio_cfgpin(S3C2410_GPB2, S3C2410_GPB2_OUTP);
    s3c2410_gpio_setpin(S3C2410_GPB2, 1);
    //TOUT3 OUTPUT
    s3c2410_gpio_cfgpin(S3C2410_GPB3, S3C2410_GPB3_OUTP);
    s3c2410_gpio_setpin(S3C2410_GPB3, 1);
}
*/
void PWM_Stop( void )
{
    //TOUT0 OUTPUT
    s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
    s3c2410_gpio_setpin(S3C2410_GPB0, 0);
    //TOUT1 OUTPUT
    s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_OUTP);
    s3c2410_gpio_setpin(S3C2410_GPB1, 0);
    //TOUT2 OUTPUT
    s3c2410_gpio_cfgpin(S3C2410_GPB2, S3C2410_GPB2_OUTP);
    s3c2410_gpio_setpin(S3C2410_GPB2, 0);
    //TOUT3 OUTPUT
    s3c2410_gpio_cfgpin(S3C2410_GPB3, S3C2410_GPB3_OUTP);
    s3c2410_gpio_setpin(S3C2410_GPB3, 0);
}

static int s3c24xx_pwm_open(struct inode *inode, struct file *file)
{
    if (!down_trylock(&lock))
        return 0;
    else
        return -EBUSY;
}


static int s3c24xx_pwm_close(struct inode *inode, struct file *file)
{
    up(&lock);
    return 0;
}


static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned int duty_tmp)
{
    switch (cmd) {
        case PWM_IOCTL_SET_FREQ:
            PWM_Set(duty_tmp);
            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"\tinitialized\n");
        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");
级别: 新手上路
UID: 9652
精华: 0
发帖: 20
金钱: 125 两
威望: 40 点
综合积分: 40 分
注册时间: 2009-10-09
最后登录: 2011-12-27
3楼  发表于: 2010-09-29 14:41

 回 2楼(janky) 的帖子

我也是同样的问题,有没有高手帮忙解答一下啊