• «
  • 1
  • 2
  • »
  • Pages: 1/2     Go
主题 : 从GPB1输出PWM 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 9652
精华: 0
发帖: 20
金钱: 125 两
威望: 40 点
贡献值: 0 点
综合积分: 40 分
注册时间: 2009-10-09
最后登录: 2011-12-27
楼主  发表于: 2010-09-30 11:32

 从GPB1输出PWM

/* 因为需要输出两路PWM,示例代码中只写了从GPB0输出,也就是蜂鸣器,折腾了好几天才知道怎么从GPB1也输出PWM。 */
/* 在原先的mini2440_pwm.c里面只需要修改PWM_Set_Freq( unsigned long freq )和PWM_Stop( void )这两个函数就可以了。                 */

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_GPB0, S3C2410_GPB0_TOUT0); */  
    /*这里是设置pwm输出口的地方,之前一直不成功,有一方面原因就是只修改了这里*/  
    s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_TOUT1);
    tcon = __raw_readl(S3C2410_TCON);  
    tcfg1 = __raw_readl(S3C2410_TCFG1);  
    tcfg0 = __raw_readl(S3C2410_TCFG0);
    //prescaler = 50
    /*先前以为这里也要改,但是实际上是没有必要改的。  
     * 因为预分频寄存器(TCFG0)的0~7位是timer0和timer1共用的*/  

    tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;  
    tcfg0 |= (50 - 1);
    //mux = 1/16
    /* tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK; */  
    /* tcfg1 |= S3C2410_TCFG1_MUX0_DIV16; */  
    /*这里是比较关键的地方,因为分频寄存器中,timer0和timer1使用的数据位不一样    
     * 分频器的0~3位是给timer0用的, 4~7位是给timer1用的,所以对于timer1要左移4位  
     * #define S3C2410_TCFG1_MUX0_DIV16  (3<<0)  
     * #define S3C2410_TCFG1_MUX0_MASK  (15<<0)  
     * #define S3C2410_TCFG1_MUX1_DIV16  (3<<4)  
     * #define S3C2410_TCFG1_MUX1_MASK  (15<<4)  
     * 从它们的宏定义中就可以看出来了           */  

    tcfg1 &= ~S3C2410_TCFG1_MUX1_MASK;  
    tcfg1 |= S3C2410_TCFG1_MUX1_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(1));  
    __raw_writel(tcnt/2, S3C2410_TCMPB(1));    
    /* 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是定时器位置控制寄存器,0~4位是timer0的,8~11位是timer1的  
     * 这就是为什么原来的代码是 tcon &= ~0x1f,而现在是tcon &= ~0x0f00
     既然是位置控制寄存器,当然要说说它们的作用了:
     对于timer0:        
         bit0:停止或开始timer0计时        
         bit1:手动更新TCNTB0和TCMPB0        
         bit2:TOUT0是否进行电平翻转      
         bit3:使用脉冲模式还是自动装载模式        
         bit4:是否使用死区功能    
     对于timer1:      
         8~11的功能分别对应了0~3    
         这就是我们这里用tcon |= 0x0b00的原因*/  

    tcon &= ~0x0f00;
    tcon |= 0x0b00;
    __raw_writel(tcon, S3C2410_TCON);
    /*这里是我一直没有想明白的地方,为什么要把这一位清掉?还请知道的兄弟解答一下*/  
    tcon &= ~0x0200;
    __raw_writel(tcon, S3C2410_TCON);
}

void PWM_Stop( void )
{      
    /*这个里面的不用说了吧*/
    /* s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP); */  
    s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_OUTP);  
    /* s3c2410_gpio_setpin(S3C2410_GPB0, 0); */  
    s3c2410_gpio_setpin(S3C2410_GPB1, 0);
}
/* 改完这些你就可以用示波器在GPB1(也就是文档上说的CON4的32口)上看到波形了。关于PWM定时器方面的内容在光盘上的s3c2440a_um_rev014_040712.pdf里面都有介绍,可以参考一下 */
[ 此帖被zhangweiguo8在2010-09-30 14:15重新编辑 ]
自由,自强,共享,共创。
级别: 论坛版主
UID: 12573
精华: 27
发帖: 8838
金钱: 46490 两
威望: 9298 点
贡献值: 27 点
综合积分: 18216 分
注册时间: 2010-01-09
最后登录: 2019-07-16
1楼  发表于: 2010-09-30 11:44
感谢你的帖子,建议楼主再编辑一下,不知道是问题还是分享经验。
新手如何向我们反馈有效的信息,以便解决问题,见此贴:
http://www.arm9home.net/read.php?tid-14431.html

[注]: 此处签名链接仅为指引方向,而非解答问题本身.
级别: 新手上路
UID: 9652
精华: 0
发帖: 20
金钱: 125 两
威望: 40 点
贡献值: 0 点
综合积分: 40 分
注册时间: 2009-10-09
最后登录: 2011-12-27
2楼  发表于: 2010-09-30 11:54
发表以后的结果怎么这么难看啊,我还是把源文件贴在附件里面吧
把扩展名改成.c以后就可以直接用了
附件: mini2440_pwm.txt (5 K) 下载次数:99
级别: 新手上路
UID: 9652
精华: 0
发帖: 20
金钱: 125 两
威望: 40 点
贡献值: 0 点
综合积分: 40 分
注册时间: 2009-10-09
最后登录: 2011-12-27
3楼  发表于: 2010-09-30 11:57

 回 1楼(mindee) 的帖子

算是分享经验吧,但是里面带个小问题,帖子还有分经验贴和问题贴吗,我没找到在哪设置呀
年轻就要放肆。
级别: 新手上路
UID: 42265
精华: 0
发帖: 31
金钱: 155 两
威望: 31 点
贡献值: 0 点
综合积分: 62 分
注册时间: 2011-04-06
最后登录: 2012-12-15
4楼  发表于: 2011-08-02 16:19
那个之所以要设置第二位为0是因为不需要更新TCNTB0 & TCMPB0的值。
级别: 新手上路
UID: 3912
精华: 0
发帖: 25
金钱: 125 两
威望: 25 点
贡献值: 0 点
综合积分: 50 分
注册时间: 2009-02-15
最后登录: 2014-04-15
5楼  发表于: 2011-08-03 10:20
mark
最近做小车正好需要,先记下来
级别: 新手上路
UID: 54854
精华: 0
发帖: 6
金钱: 30 两
威望: 6 点
贡献值: 0 点
综合积分: 12 分
注册时间: 2011-09-07
最后登录: 2011-11-18
6楼  发表于: 2011-09-26 22:39
楼主这是在linux下啊。wince下做同样的事情,我表示很没有头绪,希望能解答一下。。。感激不尽
级别: 新手上路
UID: 9652
精华: 0
发帖: 20
金钱: 125 两
威望: 40 点
贡献值: 0 点
综合积分: 40 分
注册时间: 2009-10-09
最后登录: 2011-12-27
7楼  发表于: 2011-11-01 21:15
引用第6楼newton123于2011-09-26 22:39发表的  :
楼主这是在linux下啊。wince下做同样的事情,我表示很没有头绪,希望能解答一下。。。感激不尽

这个我也没有办法啊,wince我也不懂
级别: 新手上路
UID: 54580
精华: 0
发帖: 10
金钱: 50 两
威望: 10 点
贡献值: 0 点
综合积分: 20 分
注册时间: 2011-09-01
最后登录: 2012-05-06
8楼  发表于: 2012-04-03 13:48
实在是感谢楼主
[ 此帖被楚夕在2012-04-03 15:55重新编辑 ]
级别: 新手上路
UID: 54580
精华: 0
发帖: 10
金钱: 50 两
威望: 10 点
贡献值: 0 点
综合积分: 20 分
注册时间: 2011-09-01
最后登录: 2012-05-06
9楼  发表于: 2012-04-03 13:54
tcon &= ~0x0f00;
    tcon |= 0x0b00;
    __raw_writel(tcon, S3C2410_TCON);
    /*这里是我一直没有想明白的地方,为什么要把这一位清掉?还请知道的兄弟解答一下 */  
    tcon &= ~0x0200;
    __raw_writel(tcon, S3C2410_TCON);



这里需要两步操作
第一步是:设置为手动更新。因为第一次使用定时器时,需要设置“手动更新”位为1使TCNTBn与TCMTBn寄存器的值装入到TCNTn,TCMPn中。下一次如果要设置这一位,则需要请0
  • «
  • 1
  • 2
  • »
  • Pages: 1/2     Go