在protues中仿真的,波形還好,做到實際的話需要提高pwm點數(shù)
效果圖
- //=====pic16f716全橋SPWM輸出,單極性調(diào)制,半個周期300個點左右====================
- //=====外部晶體20MHZ==輸出50HZ=======================================
- //=====AN0為電壓反饋端小于2.578125伏大于2.5390625伏為正常=============
- //=====RB0為外部保護,低電平保護,加上拉電阻10K===========================
- //====RB4為外部保護,低電平保護,加上拉電阻10K=============================
- #include<pic16f716.h>
- #include<pic.h>
- __CONFIG(0X3F32);//關閉看門狗使用外部HS晶體
- static unsigned char sin_num;
- bank1 float sin_am,sin_l,sin_d;//浮點數(shù),幅值變量,臨時變量,臨時變量
- bit sin_zz;
- bit adc_power;
- unsigned char sin_pp;
- //----------------------------------------------------------
- const unsigned char SPWMTABLE[40]={
- 8, 24, 39,54, 68, 83, 96, 110,122,134,145,
-
- 155,164,172,179,185,189,193,195,197,
-
- 197,195,193,189,185,179,172,164,155,
-
- 145,134,122,110,96,83,68,54,39,24,8
- };
- //------------------------------------------------------
- //-------------中斷服務程序------------------------------------
- void interrupt timer2()
- {
- if(TMR2IE==1&&TMR2IF==1) //定時器2中斷
- {
- TMR2IF=0;//清除標志位
- sin_d=SPWMTABLE[sin_num];
- sin_l=sin_am*sin_d;
- if(sin_l>=255)sin_l=255;//限幅
- if(sin_zz==1)//全橋正向輸出; P1D 被調(diào)制; P1A 有效; P1B 和 P1C 無效
- { P1M1=0;P1M0=1; CCPR1L=(unsigned char)sin_l;}
- else //全橋反向輸出; P1B 被調(diào)制; P1C 有效; P1A 和 P1D 無效
- { P1M1=1;P1M0=1; CCPR1L=(unsigned char)sin_l;}
- sin_num++;//指針加1
- if(sin_num==40){sin_num=0;sin_zz=!sin_zz;CCPR1L=0;}//查表40次
- if(sin_num==19)adc_power=1;//輸出最大開啟adc檢測峰值
- }
-
- if(ADIE==1&&ADIF==1)//adc中斷
- {
- ADIF=0;//清除標志
- sin_pp=ADRES;
- }
- }
- //-------------------adc初始化------------------
- void adc0_init()
- {
- TRISA0=0;
- ADCS1=0;
- ADCS0=0;//FOSC/2
- ADCON1=0x04;//參考電壓為5V
- //============================
- CHS2=0;
- CHS1=0;
- CHS0=0;//通道0
- ADON=1;//開啟adc
- ADIE=1;
- ADIF=0;
- }
- //軟件延時子程序*/
- void DELAY()
- {
- unsigned int i;
- for(i=50000;i>0;i--);
- }
- //------------pwm初始化函數(shù)-------------------
- void pwmInit()
- {
- PR2=138; //調(diào)spwm占空比138左右跟實際情況調(diào)
- //CCP1CON|=0x0c;// 1000 1100pwm雙輸出,占空比高2位清零,
- CCP1M3=1;
- CCP1M2=1;
- CCP1M1=0;
- CCP1M0=0;
- //=======死區(qū)為最大================
- DC1B1=0;
- DC1B0=0;
- //PWM 模式。P1A, P1C 高電平有效; P1B, P1D 高電平有效;
- CCPR1L=0;//占空比清零
- T2CON=0x44 ;//0100 0100預分頻1,后分頻9,使能timer2,/調(diào)為50hz
- TMR2IE=1; //允許TMR2 和 PR2 匹配中斷
- TMR2IF=0; //Timer2 中斷標志位清零
- PWM1CON=0X80;//軟件使能關閉pwm
- ECCPAS2=1;//RB0(INT)引腳低電平(0)導致關閉
- ECCPAS0=1;//RB4引腳低電平 (0)導致關閉
- PSSAC1=0;//:引腳P1A 和P1C 關閉狀態(tài)控制位
- PSSAC0=0;//00 = 驅(qū)動引腳P1A和 P1C 為 0
- PSSBD1=0;//:引腳P1B 和P1D關閉狀態(tài)控制位
- PSSBD0=0;//00 = 驅(qū)動引腳P1B和 P1D 為 0
- }
- //-----------------------------------------------
- void init()
- {TRISB=0;//D端口為輸出
- PORTB=0X00;
- TRISB0=1;
- TRISB4=1;//外部低電平保護
- }
- //------------主函數(shù)------------------------
- void main(void)
- {
- init() ;
- adc0_init();
- pwmInit();
- sin_num=0;//數(shù)組指針變量
- PEIE=1; //(TM2中斷為外設中斷)所有未被屏蔽的外設中斷1開放0關閉
- GIE=1; //使能所有未被屏蔽的中斷1使能0關閉
- sin_zz=1;//正反向全橋輸出標志
- sin_am=0;//sin函數(shù)的幅值
- sin_am=0.3000;//sin函數(shù)的幅值
- adc_power=1;//開啟adc電源
- while(1)
- {
- if(adc_power)
- {
- adc_power=0;
- GODONE=1;//開啟adc
- while(!(GODONE));//等待轉(zhuǎn)換結(jié)束
- }
- //=============5/256=0.01953125=========================
- //============== 132*0.01953125=2.578125伏==============
- if(sin_pp>153&&!ECCPASE)ECCPASE=1;//如果大于2.98828125就復位pwm
- if(sin_pp>132){sin_am-=0.005;if((sin_pp-132)>10)sin_am-=0.04; } //如果大于2.578125
- else
- if((sin_pp<=132)&&(sin_pp>=130))sin_am+=0; //如果小于2.578125伏大于2.5390625就不加
- else
- if(sin_pp<130) {sin_am+=0.005;if((130-sin_pp) >10)sin_am+=0.04;}
- if(sin_am>1.6)sin_am=1.6;//穩(wěn)壓變量,可調(diào)整
- }
- }
復制代碼
|