基於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  }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM