模塊圖片
測試平臺:STC89C516單片機 晶振:12MHz 其他單片機(如STC12單片機)或晶振,請在程序的LCD1602.c和rotary_encoder.c文件中修改延時函數
連線如圖(連線的接口在程序的port.h文件里)
測試代碼功能: 將程序下載到開發板,LCD顯示0FF,顯示數字000. 按下旋轉編碼器的按鍵,OFF變為ON,轉動旋轉編碼器就可以在LCD1602中看到數字變化. 再次按下旋轉按鍵,ON變為OFF,此時轉動旋轉編碼器不可以在LCD1602中看到數字變化.
結尾:
測試程序的注釋也比較詳細,自我感覺這個程序對較慢的轉速和正常的轉速的兼容性都比較好,只有極少數情況出現丟步,已經實現較好的實現了旋轉編碼器的功能了.
本帖測試程序參考過以下帖子
http://www.zg4o1577.cn/bbs/dpj-93972-1.html
單片機源程序如下:
- #include <intrins.h>
- #include "public.h"
- #include "rotary_encoder.h"
- #include "LCD1602.h"
- #include "port.h"
- void rotary_encoder_delay50us()//12.000MHz
- {
- u8 i;
- _nop_();
- i=22;
- while(--i);
- }
- void rotary_encoder_delay10ms() //12.000MHz
- {
- u8 i,j;
- i=20;
- j=113;
- do
- {
- while (--j);
- }while (--i);
- }
- //旋轉編碼器初始化
- void rotary_encoder_init()
- {
- ROTARY_ENCODER_CLK=1;
- ROTARY_ENCODER_DT=1;
- ROTARY_ENCODER_SW=1;
-
- IT0=1;
- EX0=1;
- EA=1;
-
- LCD1602_print_char(0,0,'O');
- LCD1602_print_char(0,1,'F');
- LCD1602_print_char(0,2,'F');
-
- LCD1602_print_char(1,0,'0'+0);
- LCD1602_print_char(1,1,'0'+0);
- LCD1602_print_char(1,2,'0'+0);
- }
- //掃描旋轉編碼器,返回值為1代表正轉,返回值為0代表反轉,返回值為0xFF代表未旋轉或旋轉錯誤
- u8 scan_rotary_encoder()
- {
- u8 rotary_encoder_state;//旋轉編碼器狀態
- u16 forced_out;//強制退出
-
- //旋轉編碼器狀態
- //如果在剛開始ROTARY_ENCODER_CLK和ROTARY_ENCODER_DT都為1,則狀態為1
- //如果在剛開始ROTARY_ENCODER_CLK和ROTARY_ENCODER_DT都為0,則狀態為0
- if((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT)) rotary_encoder_state=1;
- else if((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)) rotary_encoder_state=0;
-
- //ROTARY_ENCODER_CLK和ROTARY_ENCODER_DT為同一電平時檢測
- if(((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))||((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)))
- {
- //用最多150ms時間來等待ROTARY_ENCODER_CLK電平或ROTARY_ENCODER_DT電平變化(此時AB為11或00)
- forced_out=3000;
- while(((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))||((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)))
- {
- --forced_out;
- rotary_encoder_delay50us();
- if(!forced_out) return 0xFF;//超時則強制退出,返回錯誤碼
- }
-
- //每次電平變化必定旋轉了編碼器,電平變化后要消抖
- rotary_encoder_delay10ms();
-
- //當ROTARY_ENCODER_CLK為低電平,ROTARY_ENCODER_DT為高電平時
- if((!ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))
- {
- //用150ms時間來等待ROTARY_ENCODER_DT電平變化(此時AB為01)
- forced_out=3000;
- while((!ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))
- {
- --forced_out;
- rotary_encoder_delay50us();
- if(!forced_out) return 0xFF;//超時則強制退出,返回錯誤碼
- }
-
- //每次電平變化必定旋轉了編碼器,電平變化后要消抖
- rotary_encoder_delay10ms();
-
- //當ROTARY_ENCODER_CLK為低電平,而且ROTARY_ENCODER_DT也為低電平
- //或ROTARY_ENCODER_CLK為高電平,而且ROTARY_ENCODER_DT也為高電平(AB為11或00)
- //此時 AB從11到01到00 或 AB從00到01到11
- if(((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))||((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)))
- {
- //如果旋轉編碼器的狀態為1則返回1,代表正轉一下
- if(rotary_encoder_state) return 1;
- //如果旋轉編碼器的狀態為0則返回0,代表反轉一下
- else return 0;
- }
- //若AB不為11或不為00則返回旋轉編碼器錯誤碼
- else return ROTARY_ENCODER_ERROR;
- }
- //當ROTARY_ENCODER_CLK為高電平,ROTARY_ENCODER_DT為低電平時
- else
- {
- //當ROTARY_ENCODER_CLK為高電平,ROTARY_ENCODER_DT為低電平時
- if((ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT))
- {
- //用150ms時間來等待ROTARY_ENCODER_CLK電平變化(此時AB為10)
- forced_out=3000;
- while((ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT))
- {
- --forced_out;
- rotary_encoder_delay50us();
- if(!forced_out) return 0xFF;//超時則強制退出,返回錯誤碼
- }
-
- //每次電平變化必定旋轉了編碼器,電平變化后要消抖
- rotary_encoder_delay10ms();
-
- //當ROTARY_ENCODER_CLK為低電平,而且ROTARY_ENCODER_DT也為低電平
- //或ROTARY_ENCODER_CLK為高電平,而且ROTARY_ENCODER_DT也為高電平(AB為11或00)
- //此時 AB從11到10到00 或 AB從00到10到11
- if(((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))||((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)))
- {
- //如果旋轉編碼器的狀態為0則返回1,代表正轉一下
- if(!rotary_encoder_state) return 1;
- //如果旋轉編碼器的狀態為1則返回0,代表反轉一下
- else return 0;
- }
- //若AB不為11或不為00則返回旋轉編碼器錯誤碼
- else return ROTARY_ENCODER_ERROR;
- }
- }
- }
- //未響應返回旋轉編碼器錯誤碼
- return 0xFF;
- }
- //旋轉編碼器中斷
- void rotary_encoder_interrupt() interrupt 0
- {
- static u8 dat=0;
- u8 temp=0xFF;//臨時變量先賦旋轉編碼器錯誤碼的值
- if(!ROTARY_ENCODER_SW)//檢查按鍵是否按下
- {
- rotary_encoder_delay10ms();//若按鍵按下,則消抖
- if(!ROTARY_ENCODER_SW)//再次檢查按鍵是否按下
- {
- while(!ROTARY_ENCODER_SW);//按鍵按住則程序卡死在這里
- rotary_encoder_delay10ms();//松手消抖
-
- LCD1602_print_char(0,0,'O');
- LCD1602_print_char(0,1,'N');
- LCD1602_print_char(0,2,' ');
-
- while(ROTARY_ENCODER_SW)//現在掃描旋轉編碼器
- {
- //掃描旋轉編碼器,返回值為1代表正轉,返回值為0代表反轉,返回值為0xFF代表未旋轉或旋轉錯誤
- temp=scan_rotary_encoder();
-
- if(temp!=0xFF)//去除旋轉編碼器錯誤碼
- {
- //利用 unsigned char 特性
- //當temp為255時,再加1則溢出,變為0
- //同理,當temp為0時,再減1則變為255
- if(temp==0x01) ++dat;
- if(temp==0x00) --dat;
-
- //LCD1602打印字符(行,列,字符)
- LCD1602_print_char(1,0,'0'+(dat/100%10));
- LCD1602_print_char(1,1,'0'+(dat/10%10));
- LCD1602_print_char(1,2,'0'+(dat/1%10));
- }
- }
- rotary_encoder_delay10ms();//按鍵按下,則消抖
-
- while(!ROTARY_ENCODER_SW);//按鍵按住則程序卡死在這里
- rotary_encoder_delay10ms();//松手消抖
-
- LCD1602_print_char(0,0,'O');
- LCD1602_print_char(0,1,'F');
- LCD1602_print_char(0,2,'F');
- }
- }
- }
復制代碼
鏈接:游客,本帖隱藏的內容需要積分高于 1 才可瀏覽,您當前積分為 0
全部資料51hei下載地址:
旋轉編碼器測試代碼.rar
(1.44 MB, 下載次數: 138)
2020-5-5 15:24 上傳
點擊文件名下載附件
|