基于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状态由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) //定义延时函数 { 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); // 等待用户抬起B1 DelayMS(30); // 消除机械按键后沿抖动 } } } }