×
单片机 > 单片机程序设计 > 详情

基于51单片机PWM调速数码管显示测速

发布时间:2024-06-27 发布时间:
|

#include"reg52.h"//单片机头文件

#define uchar unsigned char//宏定义,用uchar表示unsigned char,叫无符号字符型数据类型,取值范围为:0到255。

#define uint unsigned int//宏定义,用uint表示unsigned int,叫无符号整数型数据类型,取值范围为:0到65535。

sbit qitingjian=P1^0;//位定义启停键

sbit zhengzhuan=P1^1;//位定义正转键

sbit fanzhuan=P1^2;//位定义反转键

sbit jiasujian=P1^3;//位定义加速键

sbit jiansujian=P1^4;//位定义减速键

sbit IN1=P1^5;//位定义数码管段码端口

sbit IN2=P1^6;//位定义数码管位码端口

sbit ENA=P1^7;//位定义L298M芯片使能端ENA

sbit duan=P3^0;//位定义L298M芯片控制端IN1

sbit wei=P3^1;//位定义L298M芯片控制端IN2

sbit qitingled=P3^4;//位定义启停指示灯

sbit zhengzhuanled=P3^5;//位定义正转指示灯

sbit fanzhuanled=P3^6;//位定义反转指示灯

sbit zhuansuled=P3^7;//位定义转速指示灯

sbit waibuzhongduanling=P3^2; //外部中断0端口

uint qian,bai,shi,ge,zhuansu;//数码管千位变量、百位变量、十位变量、个位变量以及转速变量

uint maichongcount,Time0num,Time1num,pwm,qitingnum,zhengzhuanflag,fanzhuanflag;//脉冲计数变量、定时器0定时计数变量、定时器1定时计数变量、脉冲宽度调制变量、启停键按下数次变量、正转标志位变量、反转标志位变量

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f,0x40,0x7c,0x39,0x5e,0x79,0x71,0x00};//共阴数码管段码,高电平点亮段码,低电平熄灭段码。

uchar code weima[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff};//共阴数码管位码,低电平点亮位码,高电平熄灭位码。

void delay(uint jishi);//毫秒延时函数

void TimerInit();//定时器初始化函数

void Time0();//定时器0定时函数

void Time1();//定时器1定时函数

void KeyScan();//按键扫描函数

void waibuzhongduanlingjishu();//外部中断0计数函数

void shumaguandisplay(uint qian,uint bai,uint shi,uint ge);//数码管显示函数

void shumaguannodisplay(uint qian,uint bai,uint shi,uint ge);//数码管无显示函数

void main()//主函数

{

TimerInit();//定时器初始化函数

IN1=0;//L298M芯片控制端IN1置低电平,电机不运转。

IN2=0;//L298M芯片控制端IN2置低电平,电机不运转。

while(1)//死循环

{

KeyScan();//按键扫描函数

if(qitingnum==1)//判断启停键是否第一次按下

shumaguandisplay(qian,bai,shi,ge);//数码管显示函数

}

}

void delay(uint jishi)//延时函数

{

uint i,j;

for(i=jishi;i>0;i--)

for(j=110;j>0;j--);

}

void TimerInit()//定时器初始化函数

{

TMOD=0x11;//设定定时器为定时器0和定时器1,工作模式都为1。

TH0=(65536-1000)/256;//TH0装初值为65536-100=65436,即定时100微妙,相当于0.1毫秒。

TL0=(65536-1000)%256;//TL0装初值为65536-100=65436

TH1=(65536-50000)/256;//TH1装初值为65536-50000=15536,即定时50000微妙,相当于50毫秒。

TL1=(65536-50000)%256;//TL1装初值为65536-50000=15536

EA=1;//全局中断允许

ET0=1;//打开定时器0中断允许

TR0=1;//开定时器0

EX0=1;//开外部中断0允许

IT0=1;//设置外部中断0下降触发中断

ET1=1;//打开定时器1中断允许

TR1=1;//开定时器1

}

void Time0() interrupt 1//定时器0定时函数,每0.1毫秒产生pwm波一次。

{

TH0=(65536-1000)/256;//TH0重装初值为65536-100=65436,即定时100微妙,相当于0.1毫秒。

TL0=(65536-1000)%256;//TH0重装初值为65536-100=65436

Time0num++;//定时器0定时计数变量先赋值再自加

if(Time0num==20)//判断定时器0定时计数变量是否大于等于20,PWM波完整周期为20ms,定时器0定时计数变量Time0num数值越大,电机运转越快。

{

Time0num=0;//定时器0定时计数变量等于0

}

if(Time0num

{

ENA=1;//L298M芯片使能端ENA置高电平,电机运转。

zhuansuled=0;//开转速指示灯

}

else

{

ENA=0;//L298M芯片使能端ENA置低电平,电机不运转。

zhuansuled=1;//关转速指示灯

}

}

void Time1() interrupt 3//定时器1定时函数,定时50ms,采集电机转速。

{

TH1=(65536-50000)/256;//TH1装初值为65536-50000=15536,即定时50000微妙,相当于50毫秒。

TL1=(65536-50000)%256;//TH1装初值为65536-50000=15536

Time1num++;//定时器1定时计数变量先赋值再自加

if(Time1num==20)//判断定时器1定时计数变量是否等于20,即每1秒测速一次。

{

Time1num=0;//定时器1定时计数变量等于0

EX0=0;//关外部中断0

zhuansu=55*maichongcount/24;//电机转速=每分钟X脉冲计数变量/每转一圈需要的脉冲个数,即55*maichongcount/24,其中的55表示55秒,为什么不是一分钟60秒?由于Protues仿真电路图中的MOTOR-ENCODER仿真件存在误差,为了让MOTOR-ENCODER仿真件显示的转速达到数码管显示转速的效果,进行了一定秒数的修改,不过实际运用要以一分钟60秒为准,maichongcount为单片机从外部中断0端口处获取MOTOR-ENCODER仿真件旋转生产的脉冲计数变量,24为MOTOR-ENCODER仿真件每旋转一圈产生的脉冲个数。

qian=zhuansu/1000;//数码管千位显示

bai=zhuansu%1000/100;//数码管百位显示

shi=zhuansu%100/10;//数码管十位显示

ge=zhuansu%10;//数码管个位显示

maichongcount=0;//脉冲计数变量归零

EX0=1;//开外部中断0

}

}

void waibuzhongduanlingjishu() interrupt 0 using 1//外部中断0计数函数,外部脉冲计数。

{

maichongcount++ ;//脉冲计数变量先赋值再自加

}

void KeyScan()//按键扫描函数

{

if(qitingjian==0)//判断启停键是否按下

{

shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时

if(qitingjian==0)//再次判断启停键是否按下

{

while(!qitingjian)//启停键释放

shumaguandisplay(qian,bai,shi,ge);//数码管显示函数

qitingnum++;//启停键按下数次变量先赋值再加加

qitingled=0;//开启停指示灯

if(qitingnum==2)//判断启停键按下数次变量是否为2

{

qitingnum=0;//启停键按下数次变量归零

qitingled=1;//关启停指示灯

zhengzhuanled=1;//关正转指示灯

fanzhuanled=1;//关反转指示灯

zhuansuled=1;//关转速指示灯

zhengzhuanflag=0;//正转标志位变量为0

fanzhuanflag=0;//反转标志位变量为0

IN1=0;//L298M芯片控制端IN1置低电平,电机不运转。

IN2=0;//L298M芯片控制端IN2置低电平,电机不运转。

shumaguannodisplay(qian,bai,shi,ge);//数码管无显示函数

}

}

}

if(qitingnum==1)//判断启停键是否第一次按下

{

if(zhengzhuan==0)//判断是否按下正转键

{

shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时

if(zhengzhuan==0)//再次判断是否按下正转

{

while(!zhengzhuan)//正转键释放

shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时

zhengzhuanled=0;//开正转指示灯

fanzhuanled=1;//关反转指示灯

zhengzhuanflag=1;//正转标志位变量为1

fanzhuanflag=0;//反转标志位变量为0

IN1=1;//L298N芯片控制端IN1置高电平

IN2=0;//L298N芯片控制端IN2置低电平

}

}

if(fanzhuan==0)//判断是否按下反转键

{

shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时

if(fanzhuan==0)//再次判断是否按下反转键

{

while(!fanzhuan)//反转键释放

shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时

zhengzhuanled=1;//关正转指示灯

fanzhuanled=0;//开反转指示灯

zhengzhuanflag=0;//正转标志位变量为0

fanzhuanflag=1;//反转标志位变量为1

IN1=0;//L298N芯片控制端IN1置低电平

IN2=1;//L298N芯片控制端IN2置高电平

}

}

}

if(zhengzhuanflag==1||fanzhuanflag==1)//判断电机是否为正转或反转

{

if(jiasujian==0)//判断是否按下加速键

{

shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时

if(jiasujian==0)//再次判断是否按下加速键

{

while(!jiasujian)//加速键释放

sh

[1] [2]
51单片机PWM调速数码管显示


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
MSP432学习笔记:ADC14