基于51单片机PWM调速数码管显示测速L298芯片控制直流电机正反运转的项目工程
1 #include"reg52.h"//单片机头文件 2 #define uchar unsigned char//宏定义,用uchar表示unsigned char,叫无符号字符型数据类型,取值范围为:0到255。 3 #define uint unsigned int//宏定义,用uint表示unsigned int,叫无符号整数型数据类型,取值范围为:0到65535。 4 sbit qitingjian=P1^0;//位定义启停键 5 sbit zhengzhuan=P1^1;//位定义正转键 6 sbit fanzhuan=P1^2;//位定义反转键 7 sbit jiasujian=P1^3;//位定义加速键 8 sbit jiansujian=P1^4;//位定义减速键 9 sbit IN1=P1^5;//位定义数码管段码端口 10 sbit IN2=P1^6;//位定义数码管位码端口 11 sbit ENA=P1^7;//位定义L298M芯片使能端ENA 12 sbit duan=P3^0;//位定义L298M芯片控制端IN1 13 sbit wei=P3^1;//位定义L298M芯片控制端IN2 14 sbit qitingled=P3^4;//位定义启停指示灯 15 sbit zhengzhuanled=P3^5;//位定义正转指示灯 16 sbit fanzhuanled=P3^6;//位定义反转指示灯 17 sbit zhuansuled=P3^7;//位定义转速指示灯 18 sbit waibuzhongduanling=P3^2; //外部中断0端口 19 uint qian,bai,shi,ge,zhuansu;//数码管千位变量、百位变量、十位变量、个位变量以及转速变量 20 uint maichongcount,Time0num,Time1num,pwm,qitingnum,zhengzhuanflag,fanzhuanflag;//脉冲计数变量、定时器0定时计数变量、定时器1定时计数变量、脉冲宽度调制变量、启停键按下数次变量、正转标志位变量、反转标志位变量 21 uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f,0x40,0x7c,0x39,0x5e,0x79,0x71,0x00};//共阴数码管段码,高电平点亮段码,低电平熄灭段码。 22 uchar code weima[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff};//共阴数码管位码,低电平点亮位码,高电平熄灭位码。 23 void delay(uint jishi);//毫秒延时函数 24 void TimerInit();//定时器初始化函数 25 void Time0();//定时器0定时函数 26 void Time1();//定时器1定时函数 27 void KeyScan();//按键扫描函数 28 void waibuzhongduanlingjishu();//外部中断0计数函数 29 void shumaguandisplay(uint qian,uint bai,uint shi,uint ge);//数码管显示函数 30 void shumaguannodisplay(uint qian,uint bai,uint shi,uint ge);//数码管无显示函数 31 void main()//主函数 32 { 33 TimerInit();//定时器初始化函数 34 IN1=0;//L298M芯片控制端IN1置低电平,电机不运转。 35 IN2=0;//L298M芯片控制端IN2置低电平,电机不运转。 36 while(1)//死循环 37 { 38 KeyScan();//按键扫描函数 39 if(qitingnum==1)//判断启停键是否第一次按下 40 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数 41 } 42 } 43 void delay(uint jishi)//延时函数 44 { 45 uint i,j; 46 for(i=jishi;i>0;i--) 47 for(j=110;j>0;j--); 48 } 49 void TimerInit()//定时器初始化函数 50 { 51 TMOD=0x11;//设定定时器为定时器0和定时器1,工作模式都为1。 52 TH0=(65536-1000)/256;//TH0装初值为65536-100=65436,即定时100微妙,相当于0.1毫秒。 53 TL0=(65536-1000)%256;//TL0装初值为65536-100=65436 54 TH1=(65536-50000)/256;//TH1装初值为65536-50000=15536,即定时50000微妙,相当于50毫秒。 55 TL1=(65536-50000)%256;//TL1装初值为65536-50000=15536 56 EA=1;//全局中断允许 57 ET0=1;//打开定时器0中断允许 58 TR0=1;//开定时器0 59 EX0=1;//开外部中断0允许 60 IT0=1;//设置外部中断0下降触发中断 61 ET1=1;//打开定时器1中断允许 62 TR1=1;//开定时器1 63 } 64 void Time0() interrupt 1//定时器0定时函数,每0.1毫秒产生pwm波一次。 65 { 66 TH0=(65536-1000)/256;//TH0重装初值为65536-100=65436,即定时100微妙,相当于0.1毫秒。 67 TL0=(65536-1000)%256;//TH0重装初值为65536-100=65436 68 Time0num++;//定时器0定时计数变量先赋值再自加 69 if(Time0num==20)//判断定时器0定时计数变量是否大于等于20,PWM波完整周期为20ms,定时器0定时计数变量Time0num数值越大,电机运转越快。 70 { 71 Time0num=0;//定时器0定时计数变量等于0 72 } 73 if(Time0num<pwm)//判断定时器0定时计数变量还否小于脉冲宽度调制变量 74 { 75 ENA=1;//L298M芯片使能端ENA置高电平,电机运转。 76 zhuansuled=0;//开转速指示灯 77 } 78 else 79 { 80 ENA=0;//L298M芯片使能端ENA置低电平,电机不运转。 81 zhuansuled=1;//关转速指示灯 82 } 83 } 84 void Time1() interrupt 3//定时器1定时函数,定时50ms,采集电机转速。 85 { 86 TH1=(65536-50000)/256;//TH1装初值为65536-50000=15536,即定时50000微妙,相当于50毫秒。 87 TL1=(65536-50000)%256;//TH1装初值为65536-50000=15536 88 Time1num++;//定时器1定时计数变量先赋值再自加 89 if(Time1num==20)//判断定时器1定时计数变量是否等于20,即每1秒测速一次。 90 { 91 Time1num=0;//定时器1定时计数变量等于0 92 EX0=0;//关外部中断0 93 zhuansu=55*maichongcount/24;//电机转速=每分钟X脉冲计数变量/每转一圈需要的脉冲个数,即55*maichongcount/24,其中的55表示55秒,为什么不是一分钟60秒?由于Protues仿真电路图中的MOTOR-ENCODER仿真件存在误差,为了让MOTOR-ENCODER仿真件显示的转速达到数码管显示转速的效果,进行了一定秒数的修改,不过实际运用要以一分钟60秒为准,maichongcount为单片机从外部中断0端口处获取MOTOR-ENCODER仿真件旋转生产的脉冲计数变量,24为MOTOR-ENCODER仿真件每旋转一圈产生的脉冲个数。 94 qian=zhuansu/1000;//数码管千位显示 95 bai=zhuansu%1000/100;//数码管百位显示 96 shi=zhuansu%100/10;//数码管十位显示 97 ge=zhuansu%10;//数码管个位显示 98 maichongcount=0;//脉冲计数变量归零 99 EX0=1;//开外部中断0 100 } 101 } 102 void waibuzhongduanlingjishu() interrupt 0 using 1//外部中断0计数函数,外部脉冲计数。 103 { 104 maichongcount++ ;//脉冲计数变量先赋值再自加 105 } 106 void KeyScan()//按键扫描函数 107 { 108 if(qitingjian==0)//判断启停键是否按下 109 { 110 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 111 if(qitingjian==0)//再次判断启停键是否按下 112 { 113 while(!qitingjian)//启停键释放 114 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数 115 qitingnum++;//启停键按下数次变量先赋值再加加 116 qitingled=0;//开启停指示灯 117 if(qitingnum==2)//判断启停键按下数次变量是否为2 118 { 119 qitingnum=0;//启停键按下数次变量归零 120 qitingled=1;//关启停指示灯 121 zhengzhuanled=1;//关正转指示灯 122 fanzhuanled=1;//关反转指示灯 123 zhuansuled=1;//关转速指示灯 124 zhengzhuanflag=0;//正转标志位变量为0 125 fanzhuanflag=0;//反转标志位变量为0 126 IN1=0;//L298M芯片控制端IN1置低电平,电机不运转。 127 IN2=0;//L298M芯片控制端IN2置低电平,电机不运转。 128 shumaguannodisplay(qian,bai,shi,ge);//数码管无显示函数 129 } 130 } 131 } 132 if(qitingnum==1)//判断启停键是否第一次按下 133 { 134 if(zhengzhuan==0)//判断是否按下正转键 135 { 136 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 137 if(zhengzhuan==0)//再次判断是否按下正转 138 { 139 while(!zhengzhuan)//正转键释放 140 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 141 zhengzhuanled=0;//开正转指示灯 142 fanzhuanled=1;//关反转指示灯 143 zhengzhuanflag=1;//正转标志位变量为1 144 fanzhuanflag=0;//反转标志位变量为0 145 IN1=1;//L298N芯片控制端IN1置高电平 146 IN2=0;//L298N芯片控制端IN2置低电平 147 } 148 } 149 if(fanzhuan==0)//判断是否按下反转键 150 { 151 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 152 if(fanzhuan==0)//再次判断是否按下反转键 153 { 154 while(!fanzhuan)//反转键释放 155 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 156 zhengzhuanled=1;//关正转指示灯 157 fanzhuanled=0;//开反转指示灯 158 zhengzhuanflag=0;//正转标志位变量为0 159 fanzhuanflag=1;//反转标志位变量为1 160 IN1=0;//L298N芯片控制端IN1置低电平 161 IN2=1;//L298N芯片控制端IN2置高电平 162 } 163 } 164 } 165 if(zhengzhuanflag==1||fanzhuanflag==1)//判断电机是否为正转或反转 166 { 167 if(jiasujian==0)//判断是否按下加速键 168 { 169 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 170 if(jiasujian==0)//再次判断是否按下加速键 171 { 172 while(!jiasujian)//加速键释放 173 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 174 if(pwm < 20)//判断脉冲宽度调制变量是否小于20 175 pwm++;//脉冲宽度调制变量先赋值再加加 176 if(pwm >= 20)//判断脉冲宽度调制变量是否大于等于20 177 pwm = 19;//脉冲宽度调制变量等于20 178 } 179 } 180 if(jiansujian==0) //判断是否按下减速键 181 { 182 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 183 if(jiansujian==0)//再次判断是否按下减键 184 { 185 while(!jiansujian)//减速键释放 186 shumaguandisplay(qian,bai,shi,ge);//数码管显示函数做延时 187 if(pwm > 0)//判断脉冲宽度调制变量是否大于0 188 pwm--;//脉冲宽度调制变量先赋值再减减 189 if(pwm <= 0)//判断脉冲宽度调制变量是否小于等于0 190 pwm = 0;//脉冲宽度调制变量等于0 191 } 192 } 193 } 194 } 195 void shumaguandisplay(uint qian,uint bai,uint shi,uint ge)//数码管显示函数 196 { 197 duan=1;//开数码管段码端口 198 P0=table[qian];//数码千位显示 199 duan=0;//关数码管段码端口 200 P0=0x00;//关数码管段码显示 201 wei=1;//开数码管位码端口 202 P2=weima[0];//第1位数码管显示 203 wei=0;//关数码管位码端口 204 delay(1);//延时 205 206 duan=1;//开数码管段码端口 207 P0=table[bai];//数码百位显示 208 duan=0;//关数码管段码端口 209 P0=0x00;//关数码管段码显示 210 wei=1;//开数码管位码端口 211 P2=weima[1];//第2位数码管显示 212 wei=0;//关数码管位码端口 213 delay(1);//延时 214 215 duan=1;//开数码管段码端口 216 P0=table[shi];//数码管十位显示 217 duan=0;//关数码管段码端口 218 P0=0x00;//关数码管段码显示 219 wei=1;//开数码管位码端口 220 P2=weima[2];//第3位数码管显示 221 wei=0;//关数码管位码端口 222 delay(1);//延时 223 224 duan=1;//开数码管段码端口 225 P0=table[ge];//数码管个位显示 226 duan=0;//关数码管段码端口 227 P0=0x00;//关数码管段码显示 228 wei=1;//开数码管位码端口 229 P2=weima[3];//第4位数码管显示 230 wei=0;//关数码管位码端口 231 delay(1);//延时 232 } 233 void shumaguannodisplay(uint qian,uint bai,uint shi,uint ge)//数码管显示函数 234 { 235 duan=1;//开数码管段码端口 236 P0=table[qian];//数码千位显示 237 duan=1;//关数码管段码端口 238 P0=0x00;//关数码管段码显示 239 wei=1;//开数码管位码端口 240 P2=weima[0];//第1位数码管显示 241 wei=1;//关数码管位码端口 242 delay(1);//延时 243 244 duan=1;//开数码管段码端口 245 P0=table[bai];//数码百位显示 246 duan=1;//关数码管段码端口 247 P0=0x00;//关数码管段码显示 248 wei=1;//开数码管位码端口 249 P2=weima[1];//第2位数码管显示 250 wei=1;//关数码管位码端口 251 delay(1);//延时 252 253 duan=1;//开数码管段码端口 254 P0=table[shi];//数码管十位显示 255 duan=1;//关数码管段码端口 256 P0=0x00;//关数码管段码显示 257 wei=1;//开数码管位码端口 258 P2=weima[2];//第3位数码管显示 259 wei=1;//关数码管位码端口 260 delay(1);//延时 261 262 duan=1;//开数码管段码端口 263 P0=table[ge];//数码管个位显示 264 duan=1;//关数码管段码端口 265 P0=0x00;//关数码管段码显示 266 wei=1;//开数码管位码端口 267 P2=weima[3];//第4位数码管显示 268 wei=1;//关数码管位码端口 269 delay(1);//延时 270 }
版权声明:本文为AChenWeiqiangA原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。