📄 pwm.c
字号:
//编程时间:07-5-16
#include<pic.h>
/////////////////////////////////////////
//--------------端口定义---------------//
/////////////////////////////////////////
//#define PWM1 RC2
//#define PWM2 RC1
///////////////////////////////////////
//-------------数据定义--------------//
///////////////////////////////////////
static char CCP1_NUMBER,CCP2_NUMBER;//CCP输出方波计数值
static char CCP1EN,CCP2EN,DOWNEN,TIMERNUMBER,TIMERNUMBER_IN;//CCP1 CCP2产生方波使能位
///////////////////////////////////////
//--------------函数定义-------------//
///////////////////////////////////////
void initccp(); //PWM初始值设置
void initvar(); //数据初试值初试化
void initt2(); //T2初试化
void delay1(); //延时程序
/******************************************
//-------------------主函数----------------
******************************************/
void main()
{
TRISC=0X00; //CCP端口输出
TRISB=0X02; //B口输出,指示灯使用,RB1键盘输入
initvar(); //数据初试值初试化
initt2(); //T2初试化
initccp(); //CCP模块初试化
TMR2ON=1; //打开定时器T2
while(1)
{
RB0=0; //LED闪烁,程序执行标志
delay1();
RB0=1;
delay1();
if(RB1==0)
{
while(RB1==1);
DOWNEN=1; //低电平输出使能位
TIMERNUMBER=TIMERNUMBER+2;//每次按下按键则在低电平延时时间增加大概1.1MS
if(TIMERNUMBER>55) //当低电平时间增加到30MS的时候,清零为20MS低电平
//按键9次即可以恢复到20MS的低电平值,在次也可以再增加一个按键来单独设定低电平输出时间值
{
TIMERNUMBER=36;
}
}
}
}
/*****************************************
---------------------中断函数-------------
*****************************************/
void interrupt ISR()
{
if(TMR2IF&&TMR2IE)
{
TMR2IF=0;
if((CCP1EN==1)&&(DOWNEN==0)) //当CCP1使能即输出上半波
{
CCPR2L=0;//CCP2输出占空比为0的波型,即为不输出
CCP1_NUMBER=CCP1_NUMBER+1;//CCP1波型个数开始计数
switch(CCP1_NUMBER)
{
case 1: CCPR1L=0x18; //占空比15% 00
break;
case 2: CCPR1L=0x30; //30% 01
break;
case 3: CCPR1L=0x48; //45% 01
break;
case 4: CCPR1L=0x5e; //58% 00
break;
case 5: CCPR1L=0x71; //71% 11
break;
case 6: CCPR1L=0x81; //80% 01
break;
case 7: CCPR1L=0x8e; //89% 00
break;
case 8: CCPR1L=0x98; //95% 01
break;
case 9: CCPR1L=0x9e; //98% 00
break;
case 10: CCPR1L=0xa0; //100% 11
break;
case 11: CCPR1L=0x9e;
break;
case 12: CCPR1L=0x98;
break;
case 13: CCPR1L=0x8e;
break;
case 14: CCPR1L=0x81;
break;
case 15: CCPR1L=0x71;
break;
case 16: CCPR1L=0x5e;
break;
case 17: CCPR1L=0x48;
break;
case 18: CCPR1L=0x30;
break;
case 19: CCPR1L=0x18;
break;
}
if(CCP1_NUMBER==19)
//当输出19个方波重新计数
{
CCP1_NUMBER=0; //清除计数值
CCP2EN=1; //打开CCP2使能位
CCP1EN=0; //清除CCP1使能位
}
}
if((CCP2EN==1)&&(DOWNEN==0))//当CCP2使能即输出上半波
{
CCPR1L=0;//CCP1输出占空比为0的波型,即为不输出
CCP2_NUMBER=CCP2_NUMBER+1;//CCP2波型个数开始计数
switch(CCP2_NUMBER)
{
case 1: CCPR2L=0x18; //占空比15% 00
break;
case 2: CCPR2L=0x30; //30% 01
break;
case 3: CCPR2L=0x48; //45% 01
break;
case 4: CCPR2L=0x5e; //58% 00
break;
case 5: CCPR2L=0x71; //71% 11
break;
case 6: CCPR2L=0x81; //80% 01
break;
case 7: CCPR2L=0x8e; //89% 00
break;
case 8: CCPR2L=0x98; //95% 01
break;
case 9: CCPR2L=0x9e; //98% 00
break;
case 10: CCPR2L=0xa0; //100% 11
break;
case 11: CCPR2L=0x9e;
break;
case 12: CCPR2L=0x98;
break;
case 13: CCPR2L=0x8e;
break;
case 14: CCPR2L=0x81;
break;
case 15: CCPR2L=0x71;
break;
case 16: CCPR2L=0x5e;
break;
case 17: CCPR2L=0x48;
break;
case 18: CCPR2L=0x30;
break;
case 19: CCPR2L=0x18;
break;
}
if(CCP2_NUMBER==19)//当输出19个方波重新计数
{
CCP2_NUMBER=0;//清除计数值
CCP1EN=1;//打开CCP1使能位
CCP2EN=0;//清除CCP12使能位
}
}
if(DOWNEN==1)//屏蔽波型输入
{
CCPR1L=0;//CCP1输出占空比为0的波型,即为低电平
CCPR2L=0;//CCP2输出占空比为0的波型,即为低电平
TIMERNUMBER_IN=TIMERNUMBER_IN+1; //内部低电平时间计数,单位位560US
if(TIMERNUMBER_IN==TIMERNUMBER)//当低电平时间等于外部按键设置的时间时则恢复波型
{
DOWNEN=0;//输出低电平使能位
TIMERNUMBER_IN=0;//低电平时间值清零
}
}
}
}
/*****************************************
//函数名称:void initvar()
//函数功能:PWM初始值设置
//函数调用:主函数调用
*****************************************/
void initccp()
{
PR2=0xa3; //526.3us=(PR2+1)*0.2*16
CCPR1L=0x18; //占空比15%
CCP1CON=0x1C; //PWM模式 低2位为01
CCPR2L=0x18; //占空比15%
CCP2CON=0x1C; //PWM模式 低2位为01
T2CON=0X06; //0111 1100 16分频,打开T2
TMR2IE=1;//打开T2中断允许位
}
/*****************************************
//函数名称:void initvar()
//函数功能:为系统调用值赋初值
//函数调用:主函数调用
*****************************************/
void initvar()
{
CCP1_NUMBER=0;//CCP方波计数值清零
CCP2_NUMBER=0;
CCP1EN=1;//系统初始化时先给CCP1使能,输出第一列方波
CCP2EN=0;//不输出第二列方波
DOWNEN=0;//CCP输出低电平标志位
TIMERNUMBER=36;//输出大约20MS的低电平
TIMERNUMBER_IN=0;
}
/*****************************************
//函数名称:void initt1()
//函数功能:T1初试化
//函数调用:主函数调用
*****************************************/
void initt2()
{
INTCON=0xC0; //打开总中断和外围中断
PIE1=0x02;
//T1CON=0x80; //0000 0001做内部定时器
TMR2IF=0;
//TMR1H=0xFd;//初试值为526.3us,方波周期
//TMR1L+=0x17;
}
void delay1()
{
int i;
for(i=6000;i>10;i--);
}
///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -