1、 写了一个简单的PWM程序,给初学者,PWM+数字电表 用QL200的VR1作输入来调节占空比,并用D10,D11来显示VR1输入到RA0的电压, ////////////////////////////////////////////////// // Author : Toby // Date : 2009/01/21 // Function : 程序用于使CCP1模块产生分辨率为10位的PWM波形,占空比可调, // MCU : PIC16F877A // C Compiler : PICC 8.05
2、// IDE : MPLAB IDE v8.10
/////////////////////////////////////////////////
#include
3、TABLE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0X82,0XF8,0X80,0X90}; //定义常数0-9的数据表格 void CCP1INIT(void); void interrupt clkint(void); void adinitial_voltage(void); void display_voltage(void); void ini(void); void delay(unsigned char x); unsigned char QC,TONOFF=5; unsigned int ad_data=0; /
4、/主程序 main() { ini(); CCP1INIT(); //CCP1模块的PWM工作方式初始化 T2CON=4; //打开TMR2,且使其前预分频为1:1,后分频比为1:1,但在这个程序中后分频比用不上 while(1) { CCPR1L=TONOFF; //CCPR1L与DC1B1与DC1B0共同组成占空比的可调范围,以当前程序为例,则占空比为DC1B<9:0)*Tosc*TMR2预分频 QC=0; displa
5、y_voltage(); adinitial_voltage(); } } void CCP1INIT() //CCP1模块的PWM工作方式初始化子程序*/ { CCP1CON=0X3C; //设置CCP1模块为PWM工作方式,且其占它比的低两位DC1B1与DC1B0为11 INTCON=0X00; //禁止总中断和外围中断 PR2=150; //设置PWM的工作周期,也即PWM的工作频率 其中PWM周期=(PR2+1)*4*Tosc*TMR2预分频比,Tosc为MCU的振荡周期
6、 //以当前程序为例,则PWM的输出频为 1/{(156+1)*4*0.25us(4M晶体)*1}=6.3694267515923566878980891719745k TRISC=RC2=0; //设置CCP1引脚为输出方式 } //A/D转化初始化子程序 void adinitial_voltage(void) { unsigned char a=50; ad_data=0; for(a;a--;) { ADCON0=0B01000001; //A/D 转换器
7、模块工作;但AD转换不进行;FOSC/8 ADCON1=0B11100000; //ADRESH 寄存器的高6 位读为0;6位与7位须置1 ADIF=0; //AD转换中断标志先清出。 while(ADGO); adresult.adre[0]=ADRESL; adresult.adre[1]=ADRESH; //读取并存储A/D转换结果 ad_data+=adresult.y1; ADGO=1; } ad_data/=50; }
8、 void display_voltage(void) //电压显示函数 { int bai,shi,ge,qian,temp,change; //定义6个临时变量 temp=ad_data/208.97959183673469387755102040816*1000; //10位AD=1024,我的电源电压为4.9V,所心1024/4.9=208.9=209 TONOFF=(ad_data/208.97959183673469387755102040816)*
9、25.000; change=temp; qian=temp/1000; //求显示的千位 bai=temp%1000/100; //求显示的百位 shi=(temp%100)/10; //求显示的十位 ge=temp%10; //求显示的个位 change=TABLE[qian]&0x7f; //显示一个小数点 PORTD=change; PORTA=0
10、B1111011; //RA2输出低电平,点亮千位显示 delay(1); PORTD=TABLE[bai]; //查表得百位显示的代码 PORTA=0x37; //RA3输出低电平,点亮百位显示 delay(1); //延时一定时间,保证显示亮度 PORTD=TABLE[shi]; //查表得十位显示的代码 PORTA=0x2F; //RA4输出低
11、电平,点亮十位显示 delay(1); //延时一定时间,保证亮度 PORTD=TABLE[ge]; //求个位显示的代码 PORTA=0x1F; //RA5输出低电平,点亮个位显示 delay(1); //延时一定时间,保证亮度 PORTD=0xff; } void ini(void) { TRISA=0B00000001; TRISD=0; PORTD=0
12、XFF; } //延时子程序 void delay(unsigned char x) //延时程序 { unsigned char i,i=x; //定义整形变量 for(i=250;--i;); //延时 } void interrupt clkint(void) //定时器中断函数 { QC++; //在这个函数中没有写TMRO=多少,主要目的是让TMR0自由的溢出,这样计时更准确。 T0IF=0x0; }






