找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3896|回復: 15
收起左側(cè)

關(guān)于單片機AD與電位器的問題

[復制鏈接]
ID:254747 發(fā)表于 2021-9-15 10:14 | 顯示全部樓層 |閱讀模式
1.請問一下電位器通過AD轉(zhuǎn)換為數(shù)字量,然后我任意旋轉(zhuǎn)一下電位器,將這個電位器得到的值送到定時器中斷里面去進行定時      例如我在中斷里面申請了一個變量 count++  
    電位器送來的值為 temp   

    假如 電位器送來的值是  temp = 50;   通過  if(count == 50)  那么這個時候count就要加到50 如果到了50成立了 就點亮LED作為盤點依據(jù);


    但是現(xiàn)在遇到一個問題就是   我快速旋轉(zhuǎn)電位器    這個中斷就會失效 , 慢慢旋轉(zhuǎn)一兩次也會失效 ,

    總結(jié); 就是   我是通過ADC將電位器準換的值,發(fā)送到了中斷的變量里面去對比,快速旋轉(zhuǎn)電位器就會出現(xiàn)失效問題  

    這個程序 問題我請教了3次了  但是還是沒有解決到  我也嘗試了很多方式 還是不行     是不是通過電位器 加簡單的判斷不行啊  麻煩大師給我講一下  
回復

使用道具 舉報

ID:734017 發(fā)表于 2021-9-15 11:11 | 顯示全部樓層
如果count是全局變量。你試試加一個標志位限制count。我的意思是,你轉(zhuǎn)一下,count開始計數(shù),再轉(zhuǎn)一下count沒有=0.經(jīng)過多次旋轉(zhuǎn)count累加超出temp. 或者 if(count >= 50).
回復

使用道具 舉報

ID:401564 發(fā)表于 2021-9-15 11:55 | 顯示全部樓層
1,count設(shè)定為全局變量
2, if(count == 50)實際是作為查找的,不是比較的,比較要用 if(count >= 50)或者 if(count <= 50),很有可能你電位器在現(xiàn)實中永遠轉(zhuǎn)不到"50"這個位置的,那么這if就永遠不成立了
回復

使用道具 舉報

ID:254747 發(fā)表于 2021-9-15 13:12 | 顯示全部樓層
本帖最后由 不將就123 于 2021-9-15 13:25 編輯
Y_G_G 發(fā)表于 2021-9-15 11:55
1,count設(shè)定為全局變量
2, if(count == 50)實際是作為查找的,不是比較的,比較要用 if(count >= 50)或 ...

嗯嗯   我就是在想這么一個問題     我是將COUNT設(shè)置為了全局變量   就是我現(xiàn)在需要是查找  比如要50 那就必須是50  
我發(fā)布了兩個視頻   到時還請大師看一下  這樣比較直觀   謝謝 啦
回復

使用道具 舉報

ID:254747 發(fā)表于 2021-9-15 13:15 | 顯示全部樓層
本帖最后由 不將就123 于 2021-9-15 13:24 編輯
happy2058 發(fā)表于 2021-9-15 11:11
如果count是全局變量。你試試加一個標志位限制count。我的意思是,你轉(zhuǎn)一下,count開始計數(shù),再轉(zhuǎn)一下count ...

上面舉例是50  假如我在動一下 為100那么 就是 count的計數(shù)要達到100  在動一下是150 那么count就是150個計數(shù)  我就是通過這樣的方式來調(diào)節(jié)定時器溢出的頻率       我發(fā)布了一個視頻現(xiàn)象 麻煩你看一下   謝謝
回復

使用道具 舉報

ID:254747 發(fā)表于 2021-9-15 13:23 | 顯示全部樓層
http://v.youku.com/v_show/id_XNT ... 6f066ea530d62f89c35

http://v.youku.com/v_show/id_XNT ... id&sharekey=68a188f

我上傳了兩個視頻到優(yōu)酷了 請大哥些看一下現(xiàn)象  然后結(jié)合我描述的問題給我看一下   是什么問題    謝謝大家了
回復

使用道具 舉報

ID:161164 發(fā)表于 2021-9-15 13:30 | 顯示全部樓層
普通電位器轉(zhuǎn)動時電阻是不平滑的
有時會有毛刺電壓產(chǎn)生
所以不要在轉(zhuǎn)動時傳送數(shù)值
要等電壓穩(wěn)定了再傳送
給你一段代碼參考一下

  1. if(MAN_KUAN_PIN_LV!=MAN_KUAN_PIN_LV_OLD)
  2. {
  3.         MAN_KUAN_PIN_LV_OLD = MAN_KUAN_PIN_LV;
  4.         Delay_Count = 0;
  5. }else{
  6.         if(Delay_Count<0xffff)Delay_Count++;
  7. }
  8. if(Delay_Count==1000)//數(shù)值按系統(tǒng)運行時間調(diào)節(jié),如要精準可放入定時器中斷中運行
  9. {
  10.         Temp = MAN_KUAN_PIN_LV;
  11. }
復制代碼




回復

使用道具 舉報

ID:935919 發(fā)表于 2021-9-15 13:31 | 顯示全部樓層
針對你的問題我有幾個地方不太清楚:
1. 你的目的是否是: 以電位器的AD值做為LED開關(guān)的延時長度?
2. 你多長時間讀一次 電位器的AD值? 定時中斷是多長時間中斷一次? 怎么把AD值"送到"中斷?
3. 你所謂的中斷失效是什么意思? 是中斷進不去了嗎? 還是其他的什么情況(具體的)?

是不是把程序貼上來?

回復

使用道具 舉報

ID:254747 發(fā)表于 2021-9-15 14:51 | 顯示全部樓層
sinside 發(fā)表于 2021-9-15 13:31
針對你的問題我有幾個地方不太清楚:
1. 你的目的是否是: 以電位器的AD值做為LED開關(guān)的延時長度?
2. 你多 ...
這是我整理過后的程序    這個程序就是 只要旋轉(zhuǎn)電位器  這個中斷就不好用了  LED要么一直亮   要么熄滅   也就是輸出沒有任何波形了
正常情況下   我這里輸出的波形是 0-25HZ可調(diào)的  
ZHU_PIN_JIE_GUO_GetADCResult()這個就是電位器的值  

  1. #include <STC15F2K60S2.H>
  2. #include "intrins.h"

  3. //數(shù)碼管延時
  4. void Delay100us()                //@24.000MHz
  5. {
  6.         unsigned char i, j;

  7.         i = 3;
  8.         j = 82;
  9.         do
  10.         {
  11.                 while (--j);
  12.         } while (--i);
  13. }


  14. #define ADC_POWER   0x80           //ADC電源控制位
  15. #define ADC_FLAG    0x10             //ADC完成標志
  16. #define ADC_START   0x08            //ADC起始控制位
  17. #define ADC_SPEEDLL 0x40          //180個時鐘

  18. //unsigned char ch2 = 0X02;         //通道選擇變量 0x02;選擇P1.2
  19. //unsigned char ch3 = 0X03;         //選擇P1.3
  20. unsigned char ch1 = 0X04;            //選擇P1.4
  21. unsigned int  count;                     //中斷計數(shù)的



  22. void ADC_INIT ();
  23. void PCA_REG_PWM();
  24. void PCA_PIN_LV_ADJ(unsigned char );
  25. void Timer0Init(void);
  26. void Timer1_Init(void);
  27. void Timer1_PING_LV_ADJ();


  28. unsigned int  ZHU_PIN_JIE_GUO_GetADCResult();
  29. //unsigned char FU_PIN_JIE_GUO_GetADCResult();
  30. //unsigned char ZHAN_KONG_BI_JIE_GUO_GetADCResult();



  31. //連接138譯碼器  
  32. sbit   LSA = P5^1;   
  33. sbit   LSB = P5^2;
  34. sbit   LSC = P5^3;
  35. sbit   LED1 = P0^3;

  36.   
  37. //0-9 數(shù)碼段位顯示數(shù)字
  38. unsigned  code   sumaguan_duan[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};   
  39. //位選信號//用來保存位選數(shù)據(jù)
  40. unsigned  char  displaydata[7] ;   
  41. //數(shù)碼管驅(qū)動函數(shù)
  42. void  shu_ma_guan();
  43. //數(shù)碼管數(shù)據(jù)接收函數(shù)
  44. void  shumaguan_shuju_chuli(unsigned int zhupin);


  45. main()
  46. {
  47.         P5M0  =   0x00;   //0000,0000 端口5模式寄存器0
  48.         P5M1  =   0x00;   //0000,0000 端口5模式寄存器1
  49.         P4M0  =   0x00;   //0000,0000 端口4模式寄存器0  數(shù)碼管用
  50.         P4M1  =   0x00;
  51.         P1M0  =   0x00;   //
  52.         P1M1  |=   0x04;   //  設(shè)置P1.2為高阻輸入模式
  53.         P0M0  =   0x00;   //0000,0000 端口4模式寄存器0  數(shù)碼管用
  54.         P0M1  =   0x00;
  55.         ADC_INIT ();
  56.         PCA_REG_PWM();
  57.         Timer0Init();
  58.         Timer1_Init();

  59.     while (1)
  60.                 {

  61.         Timer1_PING_LV_ADJ();
  62.         //數(shù)碼管驅(qū)動函數(shù)
  63.         shu_ma_guan();
  64.         //s數(shù)碼管數(shù)據(jù)接收
  65.         shumaguan_shuju_chuli(ZHU_PIN_JIE_GUO_GetADCResult());
  66.         //設(shè)置占空比
  67.         //CCAP0H = CCAP0L = ZHAN_KONG_BI_JIE_GUO_GetADCResult();   
  68.         //設(shè)置頻率
  69.         //PCA_PIN_LV_ADJ(FU_PIN_JIE_GUO_GetADCResult());   //這項暫時不能開啟 等后面改善 開啟后會導致中斷異常  

  70.                 }



  71. }



  72. // ADC初始化
  73. void ADC_INIT ()
  74.         
  75. {
  76.         P1ASF |= 0X1C;                       //  將P1.2 P1.3 P1.4 口作為ADC輸入信號
  77.         ADC_RES=0;                           //清零轉(zhuǎn)換結(jié)果寄存器高8位
  78.         ADC_RESL=0;                          //清零轉(zhuǎn)換結(jié)果寄存器低2位
  79.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START ;

  80. }

  81. //高頻結(jié)果轉(zhuǎn)換  P1.2
  82. unsigned int ZHU_PIN_JIE_GUO_GetADCResult()
  83. {
  84.         
  85.         unsigned  int  xdata zhupinjieguo;
  86.         ADC_RES=0;                           //清零轉(zhuǎn)換結(jié)果寄存器高8位
  87.         ADC_RESL=0;
  88.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch1 | ADC_START;  //打開電源 速度180個時鐘 選擇通道2 啟動轉(zhuǎn)換
  89.         _nop_();                             //等待4個NOP
  90.         _nop_();
  91.         _nop_();
  92.         _nop_();
  93.         while (!(ADC_CONTR & ADC_FLAG));     //等待ADC轉(zhuǎn)換完成  全部為1 表示轉(zhuǎn)換完成
  94.         ADC_CONTR &= ~0X80;                  //關(guān)閉ADC電源  節(jié)約功耗
  95.         ADC_CONTR &= ~ADC_FLAG;              //Close ADC  清楚標識位
  96.         zhupinjieguo =(ADC_RES<<2)+ADC_RESL;    //將高2兩位  和低8位的結(jié)果相加得到10位的結(jié)果

  97.         zhupinjieguo /= 4;                   //ad輸出的結(jié)果最大是1024按照,但是只要0-300
  98.                                              //縮小倍率就是1023除以300就是3.41 故用1023除以3.41即可轉(zhuǎn)換為300
  99.         return zhupinjieguo;                 //返回ADC結(jié)果
  100. }

  101. //數(shù)碼管顯示屏函數(shù) 初始化函數(shù)
  102. void  shu_ma_guan()
  103. {

  104.          unsigned  char xdata  i,count;
  105.          count++;
  106.          if(count == 10)
  107.          count = 0;
  108.          for(i=0;i<7;i++)    //0 1 2 3 4 5 6
  109.          {
  110.                 switch(i)         //位選,選擇點亮的數(shù)碼管,
  111.                 {
  112.                 case(0):
  113.                         LSA=0;LSB=0;LSC=0; break;//顯示第0位
  114.                 case(1):
  115.                         LSA=1;LSB=0;LSC=0; break;//顯示第1位
  116.                 case(2):
  117.                         LSA=0;LSB=1;LSC=0; break;//顯示第2位
  118.                 case(3):
  119.                         LSA=1;LSB=1;LSC=0; break;//顯示第3位
  120.                 case(4):
  121.                         LSA=0;LSB=0;LSC=1; break;//顯示第4位
  122.                 case(5):
  123.                         LSA=1;LSB=0;LSC=1; break;//顯示第5位
  124.                 case(6):
  125.                         LSA=0;LSB=1;LSC=1; break;//顯示第6位
  126.         }
  127.                                        
  128.                  P4=displaydata[i];
  129.                  Delay100us();
  130.                  P4 = 0X00;   //消影信號
  131.          }

  132.             
  133. }

  134. //數(shù)碼管 數(shù)據(jù)接收與處理函數(shù)
  135. void  shumaguan_shuju_chuli(unsigned int zhupin)
  136. {
  137.         
  138.         //主頻頻率
  139. displaydata[4] = sumaguan_duan[zhupin/100%10];
  140. displaydata[5] = sumaguan_duan[zhupin/10%10];
  141. displaydata[6] = sumaguan_duan[zhupin%10];
  142.         
  143. }

  144. //PCA_PWM寄存器配置
  145. void PCA_REG_PWM()
  146. {
  147.         
  148.   
  149.         CMOD |=0X04;   //1、CPS2、CPS1、CPS0系統(tǒng)時鐘,定時器0的溢出 脈沖
  150.                        //2、當CIDL=0時, 空閑模式下PCA計數(shù)器繼續(xù)工作;
  151.                        //允許ECF溢出中斷

  152.         CCON &=0X00;   //不需要中斷標志位和中斷溢出所以并且初始化的時
  153.                         //候需要關(guān)閉PWM所以全部設(shè)置位0        

  154.         CCAPM0 |=0X42; //允許比較器功能控制位  允許脈寬調(diào)節(jié)模式    P1.1
  155.             

  156.         //    CCAPM1 |=0X42; //同上                                      P1.0
  157.          
  158.         CL = 0;         //低位初值設(shè)置為0
  159.         CH = 0;         //高位初值設(shè)置為0
  160.          
  161.         CCAP0H = CCAP0L = 0x80;   //PWM    設(shè)置占空比為50%                              
  162.                                  

  163.         PCA_PWM0 = 0X00; //PCA模塊0工作于8位PWM功能
  164.         //     PCA_PWM1 = 0X00; //PCA模塊1工作于8位PWM功能                 
  165.         CR = 1 ;

  166. }



  167. void   Timer0Init(void)
  168. {
  169.         
  170.         AUXR |= 0x80;                //定時器時鐘1T模式
  171.         TMOD &= 0xF0;                //設(shè)置定時器模式
  172.         TL0 = 0xA0;                //設(shè)置定時初值
  173.         TH0 = 0xF6;                //設(shè)置定時初值
  174.         TF0 = 0;                //清除TF0標志
  175.         TR0 = 1;                //定時器0開始計時

  176. }


  177. //頻率可調(diào)更新函數(shù)
  178. void PCA_PIN_LV_ADJ(unsigned char fuping)
  179. {
  180.         unsigned long  temp;

  181.         //重新初始化定時初值
  182.         temp = 0x10000-24000000/(fuping*256) ;
  183.         TH0 = temp>>8;                //設(shè)置定時初值
  184.         TL0 = temp;                  //設(shè)置定時初值


  185. }



  186. //測試中斷服務程序
  187. void Timer1_Init(void)                //1毫秒@18.432MHz
  188. {
  189.          
  190.   
  191.         AUXR |= 0x40;                //定時器時鐘1T模式
  192.         TMOD &= 0x0F;                //設(shè)置定時器模式
  193.         TL1 = 0x40;                  //設(shè)置定時初值
  194.         TH1 = 0xA2;                  //設(shè)置定時初值
  195.         TF1 = 0;                    //清除TF1標志   硬件清零
  196.         TR1 = 1;                    //定時器1開始計時            
  197.         ET1 = 1;                        // 啟動定時器1中斷允許位
  198.         EA = 1;//打開總中斷
  199.         
  200. }



  201. /*-------------------------------------
  202. 功能:定時器1 中斷服務程序
  203. 介紹:中斷程序無需聲明
  204. --------------------------------------*/

  205. void timer1_isr(void) interrupt 3
  206. {
  207.    
  208.           count++;
  209. }  


  210. void   Timer1_PING_LV_ADJ()
  211.         
  212. {
  213.         
  214.           unsigned char   b;                 //臨時變量
  215.                                  
  216.          b =1000/ZHU_PIN_JIE_GUO_GetADCResult()*2 ;

  217.         if(b == count)                              //(Sd_Key_Value2*10)
  218.           {
  219.                                        
  220.             count = 0;
  221.             LED1 = ~LED1;                      //測試用   接示波器 查看副頻波形
  222.           }                        
  223.          
  224.         
  225. }
復制代碼


回復

使用道具 舉報

ID:254747 發(fā)表于 2021-9-15 14:54 | 顯示全部樓層
lkc8210 發(fā)表于 2021-9-15 13:30
普通電位器轉(zhuǎn)動時電阻是不平滑的
有時會有毛刺電壓產(chǎn)生
所以不要在轉(zhuǎn)動時傳送數(shù)值

大哥說的對  我也懷疑是這個電位器過來的數(shù)據(jù)不穩(wěn)定導致的    比如我填一個實際是數(shù)據(jù)進去都不會出現(xiàn)任何問題     

我就是在想  怎么樣 ADC按我的要求來  啟動或者停止準換  這樣等待數(shù)據(jù)穩(wěn)定

我把程序貼出來的   
回復

使用道具 舉報

ID:401564 發(fā)表于 2021-9-15 21:07 | 顯示全部樓層
不將就123 發(fā)表于 2021-9-15 13:12
嗯嗯   我就是在想這么一個問題     我是將COUNT設(shè)置為了全局變量   就是我現(xiàn)在需要是查找  比如要50 那 ...

我知道你的意思,你是想通過電位器控制定時器
但你如果是查找一個ADC的數(shù)值的話,我說過了,很有可能是現(xiàn)實中電位器根本沒法轉(zhuǎn)到這個電壓值的
比如:加在電位器上的電壓是5.00V
你要查找2.33V,很有可能是根本轉(zhuǎn)不到這個電壓的,接觸不好或者其它原因
你只能調(diào)節(jié)到2.32V,再動一下就是2.34V,這樣就錯過了2.33V了
或者有時候你轉(zhuǎn)動的時候經(jīng)過2.33V,但ADC并沒有完成,它返回的值可能是2.30V,你還在轉(zhuǎn),等下就超過2.33V了
你沒有想過這些嗎?
只能是比較大小,或者是規(guī)定一個范圍值,而不是定值
實在要定值,就只能用編碼開關(guān)了
回復

使用道具 舉報

ID:254747 發(fā)表于 2021-9-16 10:20 | 顯示全部樓層
Y_G_G 發(fā)表于 2021-9-15 21:07
我知道你的意思,你是想通過電位器控制定時器
但你如果是查找一個ADC的數(shù)值的話,我說過了,很有可能是現(xiàn)實 ...

嗯嗯  謝謝大哥   我也在想這個問題  只能用編碼器來解決它 取得精準的值   我現(xiàn)在準備嘗試給一個范圍試一試
回復

使用道具 舉報

ID:254747 發(fā)表于 2021-9-16 21:35 | 顯示全部樓層
Y_G_G 發(fā)表于 2021-9-15 21:07
我知道你的意思,你是想通過電位器控制定時器
但你如果是查找一個ADC的數(shù)值的話,我說過了,很有可能是現(xiàn)實 ...

非常感謝大師的指導  這個問題困惑了我好幾天  現(xiàn)在得到了完美的解決   太感謝了  非常重要的經(jīng)驗  同時也感謝你的耐心解答  謝謝  
回復

使用道具 舉報

ID:254747 發(fā)表于 2021-9-16 21:36 | 顯示全部樓層
在這里非常感謝各位大師的指導與解答  這個問題現(xiàn)在解決了    解決的方案就是   不用查找  用比大小的方式解決的   將語句  if(count >=ADC)ADC的點位是旋轉(zhuǎn)的值    改成這樣的就可以了   謝謝大家
回復

使用道具 舉報

ID:731195 發(fā)表于 2021-9-29 15:12 | 顯示全部樓層
你選擇的是什么型號電位器
回復

使用道具 舉報

ID:960157 發(fā)表于 2021-10-7 16:00 來自手機 | 顯示全部樓層
電位器抽頭對地加個1uf電容器,消除接觸不良毛刺。
回復

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表