我们学校电气专业开始做电力电子的课设了,小组选了一项制作硬件电路的任务,里面有要求采用数控方式实现DC-DC电压变换的输出电压调节,数控在电路中的体现就是用单片机输出可调占空比的PWM作用于IRF520模块,实现电压的变化,以作用于SG3525驱动IGBT。考虑到可能有同学没接触过51单片机的C语言编程,特写下此篇文章,希望能够给大家带来帮助。
选用51开发板
本人买了这本书,配套了一个开发板,懂的都懂哈,这本书非常适合初学者入门
目标分析
我们的目标:数码管显示当前输出PWM波占空比,使用按键可以调节占空比。
所以,我们需要:
1.一个引脚输出PWM波;
2.一个定时器控制PWM波的占空比;
3.若干按钮对占空比进行操作;
4.数码管显示占空比。
以下对这四个任务逐一进行拆解。
数码管
数码管有共阴极和共阳极两种,它们可通过向端子输入不同的字形码,就可在数码管显示对应的数字。
大家DIY的时候选扩展数码管最好用共阳极的数码管,因为共阳极数码管通过低电平驱动发光,要求驱动功率小。不过本教程配套的开发板上配了共阴极数码管,我们就用共阴极数码管了。
以下是详细解释为什么要使用共阳极数码管的文章:
单片机驱动共阳数码管和共阴数码管的比较-昌晖仪表网 (yunrun.com.cn)
选择数码管上的2个位,对应占空比0~99。
按钮
使用按钮需消抖。原因如下:
什么是按键消抖?为什么要消抖?_百度知道 (baidu.com)
这里选用四个按钮,详细作用见代码注释。
定时器
定时器配置内容可看看此文章:
51单片机定时器/计数器_单片机计数器_KeLin&的博客-CSDN博客
定时时间=振荡周期*12*(65536-初值)。
PWM波输出
选择一个引脚,当定时器达到初始装载时间A,引脚从高电平跳转到低电平;当定时器达到初始装载时间B,引脚从低电平跳转到高电平。
完整代码
#include<reg52.h>
#define uchar unsigned char
//PWM周期选择:1毫秒
#define PWMZHOUQI 1000
#define JISHIMAX 65536-PWMZHOUQI
#define CHUZHI 30#define duan P0
sbit wei1=P2^4; //LED显示器的位
sbit wei2=P2^5;
sbit wei3=P2^6;
sbit wei4=P2^7;
sbit k1=P3^4; //+1、-1
sbit k2=P3^5; //可长按
sbit k3=P3^6; //改变变化方向
sbit k4=P3^7; //重置占空比
sbit output=P2^0; //PWM输出端口int is_gd=0;
int GD= JISHIMAX*CHUZHI;//高电平时间
int zhankongbi=CHUZHI;uchar code num[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f};//对应数字0~9void delay(unsigned int xms) //按键消抖用延时,单位毫秒
{unsigned int i,j;for(i=xms;i>0;i--)for(j=112;j>0;j--);}void timer0_init()
{TMOD=0x01;//16位定时器TH0=(GD>>8)&0xFF;//初始值TL0=GD&0xFF;EA=1; //打开总中断ET0=1; //打开定时器T0中断TR0=1; //启动定时器T0}
void main()
{int dir=1;int shi;int ge;int had_press=0;output=1;is_gd=1;timer0_init();while(1){if(k4==0){delay(10);if(k4==0){while(k4==0);zhankongbi=CHUZHI;had_press=1;}}if(k3==0){delay(10);if(k3==0){while(k3==0);dir=-dir;had_press=1; }}if(k1==0){delay(10);if(k1==0){while(k1==0);if ((zhankongbi+dir)>=0&& (zhankongbi+dir)<=99)zhankongbi+=dir;had_press=1; }}if(k2==0){delay(10);while(k2==0){delay(10);if ((zhankongbi+dir)>=0&& (zhankongbi+dir)<=99)zhankongbi+=dir;had_press=1; }}shi=zhankongbi/10;ge=zhankongbi%10;if (had_press){GD=JISHIMAX*zhankongbi;TH0=(GD>>8)&0xFF;//初始值TL0=GD&0xFF;is_gd=1; }duan=num[shi];wei1=0;wei2=0;wei3=1;wei4=0;delay(5);duan=num[ge];wei1=0;wei2=0;wei3=0;wei4=1;delay(5);}
}void timer0()interrupt 1
{ if(is_gd){TH0=((JISHIMAX*(1-zhankongbi))>>8)&0xFF;//初始值TL0=(JISHIMAX*(1-zhankongbi))&0xFF; } if(!is_gd){TH0=(GD>>8)&0xFF;//初始值TL0=GD&0xFF;}is_gd=-is_gd;output=~output;
}