|
三個(gè)步進(jìn)電機(jī),需要自提
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png (20.41 KB, 下載次數(shù): 61)
下載附件
2020-10-15 19:52 上傳
51hei.png (19.36 KB, 下載次數(shù): 78)
下載附件
2020-10-15 19:46 上傳
51hei.png (15.35 KB, 下載次數(shù): 60)
下載附件
2020-10-15 19:46 上傳
單片機(jī)源程序如下:
- #include <AT89X51.h>
- #include <stdio.h>
- #include <math.h>
- #define uc unsigned char
- #define ui unsigned int
- #define LCDPAGE 0xB8 //設(shè)置頁指令。
- #define LCDLINE 0x40 //設(shè)置列指令。
- sbit E= P3^5;
- sbit RW=P3^4;
- sbit RS=P3^2;
- sbit L=P3^1; //左半平面
- sbit R=P3^0; //右半平面
- sbit Busy=P2^7;// //忙 判斷位
- uc scan_key1,scan_key2; //按鍵功能選擇,00 停止,01 正轉(zhuǎn) 10 反轉(zhuǎn)
- uc step1;step2;
- static step_index;
- ui count1,count2; //定時(shí)
- uc butter; //按鍵
- static speed; //速度參數(shù)
- //;本文件為16×16點(diǎn)陣中文字庫(kù)文件,字的橫向8點(diǎn)構(gòu)成一字節(jié),左邊點(diǎn)在字節(jié)的高
- //位,字符點(diǎn)陣四角按左上角→右上角→左下角→右下角取字
- //;如你想在以后繼續(xù)用HZDotReader打開文件,追加漢字點(diǎn)陣數(shù)據(jù),請(qǐng)不要修改或增刪所有注釋
- uc code JIANG[]=
- {
- //;江 CBDAD
- 0x10,0x60,0x01,0xC6,0x30,0x00,0x04,0x04,
- 0x04,0xFC,0x04,0x04,0x04,0x04,0x00,0x00,
- 0x04,0x04,0x7E,0x01,0x20,0x20,0x20,0x20,
- 0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x00,
- };
- uc code XI[]=
- {
- uc code DI[]= //低
- {
- 0x40,0x20,0xF0,0x0C,0x07,0x02,0xFC,0x44,
- 0x44,0x42,0xFE,0x43,0x43,0x42,0x40,0x00,
- 0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x20,
- 0x10,0x28,0x43,0x0C,0x10,0x20,0x78,0x00,
- };
- //////////////////函數(shù)聲明 **************////////
- //************************************************
- void iniLCD(void);
- void chkbusy(void);
- void wcode(uc cd) ;
- void wdata(uc dat);
- void disrow(uc page,uc col,uc *temp);
- void display( uc page,uc col,uc *temp);
- void ground(step); //轉(zhuǎn)步
- void run1(); //正轉(zhuǎn)
- void run2();
- void stop();
- void delay(ui time);
- //************************************
- //**************LCD初始化 ***************
- //*********************************
- void iniLCD(void) //初始化
- { L=1;R=1;
- wcode(0x38);
- wcode(0x0f); //開顯示 設(shè)置
- wcode(0xc0); //設(shè)置顯示啟動(dòng)為第一行
- wcode(0x01); //清屏
- wcode(0x06); //畫面不動(dòng),光標(biāo)右移。
- }
- //******************LCD判斷忙的子程序**********
- //**********************************************8
- void chkbusy(void) // 測(cè)LCD忙狀態(tài)
- {
- E=1; //使能LCD
- RS=0; //讀寫指令
- RW=1; //讀
- P2=0xff; //讀操作前先進(jìn)行一次空讀操作 ,接下來才能讀到數(shù)據(jù)
- while(!Busy); //等待,不忙退出
- }
- //*****************************************
- //*****************寫指令代碼*****************
- //***********************************************
- void wcode(uc cd) //寫指令 代碼
- {
- chkbusy(); //寫等待
- P2=0xff; //使能LCD
- RW=0; //讀禁止
- RS=0; //輸出 設(shè)置
- P2=cd; //寫數(shù)據(jù)代碼
- E=1; //以下兩句產(chǎn)生下降沿
- E=0; //
- }
- //*******************把顯示數(shù)據(jù)寫到內(nèi)存單元中 *****************
- void wdata(uc dat) //寫顯示數(shù)據(jù)
- {
- chkbusy(); //寫等待
- P2=0xff; //使能LCD
- RW=0; //讀禁止
- RS=1; //輸出 設(shè)置
- P2=dat; //寫數(shù)據(jù)代碼
- E=1; //以下兩句產(chǎn)生下降沿
- E=0; //
- }
- //***********************************************
- //****************顯示LCD程序********************
- //*****************可以更改程序中的64變?yōu)?2就可以輸出數(shù)字了**********
- //****************************************************************
- //*************還可以換成生成圖片的形式,具體****************
- ///****************************************************
- void disrow(uc page,uc col,uc *temp)
- {
- uc i;
- if(col<64) // 左半平面
- {
- L=1;R=0;
- wcode(LCDPAGE+page); // 寫指令 頁
- wcode(LCDLINE+col); //寫指令行
- if((col+16)<64) //如果字在左半平面顯示不了,轉(zhuǎn)到右半平面去
- {
- for(i=0;i<16;i++) //寫字
- wdata(*(temp+i));
- }
- else //右半平面
- {
- for(i=0;i<64-col;i++) //減去左邊數(shù),從右半平面第一位開始顯示
- wdata(*(temp+i)); //寫字 顯示
- L=0;R=1; //右半平面
- wcode(LCDPAGE+page); // 寫指令 頁
- wcode(LCDLINE); //寫指令行
- for(i=64-col;i<16;i++) //寫字 右半平面
- wdata(*(temp+i));
- }
- }
- else
- {
- L=0;R=1;
- wcode(LCDPAGE+page); // 寫指令 頁
- wcode(LCDLINE+col-64); //寫指令行
- for(i=0;i<16;i++) //寫字
- wdata(*(temp+i));
- }
- }
- //*********************供調(diào)用 ****子程序 *************
- //****************************************
- void display( uc page,uc col,uc *temp)
- {
- disrow( page, col, temp); //顯示上半字
- disrow( page+1, col, temp+16); //顯示下半字
- }
- //***********************主***控****程********序********************
- //******************************************************************
- //***************程序完成于2008年6月 1日,兒童節(jié)********************
- //***************程序員:韓福偉************************************
- //**********江西理工大學(xué)應(yīng)用科學(xué)學(xué)院機(jī)電學(xué)部自動(dòng)化******************
- //******************************************************************
- //*********
- void main(void)
- {
- P2=0xff;
- iniLCD(); //初始化 LCD
- display(0,0x00,&JIANG); // 江
- display(0,0x10,&XI); // 西
- display(0,0x20,&LI); // 理
- display(0,0x30,&GONG); // 工
- display(0,0x40,&DA); // 大
- display(0,0x50,&XUE); // 學(xué)
- step2=0;
- step1=0;
- P1=0xff;
- P0=0;
- EX1=1;
- EA=1; //開中斷
- speed=2010;
- while(1)
- {
- if((scan_key1==1)&(scan_key2==0)) // 正轉(zhuǎn)
- {
- display(6,0x00,&ZHENG); // LCD顯示
- display(6,0x10,&ZHUAN);
- ground(step_index);
- delay(speed);
- step_index++; //大于7,從頭再來
- if(step_index>7)
- step_index=0;
- }
- if((scan_key1==0)&(scan_key2==1)) //反轉(zhuǎn)
- {
- ground(step_index);
- display(6,0x00,&FAN); // LCD顯示
- display(6,0x10,&ZHUAN);
- delay(speed);
- step_index--;
- if(step_index<0) //小于0,從頭再來。
- step_index=7;
- }
- if(scan_key1==0&scan_key2==0)
- {
- display(6,0x00,&TING); // 停止
- display(6,0x10,&ZHI);
- display(6,0x20,&BAI);
- display(6,0x30,&BAI);
- P0=0xff;
- }
- if(step1==1&step2==0)
- {
- speed=speed-100;
- if(speed<200|speed==200) //小于話,說明電機(jī)的速度不能再提高了。
- { speed=200; //speed參數(shù)自己設(shè)定,以下遇到也是一樣的。我只是一個(gè)亂寫的值
- display(6,0x20,&ZHENG); //正常運(yùn)行
- display(6,0x30,&CHANG);
- display(6,0x40,&YUN);
- display(6,0x50,&XING);
- }
- else //加速
- {
- display(6,0x20,&JIA);
- display(6,0x30,&SU);
- }
- }
- if(step1==0&step2==1)
- {
- speed=speed+100; //這里面的參數(shù),論實(shí)際情況更改
- if(speed>2500|speed==2500) //如果 小于了,就說明到餓低速,可以用停止按鍵停止。
- { speed=2500; //低速運(yùn)行
- display(6,0x20,&DI);
- display(6,0x30,&SU);
- display(6,0x40,&YUN);
- display(6,0x50,&XING);
- }
- else
- {
- display(6,0x20,&JIAN); //減速
- display(6,0x30,&SU);
- }
- }
- }
- }
- //***************************************************
- //************************* 延時(shí)子程序**************
- //**************************************************
- void delay(ui time) ///延時(shí)程序
- { for (count1=0;count1<time;count1++ ) //此處可以用中斷進(jìn)行準(zhǔn)確定時(shí)。我只是瞎定了幾個(gè)參數(shù)
- for(count2=0;count2<3;count2++);
- }
- //*********************************************************
- //******************按鍵處理程序****************************
- //************************************************************
- void key(void) interrupt 2
- {
- uc i;
- for(i=0;i<200;i++); //延時(shí)防抖
- if(P3_3==0)
- {
- butter=~P1;
- switch(butter)
- {case 0x01: scan_key1=1;scan_key2=0; break; //正常運(yùn)行 ,用兩個(gè)數(shù)字進(jìn)行選擇,是不錯(cuò)的辦法
- case 0x02: scan_key1=0;scan_key2=0;break; //停止
- case 0x04: scan_key1=0 ;scan_key2=1; break; //加速
- case 0x08: step1=1;step2=0;break; //減速
- case 0x10: step1=0;step2=1;break; //正轉(zhuǎn)
- default : ; //其它值返回
- }
- }
- P1=0XFF;
- }
- //**************************************************
- //**********************轉(zhuǎn)步************************
- //**************************************************
- void ground(step_index) //轉(zhuǎn)步
- {
- switch(step_index)
- {
- case 0://0 // 這里就說明了同步電機(jī)是怎么轉(zhuǎn)的。我本來是用了代碼的,
- P0_0 = 1; //但是后來考慮了一些初學(xué)者不懂同步電機(jī)到底怎么轉(zhuǎn)的
- P0_1 = 0; //我就換成這個(gè)了, 知道怎么轉(zhuǎn)的人,就換成代碼把,一樣的
- P0_2 = 0;
- P0_3 = 0;
- break;
- case 1://0,1
- P0_0 = 1;
- P0_1 = 1;
- P0_2 = 0;
- P0_3 = 0;
- break;
- case 2://1
- P0_0 = 0;
- P0_1 = 1;
- P0_2 = 0;
- P0_3 = 0;
- break;
- case 3://1,2
- P0_0 = 0;
- P0_1 = 1;
- P0_2 = 1;
- P0_3 = 0;
- break;
- case 4://2
- P0_0 = 0;
- P0_1 = 0;
- P0_2 = 1;
- P0_3 = 0;
- break;
- case 5://2,3
- P0_0 = 0;
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
Keil代碼與Proteus仿真下載:
僅供參考.7z
(98.74 KB, 下載次數(shù): 54)
2023-4-16 16:43 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
|