|
前幾天幫別做一個(gè)51的小東西需要編碼器,結(jié)果發(fā)現(xiàn)網(wǎng)上編碼器的程序比較不好找,自己根據(jù)別人一個(gè)巧妙的思路寫了一個(gè)讀編碼器讀數(shù)的程序,用LCD1602顯示出來。里邊還有使用L298N驅(qū)動(dòng)42步進(jìn)電機(jī)部分,可以參考一下。
單片機(jī)源程序如下:
- #include <reg52.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- //LCD1602定義
- #define LCD1602_DB P0 //LCD1602數(shù)據(jù)總線
- sbit LCD1602_RS = P2^7; //RS端
- sbit LCD1602_RW = P2^6; //RW端
- sbit LCD1602_EN = P2^5; //EN端
- uchar code digit[ ]={"0123456789"}; //定義字符數(shù)組顯示數(shù)字
- uchar idata TEST[]="TEST";
- //電機(jī)正反轉(zhuǎn)二維數(shù)組 0為逆時(shí)針,1為順時(shí)針
- uchar code MotorCode[2][8]={{0x04,0x06,0x02,0x0a,0x08,0x09,0x01,0x05},{0x05,0x01,0x09,0x08,0x0a,0x02,0x06,0x04}};
- uchar MotorStatus;//電機(jī)正反轉(zhuǎn)標(biāo)志位
- sbit EncoderA=P3^2; //編碼器A相
- sbit EncoderB=P3^4; //編碼器B相
- uint EncoderCount=0 ;
- /* 毫秒軟件延時(shí)函數(shù)*/
- void delay_ms(uint x)
- {
- uint a,b;
- for(a=x;a>0;a--)
- for(b=114;b>0;b--);
- }
- /*=================================================
- *函數(shù)名稱:Read_Busy
- *函數(shù)功能:判斷1602液晶忙,并等待
- =================================================*/
- void Read_Busy()
- {
- uchar busy;
- LCD1602_DB = 0xff;//復(fù)位數(shù)據(jù)總線
- LCD1602_RS = 0; //拉低RS
- LCD1602_RW = 1; //拉高RW讀
- do
- {
- LCD1602_EN = 1;//使能EN
- busy = LCD1602_DB;//讀回?cái)?shù)據(jù)
- LCD1602_EN = 0; //拉低使能以便于下一次產(chǎn)生上升沿
- }while(busy & 0x80); //判斷狀態(tài)字BIT7位是否為1,為1則表示忙,程序等待
- }
- /*=================================================
- *函數(shù)名稱:LCD1602_Write_Cmd
- *函數(shù)功能:寫LCD1602命令
- *調(diào)用:Read_Busy();
- *輸入:cmd:要寫的命令
- =================================================*/
- void LCD1602_Write_Cmd(uchar cmd)
- {
- Read_Busy(); //判斷忙,忙則等待
- LCD1602_RS = 0;
- LCD1602_RW = 0; //拉低RS、RW操作時(shí)序情況1602課件下中文使用說明基本操作時(shí)序章節(jié)
- LCD1602_DB = cmd;//寫入命令
- LCD1602_EN = 1; //拉高使能端 數(shù)據(jù)被傳輸?shù)絃CD1602內(nèi)
- LCD1602_EN = 0; //拉低使能以便于下一次產(chǎn)生上升沿
- }
- /*=================================================
- *函數(shù)名稱:LCD1602_Write_Dat
- *函數(shù)功能:寫LCD1602數(shù)據(jù)
- *調(diào)用:Read_Busy();
- *輸入:dat:需要寫入的數(shù)據(jù)
- =================================================*/
- void LCD1602_Write_Dat(uchar dat)
- {
- Read_Busy();
- LCD1602_RS = 1;
- LCD1602_RW = 0;
- LCD1602_DB = dat;
- LCD1602_EN = 1;
- LCD1602_EN = 0;
- }
- /*=================================================
- *函數(shù)名稱:LCD1602_Clear
- *函數(shù)功能:LCD1602清屏
- =================================================*/
- void LCD1602_Clear()
- {
- Read_Busy();
- LCD1602_Write_Cmd(0x01); //清屏
- }
- /*=================================================
- *函數(shù)名稱:LCD1602_Dis_OneChar
- *函數(shù)功能:在指定位置顯示一個(gè)字符
- *調(diào)用:LCD1602_Write_Cmd(); LCD1602_Write_Dat();
- *輸入:x:要顯示的橫坐標(biāo)取值0-40,y:要顯示的行坐標(biāo)取值0-1(0為第一行,1為第二行)
- dat:需要顯示的數(shù)據(jù)以ASCLL形式顯示
- =================================================*/
- void LCD1602_Dis_OneChar(uchar x, uchar y,uchar dat)
- {
- if(y) x |= 0x40;
- x |= 0x80;
- LCD1602_Write_Cmd(x);
- LCD1602_Write_Dat(dat);
- }
- /*=================================================
- *函數(shù)名稱:LCD1602_Dis_Str
- *函數(shù)功能:在指定位置顯示字符串
- *調(diào)用:LCD1602_Write_Cmd(); LCD1602_Write_Dat();
- *輸入:x:要顯示的橫坐標(biāo)取值0-40,y:要顯示的行坐標(biāo)取值0-1(0為第一行,1為第二行)
- *str:需要顯示的字符串
- =================================================*/
- void LCD1602_Dis_Str(uchar x, uchar y, uchar *str)
- {
- if(y) x |= 0x40;
- x |= 0x80;
- LCD1602_Write_Cmd(x);
- while(*str != '\0')
- {
- LCD1602_Write_Dat(*str++);
- }
- }
- /*=================================================
- *函數(shù)名稱:Init_LCD1602
- *函數(shù)功能:1602初始化
- *調(diào)用: LCD1602_Write_Cmd();
- =================================================*/
- void Init_LCD1602()
- {
- LCD1602_Write_Cmd(0x38); // 設(shè)置16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口
- LCD1602_Write_Cmd(0x0c); //打開顯示屏,不顯示光標(biāo),光標(biāo)所在位置的字符不閃爍。
- LCD1602_Write_Cmd(0x06); //讀寫一字節(jié)后地址指針加1
- LCD1602_Write_Cmd(0x01); //清除顯示
- }
- void Motor_Forward() //電機(jī)正轉(zhuǎn)
- {
- TMOD=0x01;
- TH0=(65535-2000)/256;
- TL0=(65535-2000)%256;
- EA=1;
- ET0=1;
- TR0=1;
- MotorStatus=0;
- }
- void Motor_Reversal() //電機(jī)反轉(zhuǎn)
- {
- TMOD=0x01;
- TH0=(65535-2000)/256;
- TL0=(65535-2000)%256;
- EA=1;
- ET0=1;
- TR0=1;
- MotorStatus=1;
- }
- void Motor_Stop() //停止電機(jī)
- {
- ET0=0;
- TR0=0;
- P1=P1&0xF0;
- }
- uchar index = 0; //定義節(jié)拍輸出索引
- void time0() interrupt 1
- {
- uchar tmp; //定義一個(gè)臨時(shí)變量
- TH0=(65535-1000)/256;
- TL0=(65535-1000)%256;
-
- tmp = P1; //用 tmp 把 P1 口當(dāng)前值暫存
- tmp = tmp & 0xF0; //用&操作清零低4位
- //用|操作把節(jié)拍代碼寫到低4位
- tmp = tmp | MotorCode[MotorStatus][index];
- //把低4位的節(jié)拍代碼和高4位的原值送回 P1
- P1 = tmp;
- index++; //節(jié)拍輸出索引遞增
- index = index & 0x07; //用&操作實(shí)現(xiàn)到8歸零
-
- }
- Init_Encoder ()
- {
- EA = 1; //開總中斷
- EX0 = 1;//開外部中斷1
- IT0 = 1;//外部中斷1下降沿觸發(fā)
- }
-
- void main()
- {
- Init_Encoder ();
- Init_LCD1602();
- Motor_Reversal();
- LCD1602_Dis_Str(0, 0, &TEST[0]); //提示第一行MENU1
- while (1)
- {
- LCD1602_Dis_OneChar(0,1,digit[EncoderCount/10000]);
- LCD1602_Dis_OneChar(1,1,digit[EncoderCount%10000/1000]);
- LCD1602_Dis_OneChar(2,1,digit[EncoderCount%1000/100]);
- LCD1602_Dis_OneChar(3,1,digit[EncoderCount%100/10]);
- LCD1602_Dis_OneChar(4,1,digit[EncoderCount%10/1]);
- delay_ms(100);
- // delay_ms(500); //延時(shí) 2 ms,即 2 ms 執(zhí)行一拍
- // Motor_Reversal(); //電機(jī)反轉(zhuǎn)
- // delay_ms(500); //延時(shí) 2 ms,即 2 ms 執(zhí)行一拍
- // Motor_Stop();
- // delay_ms(500); //延時(shí) 2 ms,即 2 ms 執(zhí)行一拍
- }
-
- }
- //外部中斷1中斷服務(wù)程序
- void int0() interrupt 0
- {
- if (EncoderB)
- {
- EncoderCount++; //正轉(zhuǎn)
- }else
- {
- EncoderCount--; //反轉(zhuǎn)
- }
- if (EncoderCount==360)
- Motor_Stop();
- }
復(fù)制代碼
所有資料51hei提供下載:
42步進(jìn)電機(jī) 編碼器.rar
(32.23 KB, 下載次數(shù): 489)
2018-5-15 10:03 上傳
點(diǎn)擊文件名下載附件
51單片機(jī)+增量式編碼器+42步進(jìn)電機(jī) 下載積分: 黑幣 -5
|
|