PCA的PWM
【摘要】
#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)