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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1150|回復: 14
打印 上一主題 下一主題
收起左側

51單片機內部兩路ADC采集

[復制鏈接]
跳轉到指定樓層
樓主
ID:350682 發表于 2024-11-5 23:01 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
請問一下,用了一塊國產的51單片機CA51F005,內部有12個通道的ADC,但是好像不能同時使能兩個通道,現在我需要用一路AD去檢測按鍵(兩個按鍵,通過電壓識別),一路AD檢測電池電壓,按鍵的檢測是在定時器里面實現的,定時10ms,電壓檢測直接在主函數的while循環中,現在遇到一個問題,另個功能同時使用的話,按鍵電壓檢測到了,但是不去做相應的處理(處理在while循環中,在定時器中根據按鍵狀態,寫了一個標志位,然后根據標志位在while中處理)。調試運行的時候,每次停止運行,程序就都停在等待AD轉換完成這里。
  1. void ADC_Init(void)
  2. {
  3.         KEY_GPIO_ADC_SET(); //設置IO為ADC功能
  4.         BAT_GPIO_ADC_SET();
  5.         ADCON = AST(0) | ADIE(0) | HTME(7) | VSEL(ADC_REF_VDD);                //設置ADC參考電壓
  6.         ADOPC = GAIN(NO_AMP);
  7. }

  8. float read_adc(unsigned char adc_ch)
  9. {
  10.         unsigned int AD_Value;
  11.         ADCFGL = ACKD(7) | ADCALE(1) | ADCHS(adc_ch);        //選擇ADC通道
  12.         ADCON |= AST(1);   //啟動ADC轉換
  13.         while(!(ADCON & ADIF));//等待轉換完成
  14.         ADCON |= ADIF;         //清除中斷標志
  15.         AD_Value = ADCDH*256 + ADCDL;                                                //讀取AD值
  16.         AD_Value >>= 4;       
  17.        
  18.         VDD_Voltage = ((double)AD_Value*3.0)/4095;
  19.        
  20.         return VDD_Voltage;
  21. }
復制代碼

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:1133081 發表于 2024-11-6 06:28 | 只看該作者
不論MCU內部有多少個ADC通道,AD轉換電路只有一套,通過選擇開關實現多路AD轉換。多路AD轉換必須輪流執行。編程時一定要等待前一次轉換結束后才能執行下一次轉換。樓主在主函數和中斷中分別使用AD轉換,發生沖突是大概率事件。
回復

使用道具 舉報

板凳
ID:350682 發表于 2024-11-6 09:14 | 只看該作者
WL0123 發表于 2024-11-6 06:28
不論MCU內部有多少個ADC通道,AD轉換電路只有一套,通過選擇開關實現多路AD轉換。多路AD轉換必須輪流執行。 ...

啊這,該怎樣解決這個問題?
回復

使用道具 舉報

地板
ID:857072 發表于 2024-11-6 09:48 來自手機 | 只看該作者
互鎖唄,在開始讀ad做一個標記讀完了取消標記,然后每次讀adc值之前查看這個標記 如果這個標記被占用了 說明有其他地方在用 就不要讀了
回復

使用道具 舉報

5#
ID:1109793 發表于 2024-11-6 10:04 | 只看該作者
該ADC不支持中斷嗎?
回復

使用道具 舉報

6#
ID:624769 發表于 2024-11-6 10:43 | 只看該作者
要什么定時器啊? ADC閑著也是閑著, 讀完按鍵讀電壓,讀完電壓讀電池,周而復始的讀,把讀到的值分別存到  KeyValue, VoltValue, 兩個變量, 最多就是你定時中斷每 10ms 去 keyValue 里面讀最新數據就好了。
回復

使用道具 舉報

7#
ID:350682 發表于 2024-11-7 10:49 | 只看該作者
188610329 發表于 2024-11-6 10:43
要什么定時器啊? ADC閑著也是閑著, 讀完按鍵讀電壓,讀完電壓讀電池,周而復始的讀,把讀到的值分別存到   ...

因為要掃描按鍵,我設置的10ms掃描一次,掃描按鍵前要讀ADC判斷是哪一個按鍵。我要實現按鍵的單擊、長按和雙擊
回復

使用道具 舉報

8#
ID:350682 發表于 2024-11-7 10:51 | 只看該作者
xiaobendan001 發表于 2024-11-6 10:04
該ADC不支持中斷嗎?

支持,只是不需要用中斷吧,不熟悉51,所以問題一大堆
回復

使用道具 舉報

9#
ID:350682 發表于 2024-11-7 10:52 | 只看該作者
a185980800 發表于 2024-11-6 09:48
互鎖唄,在開始讀ad做一個標記讀完了取消標記,然后每次讀adc值之前查看這個標記 如果這個標記被占用了 說 ...

這會不會影響我讀按鍵呀,我10ms掃描一次按鍵狀態
回復

使用道具 舉報

10#
ID:624769 發表于 2024-11-7 15:35 | 只看該作者
piscest_x 發表于 2024-11-7 10:49
因為要掃描按鍵,我設置的10ms掃描一次,掃描按鍵前要讀ADC判斷是哪一個按鍵。我要實現按鍵的單擊、長按 ...

你ADC 就在主循環里 反復 讀鍵值/電壓,  鍵值存到 變量 A1,  電壓存到 變量 A2,  
你定時器 每10ms 中斷一次,去讀 變量A1 知道最近一次的 結果 來判斷 長按,短按,和雙擊 不就行了?
回復

使用道具 舉報

11#
ID:350682 發表于 2024-11-7 21:26 | 只看該作者
188610329 發表于 2024-11-7 15:35
你ADC 就在主循環里 反復 讀鍵值/電壓,  鍵值存到 變量 A1,  電壓存到 變量 A2,  
你定時器 每10ms 中 ...

現在放在主函數是可以了,但是單擊識別按鍵不靈敏,按下按鍵不是每次都能精確識別。
  1. void TIMER0_ISR (void) interrupt 1 //定時10ms
  2. {
  3.         TH0  = TH_VAL;                //高8位裝初值
  4.         TL0  = TL_VAL;                //低8位裝初值

  5.         key1_readStatus();
  6.         key2_readStatus();
  7.         if(key1_event == SINGLE_KEY)       //單擊
  8.         {
  9.                 key1_single_flag = 1;
  10.         }
  11.         else if(key1_event == DOUBLE_KEY)  //雙擊
  12.         {
  13.                 key1_double_flag = 1;
  14.         }
  15.         else if(key1_event == LONG_KEY)   //長按
  16.         {
  17.                 key1_long_flag = 1;
  18.         }
  19.         /****************************************/
  20.         if(key2_event == SINGLE_KEY)       //單擊
  21.         {
  22.                 key2_single_flag = 1;
  23.         }
  24.         else if(key2_event == DOUBLE_KEY)  //雙擊
  25.         {
  26.                 key2_double_flag = 1;
  27.         }
  28.         else if(key2_event == LONG_KEY)   //長按
  29.         {
  30.                 key2_long_flag = 1;
  31.         }
  32. }
復制代碼


這是定時器里面的處理
回復

使用道具 舉報

12#
ID:350682 發表于 2024-11-7 21:27 | 只看該作者
188610329 發表于 2024-11-7 15:35
你ADC 就在主循環里 反復 讀鍵值/電壓,  鍵值存到 變量 A1,  電壓存到 變量 A2,  
你定時器 每10ms 中 ...
  1. void key1_readStatus(void)
  2. {
  3.         switch(key1_state)
  4.         {
  5.                 case KEY_STATUS_0:               //無按鍵按下
  6.                         if(key1_flag)                  //如果按鍵1按下
  7.                         {
  8.                                 key1_state = KEY_STATUS_1;    //進入下一狀態:消抖
  9.                                 key1_event = NO_KEY;          //第一次按鍵按下,事件為空
  10.                         }
  11.                         else
  12.                         {
  13.                                 key1_state = KEY_STATUS_0;    //回到無按鍵狀態或者第二次按下前狀態
  14.                                 key1_event = NO_KEY;
  15.                         }
  16.                         break;
  17.                 case KEY_STATUS_1:               /* 消抖 */
  18.                         if(key1_flag)                  //如果按鍵1按下
  19.                         {
  20.                                 key1_state = KEY_STATUS_2;    //進入下一狀態:繼續按下
  21.                                 key1_event = NO_KEY;
  22.                         }
  23.                         else
  24.                         {
  25.                                 key1_state = KEY_STATUS_0;    //回到初始狀態
  26.                                 key1_event = NO_KEY;
  27.                         }
  28.                         break;
  29.                 case KEY_STATUS_2:              /* 確認按下 */
  30.                         if(key1_flag && key1_count >= KEY_LONG_TIME)
  31.                         {
  32.                                 key1_state = KEY_STATUS_3;   //進入下一狀態:長按
  33.                                 key1_event = NO_KEY;
  34.                                 key1_count = 0;
  35.                         }
  36.                         else if(key1_flag && key1_count < KEY_LONG_TIME)
  37.                         {
  38.                                 key1_count++;
  39.                                 key1_state = KEY_STATUS_2;   //進入下一狀態:確認按下
  40.                                 key1_event = NO_KEY;
  41.                         }
  42.                         else
  43.                         {
  44.                                 key1_count = 0;
  45.                                 key1_state = KEY_STATUS_4;   //進入下一狀態:等待第二次按下
  46.                                 key1_event = NO_KEY;
  47.                         }
  48.                         break;
  49.                 case KEY_STATUS_3:              //長按狀態
  50.                         if(key1_flag)
  51.                         {
  52.                                 key1_state = KEY_STATUS_3;   //一直等待按鍵放開
  53.                                 key1_event = NO_KEY;
  54.                                 key1_count = 0;
  55.                         }
  56.                         else
  57.                         {
  58.                                 key1_state = KEY_STATUS_0;
  59.                                 key1_event = LONG_KEY;
  60.                                 key1_count = 0;
  61.                         }
  62.                         break;
  63.                 case KEY_STATUS_4:               /* 等待第二次按下 */
  64.                         if(!key1_flag&&key1_count>=KEY_WAIT_TIME) //如果按鍵松開,且時間大于等待第二次按下的時間
  65.                         {
  66.                                 key1_count = 0;
  67.                                 key1_state = KEY_STATUS_0;
  68.                                 key1_event = SINGLE_KEY;           //判定為單擊
  69.                         }
  70.                         else if(!key1_flag&&key1_count<KEY_WAIT_TIME)
  71.                         {
  72.                                 key1_count++;
  73.                                 key1_state = KEY_STATUS_4;         //繼續等待
  74.                                 key1_event = NO_KEY;
  75.                         }
  76.                         else
  77.                         {
  78.                                 key1_count = 0;
  79.                                 key1_state = KEY_STATUS_5;         //第二次按下,且時間未到
  80.                                 key1_event = NO_KEY;
  81.                         }
  82.                         break;
  83.                 case KEY_STATUS_5:                    /* 第二次按下 */
  84.                         if(key1_flag && key1_count >= KEY_LONG_TIME)
  85.                         {
  86.                                 key1_state = KEY_STATUS_3;         //第二次按下,時間大于長按時間
  87.                                 key1_event = SINGLE_KEY;           //先響應單擊
  88.                                 key1_count = 0;
  89.                         }
  90.                         else if(key1_flag && key1_count < KEY_LONG_TIME)
  91.                         {
  92.                                 key1_count++;
  93.                                 key1_state = KEY_STATUS_5;         //等待按鍵松開
  94.                                 key1_event = NO_KEY;
  95.                         }
  96.                         else
  97.                         {
  98.                                 key1_count = 0;
  99.                                 key1_state = KEY_STATUS_0;         //等待按鍵松開
  100.                                 key1_event = DOUBLE_KEY;           //判定為雙擊
  101.                         }
  102.                         break;
  103.                 default:break;
  104.         }
  105. }
復制代碼

這個是識別按鍵狀態
回復

使用道具 舉報

13#
ID:350682 發表于 2024-11-7 21:32 | 只看該作者
188610329 發表于 2024-11-7 15:35
你ADC 就在主循環里 反復 讀鍵值/電壓,  鍵值存到 變量 A1,  電壓存到 變量 A2,  
你定時器 每10ms 中 ...
  1. void key_scan(void)
  2. {
  3.         float key_press;
  4.         key_press = read_adc(8);
  5.         if(key_press >=0&&key_press<1.0) //按鍵1
  6.         {
  7.                 key1_flag = 1;
  8.                 key2_flag = 0;
  9.         }
  10.         else if(key_press >=1.45&&key_press <1.65) //按鍵2
  11.         {
  12.                 key2_flag = 1;
  13.                 key1_flag = 0;
  14.         }
  15.         else if(key_press >2.9) //無按鍵
  16.         {
  17.                 key1_flag = 0;
  18.                 key2_flag = 0;
  19.         }
  20. }
復制代碼

這個是識別按鍵的,我放在主函數while循環里面了,然后最后的處理也在while 循環里面
  1. while(1)
  2. {
  3.         key_scan();//讀取電壓,判斷是那個按鍵按下
  4.         if(key1_double_flag)   //雙擊旋轉屏幕
  5.         {
  6.                 key1_double_flag = 0;
  7.                 something();
  8.         }
  9.         else if(key1_long_flag)//長按當前通道清零
  10.         {
  11.                 key1_long_flag = 0;
  12.                something();
  13.         }
  14. }
復制代碼
回復

使用道具 舉報

14#
ID:1135890 發表于 2024-11-8 15:14 | 只看該作者
您好,錦銳單片機為您服務,您在開發的是CA51F005T3 TSSOP20的型號,技術問題可以聯系我,我安排FAE協助您。
回復

使用道具 舉報

15#
ID:1135890 發表于 2024-11-8 16:46 | 只看該作者

您們好,錦銳單片機為您服務。

有需要請私信我安排FAE
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: av色站| 色视频在线观看 | 欧美日韩久久精品 | 国产亚洲欧美另类一区二区三区 | 一区二区视频在线 | 在线日韩欧美 | 懂色一区二区三区免费观看 | а天堂中文最新一区二区三区 | 中文字幕亚洲欧美 | 九九热久久免费视频 | 久久精品国产99国产 | 午夜激情影院 | 日韩精品一区二区三区视频播放 | 日本一区二区电影 | 国产成人精品a视频一区www | 欧美一级三级 | 欧美一级二级视频 | 波多野结衣一区二区三区 | 久久久久久久久久久一区二区 | 久在线| 欧美精品一区在线发布 | 亚洲黄色成人网 | 亚洲情综合五月天 | 国内精品久久久久久久影视简单 | 亚洲视频一区二区 | 日韩毛片免费视频 | 91免费电影 | 69亚洲精品 | 97超级碰碰 | 欧美激情精品久久久久久 | 黄网站涩免费蜜桃网站 | 久久久国产亚洲精品 | 亚洲色图综合 | 人人亚洲 | 精品国产一区二区三区久久久蜜月 | 99精品99 | 亚洲一区二区久久久 | 天天插天天操 | 99热欧美| 超碰97人人人人人蜜桃 | 狠狠干2020|