我们学校电气专业开始做电力电子的课设了,小组选了一项制作硬件电路的任务,里面有要求采用数控方式实现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~9
void 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;
}