久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標題: 自鎖和非自鎖開關在單片機程序中用法? [打印本頁]

作者: lch327    時間: 2024-12-1 21:13
標題: 自鎖和非自鎖開關在單片機程序中用法?
51單片機控制燈亮滅:用一個非自鎖開關控制2個燈亮滅,當做總開關K總,再分別用2個自鎖按鍵開關K1,K2控制這2個燈LED1,LED2亮滅。這種組合開關的用法程序怎么寫呢?

K總合上,K1,K2才起作用。K總斷開,K1,K2不起作用。K總合上時,2個燈都亮,然后K1,K2可以分別控制亮滅。K總斷開后,K1,K2延時10秒滅。

作者: lkc8210    時間: 2024-12-1 21:13
lch327 發表于 2024-12-2 22:15
K總開關觸發后,2個燈就亮了,然后再用分開關K1,,K2按鍵控制亮滅,然后不管燈亮滅,只要關斷K總,2個燈 ...

你一開始這么說就不用改那么多次
  1. #include <REG52.h>

  2. // 定義類型別名
  3. typedef unsigned char u8;  // 0 到 255
  4. typedef unsigned int u16;   // 0 到 65535

  5. // 延時函數,產生約 50 毫秒的延時
  6. void Delay50ms(void) //@11.0592MHz
  7. {
  8.     unsigned char data i, j; // 定義循環變量

  9.     i = 90;  // 外層循環次數
  10.     j = 163; // 內層循環次數
  11.     do
  12.     {
  13.         while (--j); // 內層循環
  14.     }
  15.     while (--i); // 外層循環
  16. }

  17. // 定義按鍵和 LED 引腳
  18. sbit Kzong = P3^1; // 總按鍵連接到 P3.1
  19. sbit K1 = P3^2;    // 按鍵 1 連接到 P3.2
  20. sbit K2 = P3^3;    // 按鍵 2 連接到 P3.3
  21. sbit LED1 = P2^0;  // LED1 連接到 P2.0
  22. sbit LED2 = P2^1;  // LED2 連接到 P2.1

  23. u8 Off_Delay = 0;  // 關燈延時計數器,初始化為 0

  24. void main()
  25. {
  26.     while(1) // 主循環
  27.     {
  28.         if(Kzong == 0) // 如果總按鍵被按下
  29.         {
  30.             if(Off_Delay == 0) // 如果延時計數器為 0
  31.             {
  32.                 LED1 = 0; // 開啟 LED1
  33.                 LED2 = 0; // 開啟 LED2
  34.             }
  35.             if(K1 == 0) // 如果按鍵 1 被按下
  36.             {
  37.                 Delay50ms(); // 延時 50ms
  38.                 if(K1 == 0) // 確認按鍵 1 仍被按下
  39.                 {
  40.                     LED1 = !LED1; // 切換 LED1 狀態
  41.                     while(K1 == 0); // 等待按鍵 1 釋放
  42.                 }
  43.             }
  44.             if(K2 == 0) // 如果按鍵 2 被按下
  45.             {
  46.                 Delay50ms(); // 延時 50ms
  47.                 if(K2 == 0) // 確認按鍵 2 仍被按下
  48.                 {
  49.                     LED2 = !LED2; // 切換 LED2 狀態
  50.                     while(K2 == 0); // 等待按鍵 2 釋放
  51.                 }
  52.             }
  53.             Off_Delay = 200; // 設置關燈延時計數器為 200
  54.         }
  55.         else // 如果總按鍵沒有被按下
  56.         {
  57.             if(Off_Delay != 0) // 如果延時計數器不為 0
  58.             {
  59.                 Delay50ms(); // 延時 50ms
  60.                 Off_Delay = Off_Delay - 1; // 遞減延時計數器
  61.                 if(Off_Delay == 0) // 如果計數器減到 0
  62.                 {
  63.                     LED1 = 1; // 熄滅 LED1
  64.                     LED2 = 1; // 熄滅 LED2
  65.                 }
  66.             }
  67.         }
  68.     }
  69. }
復制代碼

作者: 188610329    時間: 2024-12-1 22:03
delay 函數你應該自己會寫吧?

bit  Off_Delay;
void  main()
{
     while(1)
     {
          if(Kzong == 0)
          {
                LED1 = K1;
                LED2 = K2;
                Off_Delay = 1;
          }
          else
         {
                 if(Off_Delay == 1)
                 {
                        Off_Delay  = 0;
                        delay_Sec(10);
                        LED1  = 1;
                        LED2  = 1;
                 }
         }
     }
}
作者: lkc8210    時間: 2024-12-1 23:20
本帖最后由 lkc8210 于 2024-12-2 11:10 編輯

稍修一下
重開不用等10秒
  1. u8  Off_Delay = 0;
  2. void  main()
  3. {
  4.         while(1)
  5.         {
  6.                 if(Kzong == 0)
  7.                 {
  8.                         LED1 = K1;
  9.                         LED2 = K2;
  10.                         Off_Delay = 200;
  11.                 }
  12.                 else
  13.                 {
  14.                         if(Off_Delay)
  15.                         {
  16.                                 if(--Off_Delay==0)
  17.                                 {
  18.                                         LED1  = 1;
  19.                                         LED2  = 1;
  20.                                 }
  21.                                 delay_ms(50);
  22.                         }
  23.                 }
  24.         }
  25. }
復制代碼

作者: xiaobendan001    時間: 2024-12-2 08:03
開關畫的不太對吧,K1K2好像表示非自鎖才比較合適吧
作者: man1234567    時間: 2024-12-2 08:47
“K總斷開后,K1,K2延時10秒滅”是K總斷開后,無論K1,K2是亮是滅都要亮起延時10秒滅 ?
作者: lch327    時間: 2024-12-2 10:11
man1234567 發表于 2024-12-2 08:47
“K總斷開后,K1,K2延時10秒滅”是K總斷開后,無論K1,K2是亮是滅都要亮起延時10秒滅 ?

不需要再亮起,只要給一個滅的指令就行,滅的 狀態不管,保持原樣,亮的 狀態滅掉就行了。
作者: lch327    時間: 2024-12-2 10:16
xiaobendan001 發表于 2024-12-2 08:03
開關畫的不太對吧,K1K2好像表示非自鎖才比較合適吧

K1,K2就是按鍵開關,屬于非自鎖開關。我畫的不好。
作者: lch327    時間: 2024-12-2 10:27
K總應該是自鎖開關,K1,K2是非自鎖按鍵開關,說錯了。不好意思。
作者: xiaobendan001    時間: 2024-12-2 11:12
lch327 發表于 2024-12-2 10:27
K總應該是自鎖開關,K1,K2是非自鎖按鍵開關,說錯了。不好意思。

原來是說反了,不是畫反了
作者: xiaobendan001    時間: 2024-12-2 11:13
lch327 發表于 2024-12-2 10:27
K總應該是自鎖開關,K1,K2是非自鎖按鍵開關,說錯了。不好意思。

那你這個延時是K總觸發的,這不是沒有啥意義了?平時K1K2都是斷開的,燈也不亮啊
作者: lch327    時間: 2024-12-2 12:03
188610329 發表于 2024-12-1 22:03
delay 函數你應該自己會寫吧?

bit  Off_Delay;

不好意思,開關表達錯了,應該K總是自鎖開關,K1,K2是非自鎖按鍵開關。所以這個程序K1,K2按下時燈滅,可是抬起時燈又亮了。應該抬起是還保持滅的狀態 ,再按一下燈亮,抬起時保持不變。
作者: lch327    時間: 2024-12-2 14:01
188610329 發表于 2024-12-1 22:03
delay 函數你應該自己會寫吧?

bit  Off_Delay;

經過試驗,還是不行。
作者: xiaobendan001    時間: 2024-12-2 17:37
描述不對,K1K2不是按下去燈亮,松開燈滅,而是在K總接通的情況下,按一下改變一下燈的狀態。
K總斷開后,如果燈亮就延時滅,不亮就不管了。
作者: lkc8210    時間: 2024-12-2 21:01
lch327 發表于 2024-12-2 12:03
不好意思,開關表達錯了,應該K總是自鎖開關,K1,K2是非自鎖按鍵開關。所以這個程序K1,K2按下時燈滅, ...
  1. u8  Off_Delay = 0;
  2. void  main()
  3. {
  4.         while(1)
  5.         {
  6.                 if(Kzong == 0)
  7.                 {
  8.                         if(!K1)
  9.                         {
  10.                                 delay_ms(50);
  11.                                 if(!K1)
  12.                                 {
  13.                                         LED1=!LED1;
  14.                                         while(!K1);
  15.                                 }
  16.                         }
  17.                         if(!K2)
  18.                         {
  19.                                 delay_ms(50);
  20.                                 if(!K2)
  21.                                 {
  22.                                         LED2=!LED2;
  23.                                         while(!K2);
  24.                                 }
  25.                         }
  26.                         Off_Delay = 200;
  27.                 }
  28.                 else
  29.                 {
  30.                         if(Off_Delay)
  31.                         {
  32.                                 if(--Off_Delay==0)
  33.                                 {
  34.                                         LED1  = 1;
  35.                                         LED2  = 1;
  36.                                 }
  37.                                 delay_ms(50);
  38.                         }
  39.                 }
  40.         }
  41. }
復制代碼

作者: lch327    時間: 2024-12-2 21:40
xiaobendan001 發表于 2024-12-2 17:37
描述不對,K1K2不是按下去燈亮,松開燈滅,而是在K總接通的情況下,按一下改變一下燈的狀態。
K總斷開后, ...

對,對,對,感謝理解我的意思,就是您說的這樣。我以為描述清楚了,實際容易誤解,您說的準確。
作者: lch327    時間: 2024-12-2 22:15
xiaobendan001 發表于 2024-12-2 11:13
那你這個延時是K總觸發的,這不是沒有啥意義了?平時K1K2都是斷開的,燈也不亮啊

K總開關觸發后,2個燈就亮了,然后再用分開關K1,,K2按鍵控制亮滅,然后不管燈亮滅,只要關斷K總,2個燈是滅的狀態就行了。
作者: lch327    時間: 2024-12-2 22:28
lkc8210 發表于 2024-12-1 23:20
稍修一下
重開不用等10秒

能寫一個完整的嗎?U8是什么意思,(--off_Delay==0)是什么意思啊?看不懂,能注釋一下嗎?
作者: lch327    時間: 2024-12-2 23:25
lkc8210 發表于 2024-12-2 21:01

能寫一個完整的嗎?U8是什么意思,(--off_Delay==0)是什么意思啊?看不懂,能注釋一下嗎?
作者: xiaobendan001    時間: 2024-12-3 07:25
lch327 發表于 2024-12-2 23:25
能寫一個完整的嗎?U8是什么意思,(--off_Delay==0)是什么意思啊?看不懂,能注釋一下嗎?

看起來C你是一點不懂啊,還是先看看書吧,代碼都給你了你都看不懂啊
作者: 188610329    時間: 2024-12-3 21:32
lkc8210 發表于 2024-12-3 09:19
你一開始這么說就不用改那么多次

代碼有個小漏洞,假定 K1 / K2 年久失修,容易按下后卡住,不一定能彈起, 此時 Kzong 會失效,建議,按下后,不要等待彈起,而是標記“未彈起”,在“未彈起”標記被清除前,不再判斷按鍵按下。
沒特別意思,屬于職業習慣的強迫癥。發現有漏洞,不說就難受。
作者: lch327    時間: 2024-12-4 17:07
188610329 發表于 2024-12-3 21:32
代碼有個小漏洞,假定 K1 / K2 年久失修,容易按下后卡住,不一定能彈起, 此時 Kzong 會失效,建議,按下 ...

經過試驗,確實有這個問題,假如常按K1或K2不松手,K總就不起作用了,一直在那里死循環了。可程序具體怎么改能實現呢?我看一些教學里,也不提K1,K2卡住的問題啊。那屬于硬件故障吧。教學里沒考慮這個問題。如果按鍵壞了,肯定就得換按鍵,保證它是完好的。
作者: lch327    時間: 2024-12-4 18:03
lkc8210 發表于 2024-12-1 21:13
你一開始這么說就不用改那么多次

感謝您的解答,困擾我多日的問題解決了。我是新手,單片機愛好者,望您以后多多指教。十分感謝!!!
作者: xiaobendan001    時間: 2024-12-4 18:18
lch327 發表于 2024-12-4 17:07
經過試驗,確實有這個問題,假如常按K1或K2不松手,K總就不起作用了,一直在那里死循環了。可程序具體怎 ...

做個演示沒問題,控制個燈光也不打緊,如果是涉及安全性問題,不能使用這種死等的方式了,做為實用產品,必須方方面面考慮到各種可能出現的情況。
作者: lkc8210    時間: 2024-12-5 00:03
lch327 發表于 2024-12-4 17:07
經過試驗,確實有這個問題,假如常按K1或K2不松手,K總就不起作用了,一直在那里死循環了。可程序具體怎 ...

非死等版本
  1. #include <REG52.h>

  2. // 定義類型別名
  3. typedef unsigned char u8;  // 0 到 255
  4. typedef unsigned int u16;   // 0 到 65535

  5. // 延時函數,產生約 50 毫秒的延時
  6. void Delay50ms(void) //@11.0592MHz
  7. {
  8.     unsigned char data i, j; // 定義循環變量

  9.     i = 90;  // 外層循環次數
  10.     j = 163; // 內層循環次數
  11.     do
  12.     {
  13.         while (--j); // 內層循環
  14.     }
  15.     while (--i); // 外層循環
  16. }

  17. // 定義按鍵和 LED 引腳
  18. sbit Kzong = P3^1; // 總按鍵連接到 P3.1
  19. sbit K1 = P3^2;    // 按鍵 1 連接到 P3.2
  20. sbit K2 = P3^3;    // 按鍵 2 連接到 P3.3
  21. sbit LED1 = P2^0;  // LED1 連接到 P2.0
  22. sbit LED2 = P2^1;  // LED2 連接到 P2.1

  23. u8 Off_Delay = 0;  // 關燈延時計數器,初始化為 0

  24. void main()
  25. {
  26.         bit K1_Lock = 1;
  27.         bit K2_Lock = 1;
  28.     while(1) // 主循環
  29.     {
  30.         if(Kzong == 0) // 如果總按鍵被按下
  31.         {
  32.             if(Off_Delay == 0) // 如果延時計數器為 0
  33.             {
  34.                 LED1 = 0; // 開啟 LED1
  35.                 LED2 = 0; // 開啟 LED2
  36.             }
  37.                         if(K1 == 0 && K1_Lock ==1) //下降沿觸發
  38.                         {
  39.                                 LED1 = !LED1; // 切換 LED1 狀態
  40.                         }
  41.                         K1_Lock = L1;
  42.                         if(K2 == 0 && K2_Lock ==1) //下降沿觸發
  43.                         {
  44.                                 LED2 = !LED2; // 切換 LED1 狀態
  45.                         }
  46.                         K2_Lock = L2;
  47.             Delay50ms(); // 延時 50ms
  48.             Off_Delay = 200; // 設置關燈延時計數器為 200
  49.         }
  50.         else // 如果總按鍵沒有被按下
  51.         {
  52.             if(Off_Delay != 0) // 如果延時計數器不為 0
  53.             {
  54.                 Delay50ms(); // 延時 50ms
  55.                 Off_Delay = Off_Delay - 1; // 遞減延時計數器
  56.                 if(Off_Delay == 0) // 如果計數器減到 0
  57.                 {
  58.                     LED1 = 1; // 熄滅 LED1
  59.                     LED2 = 1; // 熄滅 LED2
  60.                 }
  61.             }
  62.         }
  63.     }
  64. }
復制代碼

作者: lch327    時間: 2024-12-6 14:31
lkc8210 發表于 2024-12-5 00:03
非死等版本

這個程序解決了按鍵卡死的問題。我搭建一個電路,用單片機控制ULN2003驅動電路,單片機輸出高電平給2003,2003反相后低電位驅動12V繼電器,12V繼電器再控制一個中間繼電器,這時候,KZONG,K1,K2都不穩定,有時好使,有時不好使,K1和K2還互相干擾。可能接入中間繼電器后,會受到電磁干擾。不接中間繼電器沒事。如果換用三極管驅動電路就沒問題。(單片機低電位控制三極管驅動12V小繼電器,再控制中間繼電器)用2種電路做了試驗。還沒用燈泡做試驗,等有了燈泡再試試。我想是不是加按鍵延時,會抵消干擾呢?下降沿觸發沒有延時,按鍵一瞬間會受到干擾嗎?
作者: lch327    時間: 2024-12-6 14:42

這種接法單片機會受到干擾
作者: xiaobendan001    時間: 2024-12-6 16:05
lch327 發表于 2024-12-6 14:42
這種接法單片機會受到干擾

2003里面就是三極管吧
開關線不能太長,否則要增加上拉電阻,還有電容。再長就要加光耦隔離了
作者: zhuls    時間: 2024-12-6 17:23
自鎖與非自鎖,不就是邏輯關系嗎?
請原諒我實話實說,連這么簡單的邏輯都搞不定,代碼也不用寫了。
如果不考慮去抖的動作:
自鎖就是按一下一個狀態(比如連通),再按一下是另一個狀態(斷開);
非自鎖就是按下時是一個狀態(比如連通),放開時是另一個狀態(斷開);
簡單地說,自鎖開關按兩下,相當于非自鎖按一下而已。
搞不定自鎖,就加標志,又不用占用太多的代碼空間。。。


作者: lkc8210    時間: 2024-12-6 17:44
lch327 發表于 2024-12-6 14:31
這個程序解決了按鍵卡死的問題。我搭建一個電路,用單片機控制ULN2003驅動電路,單片機輸出高電平給2003, ...

試試這個
  1. #include <REG52.h>

  2. // 定義類型別名
  3. typedef unsigned char u8;  // 0 到 255
  4. typedef unsigned int u16;   // 0 到 65535

  5. // 延時函數,產生約 50 毫秒的延時
  6. void Delay50ms(void) //@11.0592MHz
  7. {
  8.         unsigned char data i, j; // 定義循環變量

  9.         i = 90;  // 外層循環次數
  10.         j = 163; // 內層循環次數
  11.         do
  12.         {
  13.                 while (--j); // 內層循環
  14.         }
  15.         while (--i); // 外層循環
  16. }

  17. // 定義按鍵和 LED 引腳
  18. sbit Kzong = P3^1; // 總按鍵連接到 P3.1
  19. sbit K1 = P3^2;    // 按鍵 1 連接到 P3.2
  20. sbit K2 = P3^3;    // 按鍵 2 連接到 P3.3
  21. sbit LED1 = P2^0;  // LED1 連接到 P2.0
  22. sbit LED2 = P2^1;  // LED2 連接到 P2.1

  23. u8 Off_Delay = 0;  // 關燈延時計數器,初始化為 0

  24. void main()
  25. {
  26.         bit K1_Lock = 1;
  27.         bit K2_Lock = 1;
  28.         while(1) // 主循環
  29.         {
  30.                 if(Kzong == 0) // 如果總按鍵被按下
  31.                 {
  32.                         if(Off_Delay == 0) // 如果延時計數器為 0
  33.                         {
  34.                                 LED1 = 0; // 開啟 LED1
  35.                                 LED2 = 0; // 開啟 LED2
  36.                         }
  37.                         if(K1 == 0)
  38.                         {
  39.                                 if(K1_Lock == 0)
  40.                                 {
  41.                                         LED1 = !LED1; // 切換 LED1 狀態
  42.                                         K1_Lock = 1;
  43.                                 }
  44.                         }
  45.                         else
  46.                         {
  47.                                 K1_Lock = 0;
  48.                         }
  49.                         if(K2 == 0)
  50.                         {
  51.                                 if(K2_Lock == 0)
  52.                                 {
  53.                                         LED2 = !LED2; // 切換 LED2 狀態
  54.                                         K2_Lock = 1;
  55.                                 }
  56.                         }
  57.                         else
  58.                         {
  59.                                 K2_Lock = 0;
  60.                         }
  61.                         Delay50ms(); // 延時 50ms
  62.                         Off_Delay = 200; // 設置關燈延時計數器為 200
  63.                 }
  64.                 else // 如果總按鍵沒有被按下
  65.                 {
  66.                         if(Off_Delay != 0) // 如果延時計數器不為 0
  67.                         {
  68.                                 Delay50ms(); // 延時 50ms
  69.                                 Off_Delay = Off_Delay - 1; // 遞減延時計數器
  70.                                 if(Off_Delay == 0) // 如果計數器減到 0
  71.                                 {
  72.                                         LED1 = 1; // 熄滅 LED1
  73.                                         LED2 = 1; // 熄滅 LED2
  74.                                 }
  75.                         }
  76.                 }
  77.         }
  78. }
復制代碼

作者: lch327    時間: 2024-12-7 16:41
lkc8210 發表于 2024-12-6 17:44
試試這個

經過試驗,這個程序和上面的效果差不多,也有干擾。接上照明燈沒有問題。放棄ULN2003電路,使用三極管電路就行了。本來也是想控制照明用的。控制中間繼電器有干擾,可能需要在硬件電路上改變。十分感謝您的幫助!
作者: 188610329    時間: 2024-12-8 00:15
lch327 發表于 2024-12-6 14:42
這種接法單片機會受到干擾

你這屬于硬件問題了, 單片機電源這里 加大電容,開關到IO之間接個1K電阻,然后IO這里接104電容對地,應該會好很多。
作者: xiaobendan001    時間: 2024-12-8 14:54
只要沒有被干擾到復位,就可以用軟件處理
作者: lch327    時間: 2024-12-10 09:54
xiaobendan001 發表于 2024-12-8 14:54
只要沒有被干擾到復位,就可以用軟件處理

我看到網上教學里有這種套娃式接法,可是實際不行。不知道軟件能否解決?
作者: xiaobendan001    時間: 2024-12-10 15:35
lch327 發表于 2024-12-10 09:54
我看到網上教學里有這種套娃式接法,可是實際不行。不知道軟件能否解決?

你可以加一個上拉電阻,實際上我就不加。軟件就是多次讀取嘛




歡迎光臨 (http://www.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 日韩精品一区二区三区在线播放 | 啪啪毛片 | 欧美亚州 | 夜夜夜操 | 久久精品国产一区二区三区 | 成人在线观看免费视频 | 日日拍夜夜 | 性做久久久久久免费观看欧美 | 欧美成人a∨高清免费观看 91伊人 | 亚洲欧美国产精品一区二区 | 日韩欧美手机在线 | 久久蜜桃av| 国产 日韩 欧美 在线 | 午夜免费影视 | 你懂的av| 亚洲一区播放 | 亚洲精品一区二 | 成人在线观看免费爱爱 | 日本涩涩视频 | 精品视频一区二区三区在线观看 | 污视频在线免费观看 | av片在线播放 | 女同久久另类99精品国产 | 一级免费毛片 | 一本一道久久a久久精品综合 | 欧洲毛片 | 亚洲一区二区三区四区av | 中文字幕视频一区二区 | 日韩视频一区二区三区 | 精品自拍视频在线观看 | 91久久电影 | 国产精品美女久久久久久免费 | 亚洲精品片 | 正在播放国产精品 | 日韩在线不卡 | 免费一级黄 | 性高湖久久久久久久久aaaaa | 中文二区 | 国产精品99一区二区 | 中文字幕视频在线观看免费 | 色久伊人|