**先給大家看看我選用的EC11元器件**
代碼在最后,復(fù)制可直接食用
以及我的電路圖
在研究EC11的時(shí)序之前首先要了解一點(diǎn),EC11按旋轉(zhuǎn)的輸出動(dòng)作可以分為兩種。一種是轉(zhuǎn)兩格,A、B對(duì)C端輸出一個(gè)完整脈沖(轉(zhuǎn)一格就只是由低電平->高電平或由高電平->低電平);另一種就是轉(zhuǎn)一格,A、B對(duì)C端輸出一個(gè)完整脈沖。
一定位一脈沖的EC11按測(cè)試電路圖的接法,在靜止的時(shí)候AB兩線輸出都是高電平。轉(zhuǎn)動(dòng)一格,AB兩線各自輸出一個(gè)低電平脈沖,然后又回到高電平狀態(tài)。對(duì)應(yīng)于EC11內(nèi)部AB兩個(gè)觸點(diǎn)開關(guān)的動(dòng)作為斷開–>閉合–>斷開。
兩定位一脈沖的EC11稍微復(fù)雜一些,轉(zhuǎn)動(dòng)一格只會(huì)輸出半個(gè)脈沖。靜止時(shí),AB觸點(diǎn)開關(guān)可以是斷開的也可以是閉合的。若初始狀態(tài)時(shí)AB都是高電平,轉(zhuǎn)動(dòng)一格就輸出從高電平到低電平的下降沿,隨后一直輸出低電平。對(duì)應(yīng)于EC11內(nèi)部AB兩個(gè)觸電開關(guān)的動(dòng)作為斷開–>閉合。
若初始狀態(tài)時(shí)AB都是低電平,轉(zhuǎn)動(dòng)一格就輸出從低電平到高電平的上升沿,隨后一直輸出低電平。對(duì)應(yīng)于EC11內(nèi)部AB兩個(gè)觸點(diǎn)開關(guān)的動(dòng)作為閉合–>斷開。
由于兩脈沖一定位的EC11會(huì)有兩種初始狀態(tài),寫驅(qū)動(dòng)程序就需要考慮多一些情況。再者,這類EC11在轉(zhuǎn)動(dòng)到內(nèi)部AB觸點(diǎn)一直閉合的時(shí)候,就相當(dāng)于把上拉電阻的另一端接地,無(wú)形中加大了系統(tǒng)的功耗(若外接10K上拉電阻到5V電源就是500uA的電流),這對(duì)于低功耗應(yīng)用來(lái)說(shuō)是非常不利的。
因此對(duì)于無(wú)特殊要求的人機(jī)輸入應(yīng)用來(lái)說(shuō),我都推薦使用一定位一脈沖的EC11。
當(dāng)然了,有一些質(zhì)量比較差的EC11會(huì)有一些額外的問題要考慮,例如開關(guān)的抖動(dòng)問題,例如轉(zhuǎn)動(dòng)定位不清晰,靜止時(shí)AB兩個(gè)觸點(diǎn)都要閉合或者都要斷開才對(duì),但是定位點(diǎn)不清晰,轉(zhuǎn)動(dòng)的角度不到位導(dǎo)致一個(gè)觸點(diǎn)已經(jīng)閉合(斷開)了,另一個(gè)觸點(diǎn)卻還保持在斷開(閉合)。對(duì)于這些問題我們?cè)诤竺嬖僮隹紤]。
時(shí)序圖
要寫驅(qū)動(dòng)程序,得先了解EC11的工作過(guò)程。使用邏輯分析儀(LA)抓取時(shí)序可以很方便的從單片機(jī)的角度了解EC11的工作過(guò)程并依此來(lái)編寫驅(qū)動(dòng)程序。
??EC11的編碼器部分有3個(gè)引腳,A,B,和C。通常可以把C端接GND,A,B端接到輸入上拉模式的IO口。可以取A或B任意一根線作為時(shí)鐘線,另一根作為信號(hào)輸出線。我個(gè)人習(xí)慣把A線作為時(shí)鐘線,B線作為信號(hào)線。
??本文中出現(xiàn)的邏輯分析儀抓取的時(shí)序圖中均是最上方通道為EC11的A線,視為時(shí)鐘;下方一個(gè)通道為EC11的B線,視為數(shù)據(jù)輸出。
就不啰嗦太多,我就直接上代碼,我使用STM32F103系列
#include "ec11.h"
#include "sys.h"
void TIM4_Int_Init(u16 arr,u16 psc)
{
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//TIM2時(shí)鐘使能
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據(jù)指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM7中斷,允許更新中斷
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優(yōu)先級(jí)0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子優(yōu)先級(jí)2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
TIM_Cmd(TIM4,ENABLE);//開啟定時(shí)器4
}
//定時(shí)器4中斷服務(wù)程序
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)//是更新中斷
{
Encoder_EC11_Analyze(Encoder_EC11_Scan());
TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //清除TIM4更新中斷標(biāo)志
}
}
//*******************************************************************/
//功能:初始化EC11旋轉(zhuǎn)編碼器相關(guān)參數(shù)
//形參:EC11旋轉(zhuǎn)編碼器的類型-->> unsigned char Set_EC11_TYPE <<-- :0----一定位對(duì)應(yīng)一脈沖;1(或非0)----兩定位對(duì)應(yīng)一脈沖。
//返回:無(wú)
//詳解:對(duì)EC11旋轉(zhuǎn)編碼器的連接IO口做IO口模式設(shè)置。以及將相關(guān)的變量進(jìn)行初始化
//*******************************************************************/
void EC11_Init(unsigned char Set_EC11_TYPE)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9);
//EC11類型選擇:0-一定位一脈沖;1-兩定位一脈沖
if (Set_EC11_TYPE == 0)
{
EC11_Type = 0;
}
else
{
EC11_Type = 1;
}
//避免上電時(shí)EC11旋鈕位置不確定導(dǎo)致一次動(dòng)作誤判
EC11_A_Last = EC11_A_Now;
EC11_B_Last = EC11_B_Now;
//--------清除按鍵計(jì)數(shù)器和標(biāo)志位--------//
EC11_KEY_COUNT = 0; //EC11按鍵動(dòng)作計(jì)數(shù)器
EC11_KEY_DoubleClick_Count = 0; //EC11按鍵雙擊動(dòng)作計(jì)數(shù)器
FLAG_EC11_KEY_ShotClick = 0; //EC11按鍵短按動(dòng)作標(biāo)志
FLAG_EC11_KEY_LongClick = 0; //EC11按鍵長(zhǎng)按動(dòng)作標(biāo)志
FLAG_EC11_KEY_DoubleClick = 0; //EC11按鍵雙擊動(dòng)作標(biāo)志
TIM4_Int_Init(9,7199); //初始化定時(shí)器4 1ms中斷
}
//*******************************************************************/
//功能:對(duì)EC11旋轉(zhuǎn)編碼器的動(dòng)作進(jìn)行分析,并作出相應(yīng)的動(dòng)作處理代碼
//形參:無(wú)
//返回:char AnalyzeResult = 0;目前無(wú)用。若在該函數(shù)里做了動(dòng)作處理,則函數(shù)的返回值無(wú)需理會(huì)
//詳解:對(duì)EC11旋轉(zhuǎn)編碼器的動(dòng)作進(jìn)行模式分析,是單擊還是雙擊還是長(zhǎng)按松手還是一直按下。形參從 [ char Encoder_EC11_Scan(unsigned char Set_EC11_TYPE) ] 函數(shù)傳入。在本函數(shù)內(nèi)修改需要的動(dòng)作處理代碼
//*******************************************************************/
char Encoder_EC11_Analyze(char EC11_Value)
{
char AnalyzeResult = 0;
static unsigned int TMP_Value = 0; //中間計(jì)數(shù)值,用于連續(xù)長(zhǎng)按按鍵的動(dòng)作延時(shí)間隔
//>>>>>>>>>>>>>>>>編碼器正轉(zhuǎn)處理程序<<<<<<<<<<<<<<<<//
if(EC11_Value == 1) //正轉(zhuǎn)
{
//--------編碼器正轉(zhuǎn)動(dòng)作代碼--------//
printf("正轉(zhuǎn)?。?)
}
//>>>>>>>>>>>>>>>>編碼器反轉(zhuǎn)處理程序<<<<<<<<<<<<<<<<//
if(EC11_Value == 8) //反轉(zhuǎn)
{
//--------編碼器反轉(zhuǎn)動(dòng)作代碼--------//
printf("反轉(zhuǎn)?。?);
}
//>>>>>>>>>>>>>>>>編碼器按鍵按下并正轉(zhuǎn)處理程序<<<<<<<<<<<<<<<<//
if(EC11_Value == 3)
{
//--------編碼器按鍵按下并正轉(zhuǎn)動(dòng)作代碼--------//
}
//>>>>>>>>>>>>>>>>編碼器按鍵按下并反轉(zhuǎn)處理程序<<<<<<<<<<<<<<<<//
if(EC11_Value == 9)
{
//--------編碼器按鍵按下并反轉(zhuǎn)動(dòng)作代碼--------//
// printf("按下反轉(zhuǎn)??!");
}
//>>>>>>>>>>>>>>>>編碼器按鍵按下處理程序<<<<<<<<<<<<<<<<//
if(EC11_Value == 2) //====檢測(cè)到按鍵按下====//
{
if(EC11_KEY_COUNT<10000) //打開按鍵按下時(shí)間定時(shí)器
EC11_KEY_COUNT++;
if(EC11_KEY_COUNT == KEY_COUNT_DESHAKING) //按下按鍵時(shí)間到達(dá)消抖時(shí)間時(shí)
{ //置位短按按鍵標(biāo)志
FLAG_EC11_KEY_ShotClick = 1;
}
if((EC11_KEY_DoubleClick_Count > 0)&&(EC11_KEY_DoubleClick_Count <= KEY_COUNT_DUALCLICKTIME)) //松開按鍵后,又在定時(shí)器在雙擊時(shí)間內(nèi)按下按鍵
{ //置位雙擊按鍵標(biāo)志
FLAG_EC11_KEY_DoubleClick = 1;
}
if(EC11_KEY_COUNT == KEY_COUNT_LONGTIME) //按下按鍵時(shí)間到達(dá)長(zhǎng)按時(shí)間
{ //置位長(zhǎng)按按鍵標(biāo)志并復(fù)位短按按鍵標(biāo)志
FLAG_EC11_KEY_LongClick = 1;
FLAG_EC11_KEY_ShotClick = 0;
}
}
else //====檢測(cè)到按鍵松開====//
{
if(EC11_KEY_COUNT < KEY_COUNT_DESHAKING) //沒到消抖時(shí)長(zhǎng)就松開按鍵,復(fù)位所有定時(shí)器和按鍵標(biāo)志
{
EC11_KEY_COUNT = 0;
FLAG_EC11_KEY_ShotClick = 0;
FLAG_EC11_KEY_LongClick = 0;
FLAG_EC11_KEY_DoubleClick = 0;
EC11_KEY_DoubleClick_Count = 0;
}
else
{
if(FLAG_EC11_KEY_ShotClick == 1) //短按按鍵定時(shí)有效期間
{
if((FLAG_EC11_KEY_DoubleClick == 0)&&(EC11_KEY_DoubleClick_Count >= 0))
EC11_KEY_DoubleClick_Count++;
if((FLAG_EC11_KEY_DoubleClick == 1)&&(EC11_KEY_DoubleClick_Count <= KEY_COUNT_DUALCLICKTIME)) //如果在規(guī)定雙擊時(shí)間內(nèi)再次按下按鍵
{ //認(rèn)為按鍵是雙擊動(dòng)作
FLAG_EC11_KEY_DoubleClick = 2;
}
if((FLAG_EC11_KEY_DoubleClick == 0)&&(EC11_KEY_DoubleClick_Count > KEY_COUNT_DUALCLICKTIME)) //如果沒有在規(guī)定雙擊時(shí)間內(nèi)再次按下按鍵
FLAG_EC11_KEY_ShotClick = 0; //認(rèn)為按鍵是單擊動(dòng)作
}
if(FLAG_EC11_KEY_LongClick == 1) //檢測(cè)到長(zhǎng)按按鍵松開
{
FLAG_EC11_KEY_LongClick = 0;
}
}
}
//>>>>>>>>>>>>>>>>編碼器按鍵分析處理程序<<<<<<<<<<<<<<<<//
if(EC11_KEY_COUNT > KEY_COUNT_DESHAKING) //短按按鍵延時(shí)到了時(shí)間
{
//短按按鍵動(dòng)作結(jié)束代碼
if((FLAG_EC11_KEY_ShotClick == 0)&&(EC11_KEY_DoubleClick_Count > KEY_COUNT_DUALCLICKTIME)&&(EC11_KEY_COUNT < KEY_COUNT_LONGTIME)) //短按按鍵動(dòng)作結(jié)束代碼
{
//--------短按按鍵動(dòng)作結(jié)束代碼--------//
EC11_NUM_SW++;
if(EC11_NUM_SW >= 4)
EC11_NUM_SW = 1;
AnalyzeResult = 1;
//--------清除標(biāo)志位--------//
EC11_KEY_COUNT = 0;
EC11_KEY_DoubleClick_Count = 0;
FLAG_EC11_KEY_DoubleClick = 0;
}
//雙擊按鍵動(dòng)作結(jié)束代碼
if((FLAG_EC11_KEY_DoubleClick == 2)&&(EC11_KEY_DoubleClick_Count > 0)&&(EC11_KEY_DoubleClick_Count <= KEY_COUNT_DUALCLICKTIME)) //雙擊按鍵動(dòng)作結(jié)束代碼
{
//--------雙擊按鍵動(dòng)作結(jié)束代碼--------//
if(EC11_NUM_SW == 5)
EC11_NUM_SW = 0;
if(EC11_NUM_SW == 4)
EC11_NUM_SW = 5;
if(EC11_NUM_SW <4)
{
EC11_NUM_SW = 4;
}
AnalyzeResult = 2;
//--------清除標(biāo)志位--------//
EC11_KEY_COUNT = 0;
EC11_KEY_DoubleClick_Count = 0;
FLAG_EC11_KEY_ShotClick = 0;
FLAG_EC11_KEY_DoubleClick = 0;
}
//連續(xù)長(zhǎng)按按鍵按下代碼
if((FLAG_EC11_KEY_LongClick == 1)&&(EC11_KEY_COUNT >= KEY_COUNT_LONGTIME)) //連續(xù)長(zhǎng)按按鍵按下代碼
{
TMP_Value ++;
if(TMP_Value % KEY_LONG_REPEAT_TIME == 0)
{
TMP_Value = 0;
//-------連續(xù)長(zhǎng)按按鍵按下代碼--------//
AnalyzeResult = 4;
}
}
//長(zhǎng)按按鍵動(dòng)作結(jié)束代碼
if((FLAG_EC11_KEY_LongClick == 0)&&(EC11_KEY_COUNT >= KEY_COUNT_LONGTIME)) //長(zhǎng)按按鍵動(dòng)作結(jié)束代碼
{
//--------長(zhǎng)按按鍵按下動(dòng)作結(jié)束代碼--------//
EC11_NUM_SW = 0;
AnalyzeResult = 3;
//--------清除標(biāo)志位--------//
EC11_KEY_COUNT = 0;
}
}
return AnalyzeResult;
}
//*******************************************************************/
//功能:掃描EC11旋轉(zhuǎn)編碼器的動(dòng)作并將參數(shù)返回給動(dòng)作分析函數(shù)使用
//形參:EC11旋轉(zhuǎn)編碼器的類型-->> unsigned char Set_EC11_TYPE <<-- :0----一定位對(duì)應(yīng)一脈沖;1(或非0)----兩定位對(duì)應(yīng)一脈沖
//返回:EC11旋轉(zhuǎn)編碼器的掃描結(jié)果-->> char ScanResult -->> 0:無(wú)動(dòng)作;1:正轉(zhuǎn); -1:反轉(zhuǎn);2:只按下按鍵;3:按著按鍵正轉(zhuǎn);-3:按著按鍵反轉(zhuǎn)
//詳解:只掃描EC11旋轉(zhuǎn)編碼器有沒有動(dòng)作,不關(guān)心是第幾次按下按鍵或長(zhǎng)按或雙擊。返回值直接作為形參傳給 [ void Encoder_EC11_Analyze(char EC11_Value); ] 函數(shù)使用
//*******************************************************************/
char Encoder_EC11_Scan()
{
//以下儲(chǔ)存A、B上一次值的變量聲明為靜態(tài)全局變量,方便對(duì)EC11對(duì)應(yīng)的IO口做初始化
// static char EC11_A_Last = 0;
// static char EC11_B_Last = 0;
char ScanResult = 0; //返回編碼器掃描結(jié)果,用于分析編碼器的動(dòng)作
//返回值的取值: 0:無(wú)動(dòng)作; 1:正轉(zhuǎn); 8:反轉(zhuǎn);
// 2:只按下按鍵; 3:按著按鍵正轉(zhuǎn); 9:按著按鍵反轉(zhuǎn)
//======================================================//
if(EC11_Type == 0) //================一定位對(duì)應(yīng)一脈沖的EC11================//
{ //======================================================//
if(EC11_A_Now != EC11_A_Last) //以A為時(shí)鐘,B為數(shù)據(jù)。正轉(zhuǎn)時(shí)AB反相,反轉(zhuǎn)時(shí)AB同相
{
if(EC11_A_Now == 0)
{
if(EC11_B_Now ==1) //只需要采集A的上升沿或下降沿的任意一個(gè)狀態(tài),若A下降沿時(shí)B為1,正轉(zhuǎn)
ScanResult = 1; //正轉(zhuǎn)
else //反轉(zhuǎn)
ScanResult = 8;
}
EC11_A_Last = EC11_A_Now; //更新編碼器上一個(gè)狀態(tài)暫存變量
EC11_B_Last = EC11_B_Now; //更新編碼器上一個(gè)狀態(tài)暫存變量
}
}
//======================================================//
else //================兩定位對(duì)應(yīng)一脈沖的EC11================//
{ //======================================================//
if(EC11_A_Now !=EC11_A_Last) //當(dāng)A發(fā)生跳變時(shí)采集B當(dāng)前的狀態(tài),并將B與上一次的狀態(tài)進(jìn)行對(duì)比。
{ //若A 0->1 時(shí),B 1->0 正轉(zhuǎn);若A 1->0 時(shí),B 0->1 正轉(zhuǎn);
//若A 0->1 時(shí),B 0->1 反轉(zhuǎn);若A 1->0 時(shí),B 1->0 反轉(zhuǎn)
if(EC11_A_Now == 1) //EC11_A和上一次狀態(tài)相比,為上升沿
{
if((EC11_B_Last == 1)&&(EC11_B_Now == 0)) //EC11_B和上一次狀態(tài)相比,為下降沿
ScanResult = 1; //正轉(zhuǎn)
if((EC11_B_Last == 0)&&(EC11_B_Now == 1)) //EC11_B和上一次狀態(tài)相比,為上升沿
ScanResult = 8; //反轉(zhuǎn)
//>>>>>>>>>>>>>>>>下面為正轉(zhuǎn)一次再反轉(zhuǎn)或反轉(zhuǎn)一次再正轉(zhuǎn)處理<<<<<<<<<<<<<<<<//
if((EC11_B_Last == EC11_B_Now)&&(EC11_B_Now == 0)) //A上升沿時(shí),采集的B不變且為0
ScanResult = 1; //正轉(zhuǎn)
if((EC11_B_Last == EC11_B_Now)&&(EC11_B_Now == 1)) //A上升沿時(shí),采集的B不變且為1
ScanResult = 8; //反轉(zhuǎn)
}
else //EC11_A和上一次狀態(tài)相比,為下降沿
{
if((EC11_B_Last == 1)&&(EC11_B_Now == 0)) //EC11_B和上一次狀態(tài)相比,為下降沿
ScanResult = 8; //反轉(zhuǎn)
if((EC11_B_Last == 0)&&(EC11_B_Now == 1)) //EC11_B和上一次狀態(tài)相比,為上升沿
ScanResult = 1; //正轉(zhuǎn)
//>>>>>>>>>>>>>>>>下面為正轉(zhuǎn)一次再反轉(zhuǎn)或反轉(zhuǎn)一次再正轉(zhuǎn)處理<<<<<<<<<<<<<<<<//
if((EC11_B_Last == EC11_B_Now)&&(EC11_B_Now == 0)) //A上升沿時(shí),采集的B不變且為0
ScanResult = 8; //反轉(zhuǎn)
if((EC11_B_Last == EC11_B_Now)&&(EC11_B_Now == 1)) //A上升沿時(shí),采集的B不變且為1
ScanResult = 1; //正轉(zhuǎn)
}
EC11_A_Last = EC11_A_Now; //更新編碼器上一個(gè)狀態(tài)暫存變量
EC11_B_Last = EC11_B_Now; //更新編碼器上一個(gè)狀態(tài)暫存變量
}
}
if(EC11_Key == 0) //如果EC11的按鍵按下,并且沒有EC11沒有轉(zhuǎn)動(dòng),
{
// if(ScanResult == 0) //按下按鍵時(shí)未轉(zhuǎn)動(dòng)
ScanResult = 2; //返回值為2
// else
// {
// if(ScanResult == 1) //按下按鍵時(shí)候正轉(zhuǎn)
// ScanResult = 3; //返回值為3
// if(ScanResult == 8) //按下按鍵時(shí)候反轉(zhuǎn)
// ScanResult = 9; //返回值為-3
// }
}
return ScanResult; //返回值的取值: 0:無(wú)動(dòng)作; 1:正轉(zhuǎn); 8:反轉(zhuǎn);
} // 2:只按下按鍵; 3:按著按鍵正轉(zhuǎn); 9:按著按鍵反轉(zhuǎn)
#ifndef __ec11_H
#define __ec11_H
#include "sys.h"
#include "stm32f10x.h"
//----------------IO口定義----------------//
#define EC11_A_Now PBin(9) //EC11的A引腳,視為時(shí)鐘線
#define EC11_B_Now PBin(8) //EC11的B引腳,視為信號(hào)線
#define EC11_Key PBin(7) //EC11的按鍵
//----------------編碼器動(dòng)作代碼相關(guān)定義----------------//
static unsigned char EC11_NUM_SW = 0;
//----------------編碼器參數(shù)微調(diào)宏定義----------------//
#define EC11_SCAN_PERIOD_MS 1 //EC11編碼器掃描周期
#define KEY_COUNT_DESHAKING ( 10/EC11_SCAN_PERIOD_MS) //按鍵消抖時(shí)間
#define KEY_COUNT_LONGTIME (150/EC11_SCAN_PERIOD_MS) //長(zhǎng)按按鍵判斷時(shí)間
#define KEY_COUNT_DUALCLICKTIME (150/EC11_SCAN_PERIOD_MS) //雙擊按鍵判斷時(shí)間
#define KEY_LONG_REPEAT_TIME (200/EC11_SCAN_PERIOD_MS) //長(zhǎng)按按鍵的回報(bào)率的倒數(shù),即一直長(zhǎng)按按鍵時(shí)響應(yīng)的時(shí)間間隔
//----------------局部文件內(nèi)變量列表----------------//
static char EC11_A_Last = 0; //EC11的A引腳上一次的狀態(tài)
static char EC11_B_Last = 0; //EC11的B引腳上一次的狀態(tài)
static char EC11_Type = 1; //定義變量暫存EC11的類型---->>>>---- 0:一定位對(duì)應(yīng)一脈沖; 1:兩定位對(duì)應(yīng)一脈沖
//所謂一定位對(duì)應(yīng)一脈沖,是指EC11旋轉(zhuǎn)編碼器每轉(zhuǎn)動(dòng)一格,A和B都會(huì)輸出一個(gè)完整的方波。
//而 兩定位對(duì)應(yīng)一脈沖,是指EC11旋轉(zhuǎn)編碼器每轉(zhuǎn)動(dòng)兩格,A和B才會(huì)輸出一個(gè)完整的方波,只轉(zhuǎn)動(dòng)一格只輸出A和B的上升沿或下降沿
static int EC11_KEY_COUNT = 0; //EC11按鍵動(dòng)作計(jì)數(shù)器
static int EC11_KEY_DoubleClick_Count = 0; //EC11按鍵雙擊動(dòng)作計(jì)數(shù)器
static char FLAG_EC11_KEY_ShotClick = 0; //EC11按鍵短按動(dòng)作標(biāo)志
static char FLAG_EC11_KEY_LongClick = 0; //EC11按鍵長(zhǎng)按動(dòng)作標(biāo)志
static char FLAG_EC11_KEY_DoubleClick = 0; //EC11按鍵雙擊動(dòng)作標(biāo)志
//----------------函數(shù)快速調(diào)用(復(fù)制粘貼)列表----------------//
//
/*******************************************************************
void Encoder_EC11_Init(unsigned char Set_EC11_TYPE); //初始化EC11旋轉(zhuǎn)編碼器IO口和類型以及變量初始化
char Encoder_EC11_Scan(); //掃描旋轉(zhuǎn)編碼器的動(dòng)作
void Encoder_EC11_Analyze(char EC11_Value); //分析EC11旋轉(zhuǎn)編碼器的動(dòng)作以及動(dòng)作處理代碼
******************************************************************/
//-------->>>>>>>>--------注意事項(xiàng):EC11旋轉(zhuǎn)編碼器的掃描時(shí)間間隔控制在1~4ms之間,否則5ms及以上的掃描時(shí)間在快速旋轉(zhuǎn)時(shí)可能會(huì)誤判旋轉(zhuǎn)方向--------<<<<<<<<--------//
//-------->>>>>>>>--------注意事項(xiàng):EC11旋轉(zhuǎn)編碼器的掃描時(shí)間間隔控制在1~4ms之間,否則5ms及以上的掃描時(shí)間在快速旋轉(zhuǎn)時(shí)可能會(huì)誤判旋轉(zhuǎn)方向--------<<<<<<<<--------//
//-------->>>>>>>>--------注意事項(xiàng):EC11旋轉(zhuǎn)編碼器的掃描時(shí)間間隔控制在1~4ms之間,否則5ms及以上的掃描時(shí)間在快速旋轉(zhuǎn)時(shí)可能會(huì)誤判旋轉(zhuǎn)方向--------<<<<<<<<--------//
//----------------函數(shù)聲明列表----------------//
//
//*******************************************************************/
//功能:初始化EC11旋轉(zhuǎn)編碼器相關(guān)參數(shù)
//形參:EC11旋轉(zhuǎn)編碼器的類型-->> unsigned char Set_EC11_TYPE <<-- :0----一定位對(duì)應(yīng)一脈沖;1(或非0)----兩定位對(duì)應(yīng)一脈沖。
//返回:無(wú)
//詳解:對(duì)EC11旋轉(zhuǎn)編碼器的連接IO口做IO口模式設(shè)置。以及將相關(guān)的變量進(jìn)行初始化
//*******************************************************************/
void EC11_Init(unsigned char Set_EC11_TYPE);
//*******************************************************************/
//功能:掃描EC11旋轉(zhuǎn)編碼器的動(dòng)作并將參數(shù)返回給動(dòng)作分析函數(shù)使用
//形參:EC11旋轉(zhuǎn)編碼器的類型-->> unsigned char Set_EC11_TYPE <<-- :0----一定位對(duì)應(yīng)一脈沖;1(或非0)----兩定位對(duì)應(yīng)一脈沖
//返回:EC11旋轉(zhuǎn)編碼器的掃描結(jié)果-->> char ScanResult -->> 0:無(wú)動(dòng)作;1:正轉(zhuǎn); -1:反轉(zhuǎn);2:只按下按鍵;3:按著按鍵正轉(zhuǎn);-3:按著按鍵反轉(zhuǎn)
//詳解:只掃描EC11旋轉(zhuǎn)編碼器有沒有動(dòng)作,不關(guān)心是第幾次按下按鍵或長(zhǎng)按或雙擊。返回值直接作為形參傳給 [ void Encoder_EC11_Analyze(char EC11_Value); ] 函數(shù)使用
//*******************************************************************/
char Encoder_EC11_Scan(void);
//*******************************************************************/
//功能:對(duì)EC11旋轉(zhuǎn)編碼器的動(dòng)作進(jìn)行分析,并作出相應(yīng)的動(dòng)作處理代碼
//形參:無(wú)
//返回:char AnalyzeResult = 0;目前無(wú)用。若在該函數(shù)里做了動(dòng)作處理,則函數(shù)的返回值無(wú)需理會(huì)
//詳解:對(duì)EC11旋轉(zhuǎn)編碼器的動(dòng)作進(jìn)行模式分析,是單擊還是雙擊還是長(zhǎng)按松手還是一直按下。形參從 [ char Encoder_EC11_Scan(unsigned char Set_EC11_TYPE) ] 函數(shù)傳入。在本函數(shù)內(nèi)修改需要的動(dòng)作處理代碼
//*******************************************************************/
char Encoder_EC11_Analyze(char EC11_Value);
#endif
這個(gè)程序我只做了正轉(zhuǎn),反轉(zhuǎn)和按下,有需要自行修改,我這里利用的是定時(shí)器1毫秒掃描,所以刷新函數(shù)Encoder_EC11_Analyze(Encoder_EC11_Scan());
我寫在中斷里面,初始化函數(shù) EC11_Init(1);
在這里需要注意一定位對(duì)應(yīng)一脈沖;1(或非0)----兩定位對(duì)應(yīng)一脈沖,前面有說(shuō)過(guò)了,放心食用文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-781068.html
轉(zhuǎn)自:https://www.jianshu.com/p/41fa67ecb248文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-781068.html
到了這里,關(guān)于STM32 EC11 旋轉(zhuǎn)編碼器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!