基于PIC16F877單片機通過SPWM脈寬調制技術軟件產生純正炫波,內容包含MPLAB源文件和protues仿真文件。
輸出波形如下:
protues的原理圖:
C程序源代碼:
// CCP1 PWM做為DAC輸出例子,輸出SPWM 波形, // 即 sin PWM // 請注意本例子中兩全局變量的單位是指令周期 #include "pic.h" __CONFIG (HS & LVPDIS & WDTDIS); unsigned char g_Period=255; //PWM周期,單位為指令周期,最大值為255 unsigned char g_DutyWidth=50; //PWM高電平寬度初值,單位為指令周期,最大值為255 #define B1 RB0 // 按鍵B1狀態(tài)由RB0端口輸入 #define XTAL_FREQ 4 // 外接晶振主頻,單位為MHz const unsigned char st[] = { 0x0, 0x2, 0x4, 0x6, 0x8, 0xb, 0xd, 0xf, //8 0x11, 0x13, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, //16 0x23, 0x25, 0x27, 0x29, 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x39, 0x3b, 0x3d, 0x3f, 0x41, //32 0x43, 0x45, 0x47, 0x48, 0x4a, 0x4c, 0x4e, 0x4f, 0x51, 0x53, 0x54, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5f, 0x61, 0x62, 0x64, 0x65, 0x66, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6f, 0x70, 0x71, //64 0x72, 0x73, 0x74, 0x74, 0x75, 0x76, 0x77, 0x78, 0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, //88 0x7e, 0x7e //7e(126) }; void DelayMS(unsigned int ms) //定義延時函數(shù) { unsigned int j=0; for(ms;ms>0;ms--) for(j=27*XTAL_FREQ;j>0;j--) // 1MHz時約是27,其它主頻請酌情修改 { } } void InitPWM(unsigned char dw) { TRISC2=0; // RC2做為PWM輸出引腳 T2CKPS1=0; //TMR2預分頻比為1:1 T2CKPS1=0; TMR2ON=1; // 使能TMR2模塊 // 設置PWM的工作周期 PR2=g_Period-1; // 設置占空比,本例子忽略高電平最低兩位 CCPR1L=dw; //獲得高電平寬度高8位 CCP1X=(g_DutyWidth>>1) & 0x01; // 獲得高電平寬度的次低位 CCP1Y=g_DutyWidth & 0x01; // 獲得高電平寬度最低位 CCP1M3=1; //1100:PWM輸出模式 CCP1M2=1; CCP1M1=0; CCP1M0=0; // 以上四條語句建議寫為: // CCP1CON=(CCP1CON & 0xF0) | 0b00001100; } void main() { unsigned char i; TRISB0=1; // RB0輸入 InitPWM(50); // 初始化CCP1的PWM方式 DelayMS(1);//為何延時1mS while(1) { for(i=0;i<90;i++) { CCPR1L=128+st[i];//128+126=255; DelayMS(1); } for(i=89;i>0;i--) { CCPR1L=128+st[i]; DelayMS(1); } for(i=0;i<90;i++) { CCPR1L=128-st[i]; DelayMS(1); } for(i=89;i>0;i--) { CCPR1L=128-st[i]; DelayMS(1); } //*/ if(B1==0) // 若按鍵B1有變化 { DelayMS(30); // 消除機械按鍵前沿抖動 if(B1==0) // 再判斷為0說明是一次正常按鍵 { g_DutyWidth+=50; //增加占空比 CCPR1L=g_DutyWidth; //賦值給高電平寬度寄存器 if(g_DutyWidth>=g_Period) //超出了PWM周期 { g_DutyWidth=0; // 則高電平寬度清零,等待下次按鍵后增值 } while(B1==0); // 等待用戶抬起B(yǎng)1 DelayMS(30); // 消除機械按鍵后沿抖動 } } } }