PCA的PWM

举报
ReCclay 发表于 2022/02/22 01:59:45 2022/02/22
【摘要】 #include "STC15W4K.H" // 包含STC15W4K寄存器定义文件 void main() { //占空比 = (1-CCAPnH/256)*100% //CCAPnH = (1 -...
#include "STC15W4K.H"   // 包含STC15W4K寄存器定义文件
void main()
{
//占空比 = (1-CCAPnH/256)*100%
//CCAPnH = (1 - 占空比)*256
// (1-0.875)*256 = 32 = 20H
//对应频率为 = SYSclk/12/256 = 22118400/12/256 =7.2K 
    CCAPM0=0x42;        // 设置PCA模块为PWM输出方式。
    CR=1;               // PCA计数器开始运行
    CCAP0H=0x20;        // 脉宽控制 87.5%
    while(1);           // 让程序停在这里。
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注意:使用PWM功能,单片机IO口会自动切换到强推挽输出模式,所以我们不需要对IO口进行配置,但是要注意强推挽意味输出电流大,不能短路了!!!

上面例子为配置寄存器为系统脉冲的分频,下面演示利用定时器T0溢出作为输入脉冲,进行PWM输出

#include "STC15W4K.H"       // 包含 "STC15W4K.H"寄存器定义头文件   
void initPCA()  
{
    // 初始化定时器T0为16位自动重装方式,其溢出脉冲作PCA计数器的时钟源
    TMOD=0x00;     // 设置T0为16位自动重装方式
    TH0=0xff;      // 定时时间19.53uS 
    TL0=0xDC;       
    TR0=1;         // 启动定时器0 
    // 初始化PCA模块1为PWM输出方式
    CMOD=0x84;     // #10000100B ,选择T0为PCA计数器时钟源
    CCAPM1=0x42;   // 设置PCA模块1为8位PWM输出方式。脉冲在P1.0引脚输出,PWM无需中断支持。
    CCAP1H=0x20;   // 设置脉冲宽度 
    EA=1;          // 开整个单片机所有中断共享的总中断控制位
    CR=1;          // 启动PCA计数器(CH,CL)计数
} 
void main (void)
{
    initPCA();
    while(1);       // 这里可以编写其它程序  
} 
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

使用T0计算定时器初值的方法总结:
所需PWM频率 = (1/定时时间)/256
定时时间 = 1/(256*所需PWM频率)
eg 所需200hz
1/(256*200) = 19.63125us
16位定时器12T的计算公式为
初值 = 65536 - SYSclk/12*T = 0xFFDC

下面是配置寄存器的渐变PWM输出

#include "STC15W4K.H"           // 包含STC15W4K寄存器定义文件
#define pulse_width_MAX 0xfa    // PWM脉宽最小值,占空比2.3%
#define pulse_width_MIN 0x05    // PWM脉宽最大值,占空比98%
#define STEP 0x02;              // PWM脉宽变化步长
unsigned char  pulse_width;     // PWM脉宽变量,即存入CCAP0H中的值

void delay(void)
{
   unsigned char i,j,k;
   for(i=10;i>0;i--)      // 注意后面没分号
   for(j=50;j>0;j--)     // 注意后面没分号
   for(k=255;k>0;k--);    // 注意后面有分号
} 
void port_mode()        // 端口模式
{
    P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
    P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00; 
}
void initPWM()
{
    CMOD=0x80;   // #10000000B   空闲模式下停止PCA计数器工作
                 // 选择PCA时钟源为Fosc/12,禁止PCA计数器溢出时中断
    CCON = 0;        // 清零PCA计数器溢出中断请求标志位CF
    // CR = 0, 不允许 PCA 计数器计数,清零PCA 各模块中断请求标志位CCFn 
    CL = 0;                 // 清零PCA 计数器
    CH = 0;  
    CCAPM0=0x42;           // 设置PCA模块0为PWM输出方式。
    CR=1;                  // PCA计数器开始运行
}
void PWM_OUT()
{
    // 占空比从最小到最大
    pulse_width=pulse_width_MIN;
    while(1)
    {
        if (pulse_width>pulse_width_MAX)    break;
        CCAP0H= pulse_width;
        pulse_width+=STEP; 
        delay();
    }
    // 占空比从最大到最小
    pulse_width=pulse_width_MAX;
    while(1)
    {
        if  (pulse_width<pulse_width_MIN) break;
        CCAP0H= pulse_width;
        pulse_width-=STEP;
        delay();    
    }
}  
void main()
{   
    port_mode();      // 所有IO口设为准双向弱上拉方式。
    initPWM();
    while(1)
    {
        PWM_OUT();            // 脉宽输出
    }           
}
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

下面是调T0实现可变PWM输出的例子

#include "STC15W4K.H"       // 包含 "STC15W4K.H"寄存器定义头文件   
#define T0_1 246            // 定时器TO重装值(10个脉冲溢出)
#define T0_2 236            // 定时器TO重装值(20个脉冲溢出)
#define PWM_PluseWidth 255  // PWM脉冲宽度,数字越大,脉宽越窄,占空比越小

void delay20ms(void)
{
   unsigned char i,j,k;
   for(i=2;i>0;i--)         // 注意后面没分号
   for(j=198;j>0;j--)       // 注意后面没分号
   for(k=150;k>0;k--);      // 注意后面有分号
}
void port_mode()            // 端口模式
{
    P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
    P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00; 
}
void initPCA()  
{
    // 初始化定时器T0为8位自动重装方式,其溢出脉冲作PCA计数器的时钟源
    TMOD=0x02;     // 设置T0为8位自动重装方式
    TH0=T0_1;      // 来256-246=10个脉冲就中断
    TL0=T0_1;      // 来256-246=10个脉冲就中断
    TR0=1;         // 启动定时器0 
    // 初始化PCA模块1为8位PWM输出方式
    CMOD=0x84;     // #10000100B   空闲模式下停止PCA计数器工作
                   // PCA时钟源选择T0溢出信号,禁止PCA计数器溢出时中断
    CCON=0;        // 清零PCA计数器溢出中断请求标志位CF
                   // CR = 0, 不允许 PCA 计数器计数,清零PCA 各模块中断请求标志位CCFn
    CL=0;          // 清零PCA 计数器 
    CH=0;  
    CCAPM1=0x42;   // 设置PCA模块1为8位PWM输出方式。脉冲在P1.0引脚输出,PWM无需中断支持。
    PCA_PWM1=0;                // 清0 PWM 模式下的第9位
    CCAP1H=PWM_PluseWidth;     // 设置脉冲宽度 

    EA=1;          // 开整个单片机所有中断共享的总中断控制位
    CR=1;          // 启动PCA计数器(CH,CL)计数
}

void main (void)
{
    port_mode();         // 所有IO口设为准双向弱上拉方式。
    initPCA();
    while(1)             // 等待中断
    {
        // P1.0 输出高频PWM极窄脉冲
        TH0=T0_1;      // 来256-246=10个脉冲就中断
        TL0=T0_1;      // 来256-246=10个脉冲就中断
        CCAP1H=PWM_PluseWidth;     // 设置脉冲宽度
        delay20ms(); 
        // P1.0 输出低频PWM极窄脉冲
        TH0=T0_2;      // 来256-236=20个脉冲就中断
        TL0=T0_2;      // 来256-236=20个脉冲就中断
        delay20ms();
        // P1.0 输出高频PWM窄脉冲
        TH0=T0_1;      // 来256-246=10个脉冲就中断
        TL0=T0_1;      // 来256-246=10个脉冲就中断
        CCAP1H=PWM_PluseWidth>>2;     // 设置脉冲宽度
        delay20ms(); 
        // P1.0 输出低频PWM窄脉冲
        TH0=T0_2;      // 来256-236=20个脉冲就中断
        TL0=T0_2;      // 来256-236=20个脉冲就中断
        delay20ms(); 
        //P1.0 输出高频PWM宽脉冲
        TH0=T0_1;      // 来256-246=10个脉冲就中断
        TL0=T0_1;      // 来256-246=10个脉冲就中断
        CCAP1H=PWM_PluseWidth>>4;     
        delay20ms(); 
        // P1.0 输出低频PWM宽脉冲
        TH0=T0_2;      // 来256-236=20个脉冲就中断
        TL0=T0_2;      // 来256-236=20个脉冲就中断
        delay20ms(); 
    }
} 


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76

文章来源: recclay.blog.csdn.net,作者:ReCclay,版权归原作者所有,如需转载,请联系作者。

原文链接:recclay.blog.csdn.net/article/details/76358981

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。