问天BlockSTC15单片机PWM输出讲解
Posted perseverance52
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了问天BlockSTC15单片机PWM输出讲解相关的知识,希望对你有一定的参考价值。
【问天Block】STC15单片机PWM输出讲解
-
示波器捕捉到的实时波形
-
采用的是自制开发板
-
我的开发板已经开源《【开源分享】自制STC15W408AS开发板》
-
开发工具:问天Block
-
采用的是字符编程方式,如果使用图像块编程频率是固定的11.0592MHz,我自制的STC15W408AS使用的是外部16MHz的晶振。
-
以PCA三路PWM输出范例参考
PWM频率调节
- 下面的函数是对时钟的分频,决定PWM的工作频率。
PCA_Clock_1T
频率最高,PCA_Clock_12T
频率最低。
PCA_InitStructure.PCA_Clock = PCA_Clock_1T; //PCA_Clock_1T, PCA_Clock_2T, PCA_Clock_4T, PCA_Clock_6T, PCA_Clock_8T, PCA_Clock_12T, PCA_Clock_Timer0_OF, PCA_Clock_ECI
-
PCA_Clock_1T
的频率:16MHz/256=62.5KHz;
(时钟频率采用的是外部晶振16MHz,)
-
PCA_Clock_12T = 16MHz/256/12=5208Hz
固定频率下的占空比调节
- 下面是关于占空比调整的函数,原函数调节的占空比是
0~100
占空比调整映射到0-254
之间不断变化的占空比值。注意:0对应的是最高占空比值,接近100%,254是最小占空比差不多为0.
void loop()
for (i = 0; i < 255; i = i + 1)
UpdatePwm(PCA0, i);
UpdatePwm(PCA1, i);
UpdatePwm(PCA2, i);
delay(50);
主程序代码
#define SYS_CLK 16000000L//设置时钟频率16MHz
#include <STC15X.h>
#include "lib/STC15_PCA.h"
#include "lib/STC15_delay.h"
uint8 i;
void setup()
PCA_InitTypeDef PCA_InitStructure;
PCA_InitStructure.PCA_Clock = PCA_Clock_12T; //PCA_Clock_1T, PCA_Clock_2T, PCA_Clock_4T, PCA_Clock_6T, PCA_Clock_8T, PCA_Clock_12T, PCA_Clock_Timer0_OF, PCA_Clock_ECI
PCA_InitStructure.PCA_IoUse = PCA_P11_P10_P37; //PCA_P12_P11_P10_P37, PCA_P34_P35_P36_P37, PCA_P24_P25_P26_P27
PCA_InitStructure.PCA_Interrupt_Mode = DISABLE; //ENABLE, DISABLE
PCA_InitStructure.PCA_Polity = PolityHigh; //优先级设置 PolityHigh,PolityLow
PCA_InitStructure.PCA_RUN = DISABLE; //ENABLE, DISABLE
PCA_Init(PCA_Counter,&PCA_InitStructure);
PCA_InitStructure.PCA_Mode = PCA_Mode_PWM; //PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutput
PCA_InitStructure.PCA_PWM_Wide = PCA_PWM_8bit; //PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bit
PCA_InitStructure.PCA_Interrupt_Mode = DISABLE; //PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLE
PCA_InitStructure.PCA_Value = 100 << 8; //对于PWM,高8位为PWM占空比
PCA_Init(PCA0,&PCA_InitStructure);
PCA_InitStructure.PCA_Mode = PCA_Mode_PWM; //PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutput
PCA_InitStructure.PCA_PWM_Wide = PCA_PWM_8bit; //PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bit
PCA_InitStructure.PCA_Interrupt_Mode = DISABLE; //PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLE
PCA_InitStructure.PCA_Value = 100 << 8; //对于PWM,高8位为PWM占空比
PCA_Init(PCA1,&PCA_InitStructure);
PCA_InitStructure.PCA_Mode = PCA_Mode_PWM; //PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutput
PCA_InitStructure.PCA_PWM_Wide = PCA_PWM_8bit; //PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bit
PCA_InitStructure.PCA_Interrupt_Mode = DISABLE; //PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLE
PCA_InitStructure.PCA_Value = 100 << 8; //对于PWM,高8位为PWM占空比
PCA_Init(PCA2,&PCA_InitStructure);
CR = 1; //1: 允许PCA计数器计数,必须由软件清0。
//PCA三路输出PWM
void loop()
for (i = 0; i < 250; i = i + 1)
UpdatePwm(PCA0, i);
UpdatePwm(PCA1, i);
UpdatePwm(PCA2, i);
delay(50);
void main(void)
setup();
while(1)
loop();
STC15_PCA.h
文件
#ifndef __STC15_PCA_H
#define __STC15_PCA_H
#include <STC15X.h>
#define TRUE 1
#define FALSE 0
//=============================================================
//========================================
#define PolityLow 0 //低优先级中断
#define PolityHigh 1 //高优先级中断
#define ENABLE 1
#define DISABLE 0
#define PCA0 0
#define PCA1 1
#define PCA2 2
#define PCA_Counter 3
#define PCA_P11_P10_P37 (0<<4)
#define PCA_P35_P36_P37 (1<<4)
#define PCA_P25_P26_P27 (2<<4)
#define PCA_Mode_PWM 0x42 //B0100_0010
#define PCA_Mode_Capture 0
#define PCA_Mode_SoftTimer 0x48 //B0100_1000
#define PCA_Mode_HighPulseOutput 0x4c //B0100_1100
#define PCA_Clock_1T (4<<1)
#define PCA_Clock_2T (1<<1)
#define PCA_Clock_4T (5<<1)
#define PCA_Clock_6T (6<<1)
#define PCA_Clock_8T (7<<1)
#define PCA_Clock_12T (0<<1)
#define PCA_Clock_Timer0_OF (2<<1)
#define PCA_Clock_ECI (3<<1)
#define PCA_Rise_Active (1<<5)
#define PCA_Fall_Active (1<<4)
#define PCA_PWM_8bit (0<<6)
#define PCA_PWM_7bit (1<<6)
#define PCA_PWM_6bit (2<<6)
typedef struct
uint8 PCA_IoUse; //PCA_P12_P11_P10_P37, PCA_P34_P35_P36_P37, PCA_P24_P25_P26_P27
uint8 PCA_Clock; //PCA_Clock_1T, PCA_Clock_2T, PCA_Clock_4T, PCA_Clock_6T, PCA_Clock_8T, PCA_Clock_12T, PCA_Clock_Timer0_OF, PCA_Clock_ECI
uint8 PCA_Mode; //PCA_Mode_PWM, PCA_Mode_Capture, PCA_Mode_SoftTimer, PCA_Mode_HighPulseOutput
uint8 PCA_PWM_Wide; //PCA_PWM_8bit, PCA_PWM_7bit, PCA_PWM_6bit
uint8 PCA_Interrupt_Mode; //PCA_Rise_Active, PCA_Fall_Active, ENABLE, DISABLE
uint8 PCA_Polity; //优先级设置 PolityHigh,PolityLow
uint16 PCA_Value;
uint8 PCA_RUN; //ENABLE, DISABLE
PCA_InitTypeDef;
bit B_Capture0,B_Capture1,B_Capture2;
uint8 PCA0_mode,PCA1_mode,PCA2_mode;
uint16 CCAP0_tmp,PCA_Timer0;
uint16 CCAP1_tmp,PCA_Timer1;
uint16 CCAP2_tmp,PCA_Timer2;
/************* 功能说明 **************
******************************************/
//========================================================================
// 函数: UpdatePwm(uint8 PCA_id, uint8 pwm_value)
// 描述: 更新PWM值.
// 参数: PCA_id: PCA序号. 取值 PCA0,PCA1,PCA2,PCA_Counter
// pwm_value: pwm值, 这个值是输出低电平的时间.
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void UpdatePwm(uint8 PCA_id, uint8 pwm_value)
if(PCA_id == PCA0) CCAP0H = pwm_value;
else if(PCA_id == PCA1) CCAP1H = pwm_value;
else if(PCA_id == PCA2) CCAP2H = pwm_value;
//========================================================================
// 函数: void PCA_Init(PCA_id, PCA_InitTypeDef *PCAx)
// 描述: PCA初始化程序.
// 参数: PCA_id: PCA序号. 取值 PCA0,PCA1,PCA2,PCA_Counter
// PCAx: 结构参数,请参考PCA.h里的定义.
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void PCA_Init(uint8 PCA_id, PCA_InitTypeDef *PCAx)
if(PCA_id > PCA_Counter) return; //id错误
if(PCA_id == PCA_Counter) //设置公用Counter
CR = 0;
CH = 0;
CL = 0;
AUXR1 = (AUXR1 & ~(3<<4)) | PCAx->PCA_IoUse; //切换IO口
CMOD = (CMOD & ~(7<<1)) | PCAx->PCA_Clock; //选择时钟源
CMOD = (CMOD & ~1) | (PCAx->PCA_Interrupt_Mode & 1); //ECF
if(PCAx->PCA_Polity == PolityHigh) PPCA = 1; //高优先级中断
else PPCA = 0; //低优先级中断
if(PCAx->PCA_RUN == ENABLE) CR = 1;
return;
PCAx->PCA_Interrupt_Mode &= (3<<4) + 1;
if(PCAx->PCA_Mode >= PCA_Mode_SoftTimer) PCAx->PCA_Interrupt_Mode &= ~(3<<4);
if(PCA_id == PCA0)
CCAPM0 = PCAx->PCA_Mode | PCAx->PCA_Interrupt_Mode; //工作模式, 中断模式
PCA_PWM0 = (PCA_PWM0 & ~(3<<6)) | PCAx->PCA_PWM_Wide; //PWM宽度
PCA_Timer0 = PCAx->PCA_Value;
B_Capture0 = 0;
PCA0_mode = PCAx->PCA_Mode;
CCAP0_tmp = PCA_Timer0;
CCAP0L = (uint8)CCAP0_tmp; //将影射寄存器写入捕获寄存器,先写CCAP0L
CCAP0H = (uint8)(CCAP0_tmp >> 8); //后写CCAP0H
if(PCA_id == PCA1)
CCAPM1 = PCAx->PCA_Mode | PCAx->PCA_Interrupt_Mode;
PCA_PWM1 = (PCA_PWM1 & ~(3<<6)) | PCAx->PCA_PWM_Wide;
PCA_Timer1 = PCAx->PCA_Value;
B_Capture1 = 0;
PCA1_mode = PCAx->PCA_Mode;
CCAP1_tmp = PCA_Timer1;
CCAP1L = (uint8)CCAP1_tmp; //将影射寄存器写入捕获寄存器,先写CCAP0L
CCAP1H = (uint8)(CCAP1_tmp >> 8); //后写CCAP0H
if(PCA_id == PCA2)
CCAPM2 = PCAx->PCA_Mode | PCAx->PCA_Interrupt_Mode;
PCA_PWM2 = (PCA_PWM2 & ~(3<<6)) | PCAx->PCA_PWM_Wide;
PCA_Timer2 = PCAx->PCA_Value;
B_Capture2 = 0;
PCA2_mode = PCAx->PCA_Mode;
CCAP2_tmp = PCA_Timer2;
CCAP2L = (uint8)CCAP2_tmp; //将影射寄存器写入捕获寄存器,先写CCAP0L
CCAP2H = (uint8)(CCAP2_tmp >> 8); //后写CCAP0H
//========================================================================
// 函数: void PCA_Handler (void) interrupt PCA_VECTOR
// 描述: PCA中断处理程序.
// 参数: None
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void PCA_Handler (void) interrupt 7
if(CCF0) //PCA模块0中断
CCF0 = 0; //清PCA模块0中断标志
if(PCA0_mode >= PCA_Mode_SoftTimer) //PCA_Mode_SoftTimer and PCA_Mode_HighPulseOutput
CCAP0_tmp += PCA_Timer0;
CCAP0L = (uint8)CCAP0_tmp; //将影射寄存器写入捕获寄存器,先写CCAP0L
CCAP0H = (uint8)(CCAP0_tmp >> 8); //后写CCAP0H
else if(PCA0_mode == PCA_Mode_Capture)
CCAP0_tmp = CCAP0H; //读CCAP0H
CCAP0_tmp = (CCAP0_tmp << 8) + CCAP0L;
B_Capture0 = 1;
if(CCF1) //PCA模块1中断
CCF1 = 0; //清PCA模块1中断标志
if(PCA1_mode >= PCA_Mode_SoftTimer) //PCA_Mode_SoftTimer and PCA_Mode_HighPulseOutput
CCAP1_tmp += PCA_Timer1;
CCAP1L = (uint8)CCAP1_tmp; //将影射寄存器写入捕获寄存器,先写CCAP0L
CCAP1H = (uint8)(CCAP1_tmp >> 8); //后写CCAP0H
else if(PCA1_mode == PCA_Mode_Capture)
CCAP1_tmp = CCAP1H; //读CCAP1H
CCAP1_tmp = (CCAP1_tmp << 8) + CCAP1L;
B_Capture1 = 1;
if(CCF2) //PCA模块2中断
CCF2 = 0; //清PCA模块1中断标志
if(PCA2_mode >= PCA_Mode_SoftTimer) //PCA_Mode_SoftTimer and PCA_Mode_HighPulseOutput
CCAP2_tmp += PCA_Timer2;
CCAP2L = (uint8)CCAP2_tmp; //将影射寄存器写入捕获寄存器,先写CCAP0L
CCAP2H = (uint8)(CCAP2_tmp >> 8); //后写CCAP0H
else if(PCA2_mode == PCA_Mode_Capture)
CCAP2_tmp = CCAP2H; //读CCAP2H
CCAP2_tmp = (CCAP2_tmp << 8) + CCAP2L;
B_Capture2 = 1;
if(CF) //PCA溢出中断
CF = 0; //清PCA溢出中断标志
#endif
STC15_delay.h
文件
#ifndef __STC15_DELAY_H
#define __STC15_DELAY_H
#include <STC15X.h>
#ifndef SYS_CLK
#define SYS_CLK 11059200L
#endif
void delay1ms(); //延迟1毫秒
void delay(uint16 time); //延迟time毫秒
#if (SYS_CLK == 24000000)
void delay1us(); //延迟1微秒
void delay5us(); //延迟5微秒
void delay10us(); //延迟10微秒
void delay50us(); //延迟50微秒
void delay100us(); //延迟100微秒
//========================================================================
// 描述: 延迟1微秒.
// 参数: none.
// 返回: none.
//========================================================================
void delay1us() //@24.000MHz
uint8 i;
_nop_();
_nop_();
i = 3;
while (--i);
//========================================================================
// 描述: 延迟5微秒.
// 参数: none.
// 返回: none.
//========================================================================
void delay5us() //@24.000MHz
uint8 i;
_nop_();
_nop_();
i = 27;
while (--i);
//========================================================================
// 描述: 延迟10微秒.
// 参数: none.
// 返回: none.
//========================================================================
void delay10us() //@24.000MHz
uint8 i;
_nop_();
_nop_();
i = 57;
while (--i);
//========================================================================
// 描述: 延迟50微秒.
// 参数: none.
// 返回: none.
//========================================================================
void delay50us() //@24.000MHz
uint8 i, j;
i = 2;
j = 39;
do
while (--j);
以上是关于问天BlockSTC15单片机PWM输出讲解的主要内容,如果未能解决你的问题,请参考以下文章
11.STC15W408AS单片机CCP/PCA/PWM应用
11.STC15W408AS单片机CCP/PCA/PWM应用
11.STC15W408AS单片机CCP/PCA/PWM应用