標題: EC11增量型脈沖數(shù)字電位器單片機驅(qū)動程序 [打印本頁]

作者: datouyuan    時間: 2022-6-14 16:45
標題: EC11增量型脈沖數(shù)字電位器單片機驅(qū)動程序
論壇里的代碼都是用定時掃描端口的,沒有一例采用外中斷或端口變化中斷的。這種方法占用mcu時間極少,適用面廣(0~MHz級),代碼簡短,極其可靠。

單片機源程序如下:
  1. /*
  2. 所有微芯系mcu(例如PIC、九齊、義隆等)都有引腳變化中斷。
  3. 十速51mcu的P1有引腳變化中斷。
  4. PIN_A P10  開啟引腳變化中斷,可接P1任意端口P1x。
  5. PIN_B P11  不開啟引腳變化中斷,可接任意端口Pxx。
  6. */
  7. //只開啟一個引腳(PIN_A)變化中斷
  8. volatile u8 gPosition; // EC11 8位足夠。如需定位應(yīng)用,16位32位都有可能。
  9. u8 gPositionOld;
  10. void p1_change_int(void) interrupt 8
  11. { //加消抖電容,減少mcu開銷
  12.         bit bZZ = 0;//使用該臨時變量是為了加快端口讀取過程
  13.         if (PIN_A)
  14.         {//上跳
  15.                 if (!PIN_B)
  16.                         bZZ = 1;
  17.         }
  18.         else
  19.         {//下跳
  20.                 if (PIN_B)
  21.                         bZZ = 1;
  22.         }
  23.         if (bZZ)
  24.                 gPosition++; //正傳
  25.         else
  26.                 gPosition--; //反轉(zhuǎn)
  27.         INTFLG = 0;                 //清除變化中斷
  28. }

  29. void EC11_init(void)
  30. {
  31.         //開啟P10引腳變化中斷
  32.         gPositionOld=gPosition;
  33. }

  34. void EC11_Scan(void)
  35. {//定時執(zhí)行,選擇合適定時使任何時候(step<2)
  36.         u8 step=gPosition-gPositionOld;
  37.         if(0==step) return;
  38.         gPositionOld=gPosition;
  39.         if(step&0x80){
  40.                 step=0-step;
  41.                 //反轉(zhuǎn)處理 step為步數(shù)
  42.         }
  43.         else{
  44.                 //正傳處理 step為步數(shù)
  45.         }
  46. }
復制代碼




作者: 人人學會單片機    時間: 2022-6-15 11:35
//**********************************---祁緒電子---2020年5月 *************
// 按鍵或者旋轉(zhuǎn)編碼器 底層驅(qū)動 加減函數(shù)
//*********************************************************************
void ROTARY_ROTARY_Scan_Drive(void)
{
        static xdata u8 count=0,Rotary_Flag=0;
        if(count>30)
        {
                count=0;
                if((ROTARY_B==0)&&(Rotary_Flag==0))                        //如果按鍵B按下,且flag是0       
                {
                        Rotary_Flag=1;
                        Rotary_Read_Data_Rotary++;                                //按鍵值增加1
                        if(Rotary_Read_Data_Rotary>Key_MAX)                //如果大于最大值 跳回0
                        {
                                Rotary_Read_Data_Rotary=Key_MIN;
                        }
                }
                if((ROTARY_A==0)&&(Rotary_Flag==0))                        //如果按鍵A按下,且flag是0       
                {
                        Rotary_Flag=1;
                        Rotary_Read_Data_Rotary--;                                //按鍵值減少1
                        if(Rotary_Read_Data_Rotary<Key_MIN)                //如果按鍵值等于0,跳回最大值
                        {
                                Rotary_Read_Data_Rotary=Key_MAX;
                        }
                }
                if((ROTARY_B!=0)&&(ROTARY_A!=0))                        //按鍵必須釋放,下次按鍵才有效
                {
                        Rotary_Flag=0;
                }
        }
        count++;
}

EC11很簡單 主函數(shù)不斷的掃描這個函數(shù) 就行了  ,兩個按鍵和EC11通用這段代碼
作者: Y_G_G    時間: 2022-6-15 16:12
為什么要節(jié)省MCU占用時間?是真的一個EC11讓整個程序停滯不前了嗎?有必要去省下那點時間嗎?
更多的時候,加一個電容才是不可取的.明明可以不要這個電容的,你卻要加電容?
自己DIY點小玩意玩玩也就無所謂了,批量的產(chǎn)品,一個一分錢的電容都是一個敏感的成本,而這個成本的增加只是不想讓單片機太累而已
作者: datouyuan    時間: 2022-6-16 09:29
Y_G_G 發(fā)表于 2022-6-15 16:12
為什么要節(jié)省MCU占用時間?是真的一個EC11讓整個程序停滯不前了嗎?有必要去省下那點時間嗎?
更多的時候,加 ...

EC11這種超慢速設(shè)備,可靠性不做要求的設(shè)備,好像隨便寫都能達到要求。
但節(jié)省MCU占用時間,總比浪費要好吧(可讓改代碼用于極低主頻的mcu)。
并且這個節(jié)省還附帶了提高可靠性、代碼簡單,方便易用等好處。

我這代碼天然自帶消抖,這個電容不是必須,但有了這電容,mcu主頻可工作于10kHz。
作者: datouyuan    時間: 2022-6-16 09:47
本帖最后由 datouyuan 于 2022-6-16 09:52 編輯
Y_G_G 發(fā)表于 2022-6-15 16:12
為什么要節(jié)省MCU占用時間?是真的一個EC11讓整個程序停滯不前了嗎?有必要去省下那點時間嗎?
更多的時候,加 ...

假如這個EC11速度快了1000倍,并且還不允許丟步,掃描法還能不能用?
而用中斷法的方式,代碼不做修改還能用。


作者: Y_G_G    時間: 2022-6-16 20:04
datouyuan 發(fā)表于 2022-6-16 09:29
EC11這種超慢速設(shè)備,可靠性不做要求的設(shè)備,好像隨便寫都能達到要求。
但節(jié)省MCU占用時間,總比浪費要 ...

關(guān)鍵節(jié)省MCU時間來干嘛呢?總覺得提高MCU效率是件好事,可關(guān)鍵是這用得著嗎?如果不是極端條件下,這種"優(yōu)化"一點意義都沒有,自己知道怎么優(yōu)化就行,并不需要每次都要優(yōu)化的
而且,用外部中斷的辦法并不是適用所有情況,因為大多的單片機,外部中斷有最高等級的中斷,它會打斷其它所有的中斷,不知道你看過EC11的波形沒有,它轉(zhuǎn)動一次,新的EC11抖動有五六下,電平就固定了,如果是用了很久的時間,它抖動有上百次的,以你的代碼,會直接打斷其它程序上百次,你試想一下,比如有波特率高點的串口,你能保證數(shù)據(jù)手準確性?又或者是再去更改一下中斷優(yōu)先等級?
作者: GodWorks    時間: 2022-6-17 08:04
學習學習學習,每天進步一點點
作者: datouyuan    時間: 2022-6-17 11:55
Y_G_G 發(fā)表于 2022-6-16 20:04
關(guān)鍵節(jié)省MCU時間來干嘛呢?總覺得提高MCU效率是件好事,可關(guān)鍵是這用得著嗎?如果不是極端條件下,這種"優(yōu)化" ...

你有幾條最基本的錯誤:
1.提高MCU效率,節(jié)約mcu的占用時間當然是好事。
2.中斷就是要打斷程序,甚至頻繁打斷。假如中斷會對其它功能造成影響,最主要的解決辦法是減少相關(guān)代碼的占用時間,例如提高賣出主頻、提高代碼效率。
3.外部中斷雖是最高等級(非嵌入式優(yōu)先級)的中斷,但它只會打斷嵌入式優(yōu)先級比它低的中斷。


在你說的極其惡劣環(huán)境下,甚至還差,我這代碼能保證波特率高點的串口數(shù)據(jù)準確性,并且還保證了ec11的可靠性。這可靠性就是靠減少mcu占用時間保證的。
作者: datouyuan    時間: 2022-6-17 15:00
本帖最后由 datouyuan 于 2022-6-17 15:08 編輯
3.外部中斷雖是最高等級(非嵌入式優(yōu)先級)的中斷,但它只會打斷嵌入式優(yōu)先級比它低的中斷。

你對很多基本知識有錯誤理解,我表達能力又不好,所以多啰嗦幾句。
1.遠古51嵌入式優(yōu)先級有2級,現(xiàn)在很多51嵌入式優(yōu)先級有4級。
2.相同嵌入優(yōu)先級的中斷同時發(fā)生時,mcu會先處理普通優(yōu)先級高的中斷,但不會打斷正在處理的中斷。提高代碼效率,減少mcu占用時間,能處理更多的中斷。
3.你所說的“外部中斷有最高等級的中斷,它會打斷其它所有的中斷”不會發(fā)生,因為你不特意調(diào)整嵌入式優(yōu)先級的話,外部中斷的嵌入優(yōu)先級是最低的。
4.使用中斷解決問題是單片機初學者必須掌握的技能,該整理下你的知識體系了。
5.一直圍繞著基礎(chǔ)討論,卻忽略了我這簡單代碼的精妙之處,希望你能仔細體會。

作者: 51黑電子會員    時間: 2023-9-12 18:42
人人學會單片機 發(fā)表于 2022-6-15 11:35
//**********************************---祁緒電子---2020年5月 *************
// 按鍵或者旋轉(zhuǎn)編碼器 底 ...

count這個變量咋么計數(shù)  定時器計數(shù)  還是旋轉(zhuǎn)編碼開關(guān)旋動就抖動計數(shù)
作者: yanggo    時間: 2023-10-27 15:40
雖然不會軟件,但能不用增加產(chǎn)品成本,就不要增加產(chǎn)品成本,畢竟消費電子對成本比較敏感,老板來了句,為什么別人的可以做這么便宜?你的又要這個電容那個電容的……你不吐血?能解決項目工程的問題就好。
作者: lzzasd    時間: 2023-10-28 10:10
yanggo 發(fā)表于 2023-10-27 15:40
雖然不會軟件,但能不用增加產(chǎn)品成本,就不要增加產(chǎn)品成本,畢竟消費電子對成本比較敏感,老板來了句,為什 ...

你這個說法不敢茍同   如果節(jié)省一兩個貼片電容就可以節(jié)省成本的話我無話可說    節(jié)省的途徑是以高可靠設(shè)計電路來節(jié)省使用元器件    試問你的功能都不穩(wěn)定節(jié)省這兩個電容有什么意義??   使用者使用時數(shù)字亂竄是什么使用體驗??   還有設(shè)計的原則是程序盡可能優(yōu)化   寧愿讓MCU空轉(zhuǎn)也不能讓他堵塞運行
作者: hi等你    時間: 2023-10-30 10:47


這種數(shù)字電位器我也用了幾年了,從來不用防抖和電容,也不用中斷,中斷用在逐個點亮數(shù)碼管

我覺得保障顯示正常很重要,這電位器兩腳從00變化到01的時間對于主程序來說太漫長了,

把中斷用在編碼器也太浪費,我的程序大多數(shù)時間都是閑置狀態(tài)和軟件讀取數(shù)字電位器兩腳狀態(tài)

作者: shennognshi    時間: 2024-1-5 13:07
贊同樓主的理念!有的人的思維邏輯和你奇怪,如果你說人用兩條腿走路比較好,他都會提出殘疾人沒有兩條腿怎么走這樣類似的反駁理由。中斷不夠用你就用輪訓唄!中斷多余的話,用中斷不是挺好的嗎?至于用不用電容,你買產(chǎn)品的時候一定希望產(chǎn)品里用電容吧,怎么你是制造者了就不想用電容了?匠心何在?
作者: shennognshi    時間: 2024-1-8 11:03
今天實測樓主的中斷方式檢測EC11的轉(zhuǎn)動,不好用!主要是判斷結(jié)果里正傳中夾雜反轉(zhuǎn)、反轉(zhuǎn)中夾雜正轉(zhuǎn)!一開始分析程序,發(fā)現(xiàn)對于一個U8變量step,你來一句“step=0-step;”就令人費解。以下是我的代碼,同樣采取中斷,結(jié)果非常準確穩(wěn)定,能完整輸出當前轉(zhuǎn)動方向和累計計數(shù)值(正轉(zhuǎn)增大數(shù)值,反轉(zhuǎn)減小數(shù)值),通過方向和計數(shù)就可用于特定的功能設(shè)計了。代碼對EC11的A腳進行中斷響應(yīng)(下降沿檢測),響應(yīng)函數(shù)為:
void EC11_Change_Interupt(){
  static bool prev_A = 0;//必須為static!或者定義為一般的全局變量
  volatile bool curr_A = digitalRead(EC11_A);
  volatile bool curr_B = digitalRead(EC11_B);
  if((prev_A == 0) && (curr_A == 1)){
    if(curr_B == 0){
      count = count - 1;
      direction = 0;
    }
    else{
      count = count + 1;
      direction = 1;
    }
  }
  else if((prev_A == 1) && (curr_A == 0)){
    if(curr_B == 0){
      count = count + 1;
      direction = 1;
    }
    else{
      count = count - 1;
      direction = 0;
    }
  }
  prev_A = curr_A;
  if(direction){
    Serial1.println((String("正轉(zhuǎn):") + String(count)));
  }
  else{
    Serial1.println((String("反轉(zhuǎn):") + String(count)));
  }
}

對于SW腳,也可以通過下降沿中斷,使count歸零。以上代碼由圖形化軟件轉(zhuǎn)化而來,可能比較累贅,可以適當去掉一些強制轉(zhuǎn)換和括號。




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1