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 }