仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
Proteus仿真操作流如下:
步驟一:打開仿真.DSN文件  (用Proteus7.8打開) 步驟二:左鍵雙擊U1單片機,打開加載HEX文件界面,左鍵單擊文件夾圖標
步驟三:選擇給的1號源程序文件夾,找到HEX文件。 步驟四:左鍵雙擊打開HEX文件,跳到步驟二界面,點擊OK
步驟五:左鍵點擊左下角運行
單片機源程序如下:
- #include<reg52.h>
- #include<stdio.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit RS = P2^4;//1602數據/命令選擇端(H:數據寄存器L:指令寄存器)
- sbit RW = P2^5;//1602讀/寫選擇端
- sbit E = P2^6;//1602使能信號端
- sbit key1=P3^0;//用戶按鍵
- sbit key2=P3^1;
- sbit key3=P3^2;
- sbit key4=P3^3;
- sbit key5=P3^4;
- uchar code B_Rotation[8]={0x7f,0x3f,0xbf,0x9f,0xdf,0xcf,0xef,0x6f}; //反轉表格
- uchar code F_Rotation[8]={0xef,0xcf,0xdf,0x9f,0xbf,0x3f,0x7f,0x6f}; //正轉表格
- uchar table1[]="dir: + spe:005";
- uchar table2[]="cir:000 ang:000";
- uchar num;
- uint key,flag,speed=5,zflag,znum,fflag,fnum,select,pp,qq;
- //1鍵值2鍵值標志3速度4正轉標志5正轉圈數6反轉標志7反轉圈數8正轉角度9反轉角度10選擇
- float zang,fang;
- /******************************************************************/
- /* 延時函數 Xms */
- /******************************************************************/
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /******************************************************************/
- /* LCD1602寫命令操作 */
- /******************************************************************/
- void WriteCommand(uchar com)
- {
- delay(5);//操作前短暫延時,保證信號穩定
- E=0;
- RS=0;
- RW=0;
- P0=com;
- E=1;
- delay(5);
- E=0;
- }
- /******************************************************************/
- /* LCD1602寫數據操作 */
- /******************************************************************/
- void WriteData(uchar dat)
- {
- delay(5); //操作前短暫延時,保證信號穩定
- E=0;
- RS=1;
- RW=0;
- P0=dat;
- E=1;
- delay(5);
- E=0;
- }
- /******************************************************************/
- /* 1602初始化程序 */
- /******************************************************************/
- void InitLcd()//1602初始化程序
- {
- delay(15);
- WriteCommand(0x38); //display mode
- WriteCommand(0x38); //display mode
- WriteCommand(0x38); //display mode
- WriteCommand(0x06); //當讀或寫一個字符后地址指針加一,且光標加一
- WriteCommand(0x0c); //顯示開及光標不顯示
- WriteCommand(0x01); //清屏
- WriteCommand(0x80);
- for(num=0;num<15;num++)//第一行的顯示
- {
- WriteData(table1[num]);
- delay(15);
- }
- WriteCommand(0x80+0x40);//第二行的顯示
- for(num=0;num<15;num++)
- {
- WriteData(table2[num]);
- delay(15);
- }
- }
- /******************************************************************/
- /* 獨立鍵盤掃描函數 */
- /******************************************************************/
- void keyscan()
- {
-
- P3=0xff;//拉高P3口,以讀取P3口的值
- if(key1==0)//鍵1被按下
- {
- delay(5);//延時消抖
- if(key1==0)
- {
- flag=1;
- }
- while(!key1);
- delay(5);//延時消抖
- while(!key1);//松手檢測
- }
- if(key2==0)
- {
- delay(5);
- if(key2==0)
- {
- flag=2;
- }
- while(!key2);
- delay(5);
- while(!key2);
- }
- if(key3==0)//鍵1被按下
- {
- delay(5);//延時消抖
- if(key3==0)
- {
- flag=3;
- }
- while(!key3);
- delay(5);//延時消抖
- while(!key3);//松手檢測
- }
- if(key4==0)
- {
- delay(5);
- if(key4==0)
- {
- flag=4;
- }
- while(!key4);
- delay(5);
- while(!key4);
- }
- if(key5==0)
- {
- delay(5);
- if(key5==0)
- {
- flag=5;
- }
- while(!key5);
- delay(5);
- while(!key5);
- }
- }
- /******************************************************************/
- /* 1602顯示3位數 */
- /******************************************************************/
- void write_sfm(uchar add,uint date)//1602顯示
- {
- uchar bai,shi,ge;
- bai=date/100;
- shi=date%100/10;
- ge=date%10;
- WriteCommand(0x80+add);//設置數據地址指針
- WriteData(0x30+bai);
- WriteData(0x30+shi);
- WriteData(0x30+ge);
- WriteData(0x20);
- }
- /******************************************************************/
- /* 鍵值處理 */
- /******************************************************************/
- void handle_flag()
- {
- uchar select1;
- if(TR0==0&&TR1==0)
- {
- if(flag==1) //正轉
- {
- WriteCommand(0x80+0x05);
- WriteData('+');
- delay(20);
- select=0;
- }
- if(flag==2) //反轉
- {
- WriteCommand(0x80+0x05);
- WriteData('-');
- delay(20);
- select=1;
- }
- if(flag==3)//轉速加
- {
- speed++;
- if(speed>=12)
- speed=12;
- write_sfm(0x0c,speed);//顯示速度
- delay(20);
- }
- if(flag==4) //轉速減
- {
- speed--;
- if(speed<=1)
- speed=1;
- write_sfm(0x0c,speed);//顯示速度
- delay(20);
- }
- }
- if(flag==5)////關閉中斷,停止電機
- {
- select1++;
- select1%=2;
- if( select1==0)
- {
- TR0=0;
- TR1=0;
- if(select==0)//顯示轉動的角度
- write_sfm(0x40+0x0c,zang);
- else
- write_sfm(0x40+0x0c,fang);
- }
- else
- {if(select==0)
- {
- TR0=1;//開定時器0,產生正轉相序
- TR1=0;//關定時器1
- }
- else
- {
- TR1=1;//開定時器1,產生反轉相序
- TR0=0;//關定時器0
- }
- }
- }
- flag=0;
- }
- void main()
- {
-
- pp=0;
- qq=0;
-
- InitLcd();
- TMOD=0x11;
- EA=1;
- ET0=1;
- ET1=1;
- TH0=(65536-(14648/speed))/256;
- TL0=(65536-(14648/speed))%256;
- TH1=(65536-(14648/speed))/256;
- TL1=(65536-(14648/speed))%256;
- TR0=0;
- TR1=0;
-
- while(1)
- {
- keyscan();
- handle_flag();
- }
- }
- void time0() interrupt 1
- {
- uint zz;
- TH0=(65536-(14648/speed))/256; // 360/(5.625/64)=4096
- //假設60秒轉一圈,即60秒中斷4096次,
- //那么一次中斷需要60000000/4096=14648個時鐘
- //60000000/(4096*speed) zflag=4096時一圈
- TL0=(65536-(14648/speed))%256;
- zz%=8;
- P1=F_Rotation[zz]; //輸出對應的相
- zz++;
- zflag++;
- if(zflag==4096) //正轉了一圈
- {
- zflag=0;
- znum++;
- write_sfm(0x40+0x04,znum);
- }
- if(zflag%64==0)//計算正轉動的角度
- {
- pp++;
- zang=(uint)(pp*5.625);
- if(zang==360)
- pp=0;
- write_sfm(0x40+0x0c,zang);
- }
- //zang=0.088*zflag;
- //write_sfm(0x40+0x0c,zang);
- }
- void time1() interrupt 3
- {
-
- uint ff;
- TH1=(65536-(14648/speed))/256;
- TL1=(65536-(14648/speed))%256;
- ff%=8;
- P1=B_Rotation[ff]; //輸出對應的相
- ff++;
- fflag++;
- if(fflag==4096) //反轉了一圈
- {
- fflag=0;
- fnum++;
- write_sfm(0x40+0x04,fnum);
- }
- if(fflag%64==0)//計算反轉動的角度
- {
- qq++;
- fang=(uint)(qq*5.625);
- if(fang==360)
- qq=0;
- write_sfm(0x40+0x0c,fang);
- }
- }
復制代碼
Keil4代碼與Proteus7.5,8.8仿真下載:
資料.7z
(388.36 KB, 下載次數: 166)
2022-5-2 04:50 上傳
點擊文件名下載附件
|