查看: 877|回复: 0
收起左侧

risc-v Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2020-8-24 23:21:36 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 皋陶 于 2020-8-25 18:02 编辑

    RISC-V Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速 电机调速 占空比
    risc-v Sifive learn inventor基础之硬件pwm

    目录


    risc-v Sifive learn inventor基础之串口
    继串口之后,继续来通过寄存器操作硬件pwm,熟悉操作寄存器的流程。
    因为sifive官方没有提供pwm的库函数,所以必须根据芯片手册配置寄存器来开发pwm。这是练习操作寄存器的好机会!



    错误修改

    2020.7.24
    修改了示例应用中,pwm占空比为1/5;多谢指正;
    之前关于pwmcount,scale与pwms的关系搞错了,正确的关系是pwms=pwmcount/scale。耽误各位了


    一,硬件连接

    在入门手册中可以知道,在金手指上,gpio2接到小车上的右边电机且控制电机正转。在芯片手册的gpio章节,可以找到gpio2的复用功能1中对应的是pwm0_cmp2,所以要操作的就是pwmcmp2输出pwm波。


    国内芯片技术交流-risc-v Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速risc-v单片机中文社区(1)

    国内芯片技术交流-risc-v Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速risc-v单片机中文社区(2)


    二,pwm

    e310有三个pwm控制器,我们需要操作的是pwm0。


    一个pwm控制器的寄存器如下:


    pwmcfg:配置pwm


    pwmcount:pwm计数寄存器


    pwms:保存pwmcount经过放大后的值,这个寄存器用来与pwmcmpX寄存器比较,从而产生pwm波。



    国内芯片技术交流-risc-v Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速risc-v单片机中文社区(3)


    1,pwmcfg
    • pwmscale:pwmcount的扩大倍数 ;pwmscale∈(0-15);扩大倍数:20—>215;
    • pwmsticky和pwmdeglitch:是与pwm中断相关的,是用来防止当改变cmpX的值时,中断再次触发。
    • pwmzero :为1时,当pwms==cmp0时,pwmcount会重置。但是在开发过程中,我发现这个位无法被置一,当向bit 9写1时,bit 10置1,而bit 9保持0 最后发现这个不会影响pwmzero的功能。
    • pwmcmpXcenter: 用来设置pwm的中央对齐模式
    • pwmXgang: 设置pwm轮流产生信号。
    • pwmcmpXip:中断标志位

    国内芯片技术交流-risc-v Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速risc-v单片机中文社区(4)


    2,pwms与pwmcmpx
    pwms的值就是pwmcount的值缩小2^n倍,n=scale,n∈【0,15】。缩放后的值与pwmcmpX寄存器里的值比较,产生pwm波。当pwms>pwmcmpX 时,gpioX输出高电平。



    国内芯片技术交流-risc-v Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速risc-v单片机中文社区(5)


    pwmcpmX的最大值与cmpwdith有关,如图不同pwm控制器有不一样的cmpwdith,如pwm0的cmpwdith=8,pwmcmpX寄存器就只能设置8位,也就是0->255,pwm1的cmpwdith=16,pwmcmpX范围0->2^16-1。这一点在编程时需要注意传递的参数不能超出范围。


    国内芯片技术交流-risc-v Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速risc-v单片机中文社区(6)



    二,代码编写

    了解了寄存器的功能后,就可以通过代码来操作寄存器实现所需的功能了。可见,通过scale可以设置pwms的时钟频率(pwm时钟频率是16MHZ),设置pwmcmp0可以设置pwm的周期,再通过设置pwmcmpX调节pwm的占空比。


    首先设置gpio2,输出使能,复用功能1,配置pwmcfg寄存器,保险起见,先清零,再设置scale


    注意,pwmenalways必须在pwmzerocmp之前置位,若pwmzerocmp先置位,则pwmenalways设置为1时,pwmzerocmp会被清零!


    最后清零所有cmp寄存器,然后设置cmp0的值,这样初始化了周期,cmp1-cmp3的输出全是高电平。


    1. #include "pwm.h"
    2. /*
    3. * 设置pwm0占空比
    4. * cmp_num :0->3
    5. * 通过设置pwmcmp0可以设置周期,cmpx>pwms 低电平
    6. * cmp 【0,155】这是由于pwmdwith=8
    7. */
    8. int pwm0_setcmp(int cmp_num,char cmp){
    9.         if(cmp_num==0){
    10.                 PWM0_CMP0 &=0;
    11.                 PWM0_CMP0|=cmp;
    12.         }
    13.         else if(cmp_num==1){
    14.                 PWM0_CMP1 &=0;
    15.                 PWM0_CMP1|=cmp;
    16.         }
    17.         else if(cmp_num==2){
    18.                 PWM0_CMP2 &=0;
    19.                 PWM0_CMP2|=cmp;
    20.         }
    21.         else if(cmp_num==3){
    22.                 PWM0_CMP3 &=0;
    23.                 PWM0_CMP3|=cmp;
    24.         }
    25. }
    26. /*
    27. * pwm初始化
    28. *  假设时钟周期设为64M
    29. * 周期 = (250*2^scale)/64 us=2^scale*3.90625
    30. *int scale (0-15)时钟分频系数 scale=7时,T=500us
    31. */
    32. void pwm_init(int scale){

    33.         //GPIO2->PWM0CMP2
    34.         GPIO0_IOF_EN |=(1<<2);//enable gpio2 iof
    35.         GPIO0_IOF_SEL |=(1<<2); //select iof 1

    36.         //配置cfg寄存器
    37.         PWM0_CFG &=0;//clear cfg
    38.         PWM0_CFG |=scale;//set scale=0
    39.         PWM0_CFG |=(1<<12);//set pwmenalways 1 ;note:this must be done before pwmzeorcmp
    40.         PWM0_CFG |=(1<<9);//set pwmzero 1

    41.         //init the cmpx value
    42.         pwm0_setcmp(0,250);
    43.         pwm0_setcmp(1,250);
    44.         pwm0_setcmp(2,250);
    45.         pwm0_setcmp(3,250);
    46. }
    复制代码


    寄存器相关宏定义

    1. #define PWM0_CFG (__METAL_ACCESS_ONCE((__metal_io_u32 *)(METAL_SIFIVE_PWM0_0_BASE_ADDRESS + METAL_SIFIVE_PWM0_PWMCFG)))
    2. #define PWM0_CMP0 (__METAL_ACCESS_ONCE((__metal_io_u32 *)(METAL_SIFIVE_PWM0_0_BASE_ADDRESS + METAL_SIFIVE_PWM0_PWMCMP0)))
    3. #define PWM0_CMP1 (__METAL_ACCESS_ONCE((__metal_io_u32 *)(METAL_SIFIVE_PWM0_0_BASE_ADDRESS + METAL_SIFIVE_PWM0_PWMCMP1)))
    4. #define PWM0_CMP2 (__METAL_ACCESS_ONCE((__metal_io_u32 *)(METAL_SIFIVE_PWM0_0_BASE_ADDRESS + METAL_SIFIVE_PWM0_PWMCMP2)))
    5. #define PWM0_CMP3 (__METAL_ACCESS_ONCE((__metal_io_u32 *)(METAL_SIFIVE_PWM0_0_BASE_ADDRESS + METAL_SIFIVE_PWM0_PWMCMP3)))
    复制代码


    示例应用
    设置pwm周期500us 占空比1/5

    1. __metal_driver_sifive_fe310_g000_pll_init(&__metal_dt_clock_4);//clock 64mhz
    2. metal_clock_set_rate_hz(&__metal_dt_clock_4.clock,64000000);
    3. //当scale=7 PWM周期500us
    4. pwm_init(7);
    5. pwm0_setcmp(2,200);
    复制代码


    三,小结


    以pwm0为例,其他的pwm也大致可以依样画葫芦。这次用逻辑分析仪,能明显清晰的看到pwm的周期和占空比,通过不断调试pwmcfg,最后找到规律。同时实践了操作寄存器的方法。编写了reg.h,方便操作寄存器。


    作者学识短浅,如有错误的地方,望不吝赐教,如果我的博客对你有帮助,记得点赞收藏哦!

    国内芯片技术交流-risc-v Sifive learn inventor基础之硬件pwm&寄存器HifiveRev B pwm调速risc-v单片机中文社区(7)


    本篇完,感谢关注:RISC-V单片机中文网




    上一篇:初学risc-v,入门了解R-type,I-type,S-type
    下一篇:阅读日记:computer organization and design——RISC-V——preface
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-18 18:47 , Processed in 0.921347 second(s), 48 queries .

    快速回复 返回顶部 返回列表