• AT91-PWM应用


    步骤1:

    make menuconfig配置内核, 开启PWM输出功能.

    1. Device Drivers --->  
    2.   Misc devices  --->  
    3.     <*>Atmel AT32/AT91 PWM support  
    4.   [*] LEDSupport  --->  
    5.     <*>   LED Support usingAtmel PWM outputs  


    步骤2:

    修改arch/arm/mach-at91/board-sam9m10g45ek.c

    1. static struct gpio_ledek_pwm_led[] = {  
    2. #ifdefined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE)  
    3.     {  /* "right" led, green, userled1, pwm1 */  
    4.         .name           = "d7",  
    5.         .gpio           = 1<< AT91_PWM1,    /* is PWM channel number */  
    6.         .active_low     = 1,  
    7.         .default_trigger    = "none",  
    8.     },  
    9. #endif  
    10. };  

    ----------------------------------------

    修改.gpio成员指定PWM通道, AT91SAM9G45一共有四个PWM通道.

     

    步骤3:

    编译内核, 下载烧写. 如果一切顺利, 输入下列命令即可从PD31输出越100Hz的方波.

    1. echo 127 > /sys/class/leds/pd7/brightness  

    占空比为127/256 ≈ 49.6%

     

    步骤4:

    为了修改PWM输出频率, 我们现在分析下驱动源码.

    打开驱动文件"drivers/leds/leds-atmel-pwm.c",找到pwmled_probe()函数, 重点关注下面几条语句

    1. tmp = 5;  
    2. if (!led->active_low)  
    3.     tmp |= PWM_CPR_CPOL;  
    4. pwm_channel_writel(&led->pwmc,PWM_CMR, tmp);  
    5.    
    6. /* 
    7.  * Pick a period so PWM cycles at 100+ Hz; anda multiplier 
    8.  * for scaling duty cycle:  brightness * mult. 
    9.  */  
    10. tmp = (led->pwmc.mck / (1 << 5))/ 100;  
    11. tmp /= 255;  
    12. led->mult = tmp;  
    13. pwm_channel_writel(&led->pwmc,PWM_CDTY,  
    14.         led->cdev.brightness * 255);  
    15. pwm_channel_writel(&led->pwmc,PWM_CPRD,  
    16.         LED_FULL * tmp);  

    --------------------------------

    a.led->pwmc.mck = 133333333, 外部总线时钟

    b.标蓝部分设置的是PWM模块的时钟分频系数, 参照手册PWM_CMR设置得知tmp=5(二进制0101)为MCK/32

    c.tmp = (led->pwmc.mck / (1 << 5))/ 100;

    这里的100为将要设置的目标频率. 如果分频系数为5, 那么最大可达到的目标频率约为16kHz.

     

    好的, 我们已经找到了这两个关键的设置点, 下面以设置PWM输出38kHz为例, 计算参数

    CPRD= 总线时钟/分频系数/目标频率

     
    由上表可以看出, 分频系数2的小数部分最小, 误差也最小, 为最优选择. 但最终的目标频率不是精确的38kHz, 有误差的哟请务必注意.

     

    代码如下

    1. tmp = 2;  
    2. if (!led->active_low)  
    3.     tmp |= PWM_CPR_CPOL;  
    4. pwm_channel_writel(&led->pwmc,PWM_CMR, tmp);  
    5.    
    6. /* 
    7.  * Pick a period so PWM cycles at 100+ Hz; anda multiplier 
    8.  * for scaling duty cycle:  brightness * mult. 
    9.  */  
    10. tmp = (led->pwmc.mck / (1 << 2))/38000;  
    11. tmp /= 255;  
    12. led->mult = tmp;  
    13. pwm_channel_writel(&led->pwmc,PWM_CDTY,  
    14.         led->cdev.brightness * 255);  
    15. pwm_channel_writel(&led->pwmc,PWM_CPRD,  
    16.         LED_FULL * tmp);  


  • 相关阅读:
    C++---拷贝构造函数和赋值构造函数
    C++---类成员变量定义为引用
    从文件处理到文件的高级应用
    Jupyter的使用复习
    字符编码到python编辑器流程
    周四的小结
    中秋前的题目
    三段代码块带走今天的脚本
    今日份的随笔
    明天才能学的运算符号表格
  • 原文地址:https://www.cnblogs.com/zym0805/p/5992249.html
Copyright © 2020-2023  润新知