找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2503|回复: 15
收起左侧

关于单片机AD与电位器的问题

[复制链接]
ID:254747 发表于 2021-9-15 10:14 | 显示全部楼层 |阅读模式
1.请问一下电位器通过AD转换为数字量,然后我任意旋转一下电位器,将这个电位器得到的值送到定时器中断里面去进行定时      例如我在中断里面申请了一个变量 count++  
    电位器送来的值为 temp   

    假如 电位器送来的值是  temp = 50;   通过  if(count == 50)  那么这个时候count就要加到50 如果到了50成立了 就点亮LED作为盘点依据;


    但是现在遇到一个问题就是   我快速旋转电位器    这个中断就会失效 , 慢慢旋转一两次也会失效 ,

    总结; 就是   我是通过ADC将电位器准换的值,发送到了中断的变量里面去对比,快速旋转电位器就会出现失效问题  

    这个程序 问题我请教了3次了  但是还是没有解决到  我也尝试了很多方式 还是不行     是不是通过电位器 加简单的判断不行啊  麻烦大师给我讲一下  
回复

使用道具 举报

ID:734017 发表于 2021-9-15 11:11 | 显示全部楼层
如果count是全局变量。你试试加一个标志位限制count。我的意思是,你转一下,count开始计数,再转一下count没有=0.经过多次旋转count累加超出temp. 或者 if(count >= 50).
回复

使用道具 举报

ID:401564 发表于 2021-9-15 11:55 | 显示全部楼层
1,count设定为全局变量
2, if(count == 50)实际是作为查找的,不是比较的,比较要用 if(count >= 50)或者 if(count <= 50),很有可能你电位器在现实中永远转不到"50"这个位置的,那么这if就永远不成立了
回复

使用道具 举报

ID:254747 发表于 2021-9-15 13:12 | 显示全部楼层
本帖最后由 不将就123 于 2021-9-15 13:25 编辑
Y_G_G 发表于 2021-9-15 11:55
1,count设定为全局变量
2, if(count == 50)实际是作为查找的,不是比较的,比较要用 if(count >= 50)或 ...

嗯嗯   我就是在想这么一个问题     我是将COUNT设置为了全局变量   就是我现在需要是查找  比如要50 那就必须是50  
我发布了两个视频   到时还请大师看一下  这样比较直观   谢谢 啦
回复

使用道具 举报

ID:254747 发表于 2021-9-15 13:15 | 显示全部楼层
本帖最后由 不将就123 于 2021-9-15 13:24 编辑
happy2058 发表于 2021-9-15 11:11
如果count是全局变量。你试试加一个标志位限制count。我的意思是,你转一下,count开始计数,再转一下count ...

上面举例是50  假如我在动一下 为100那么 就是 count的计数要达到100  在动一下是150 那么count就是150个计数  我就是通过这样的方式来调节定时器溢出的频率       我发布了一个视频现象 麻烦你看一下   谢谢
回复

使用道具 举报

ID:254747 发表于 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

我上传了两个视频到优酷了 请大哥些看一下现象  然后结合我描述的问题给我看一下   是什么问题    谢谢大家了
回复

使用道具 举报

ID:161164 发表于 2021-9-15 13:30 | 显示全部楼层
普通电位器转动时电阻是不平滑的
有时会有毛刺电压产生
所以不要在转动时传送数值
要等电压稳定了再传送
给你一段代码参考一下

  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)//数值按系统运行时间调节,如要精准可放入定时器中断中运行
  9. {
  10.         Temp = MAN_KUAN_PIN_LV;
  11. }
复制代码




回复

使用道具 举报

ID:935919 发表于 2021-9-15 13:31 | 显示全部楼层
针对你的问题我有几个地方不太清楚:
1. 你的目的是否是: 以电位器的AD值做为LED开关的延时长度?
2. 你多长时间读一次 电位器的AD值? 定时中断是多长时间中断一次? 怎么把AD值"送到"中断?
3. 你所谓的中断失效是什么意思? 是中断进不去了吗? 还是其他的什么情况(具体的)?

是不是把程序贴上来?

回复

使用道具 举报

ID:254747 发表于 2021-9-15 14:51 | 显示全部楼层
sinside 发表于 2021-9-15 13:31
针对你的问题我有几个地方不太清楚:
1. 你的目的是否是: 以电位器的AD值做为LED开关的延时长度?
2. 你多 ...
这是我整理过后的程序    这个程序就是 只要旋转电位器  这个中断就不好用了  LED要么一直亮   要么熄灭   也就是输出没有任何波形了
正常情况下   我这里输出的波形是 0-25HZ可调的  
ZHU_PIN_JIE_GUO_GetADCResult()这个就是电位器的值  

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

  3. //数码管延时
  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;                     //中断计数的



  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 数码段位显示数字
  38. unsigned  code   sumaguan_duan[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};   
  39. //位选信号//用来保存位选数据
  40. unsigned  char  displaydata[7] ;   
  41. //数码管驱动函数
  42. void  shu_ma_guan();
  43. //数码管数据接收函数
  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  数码管用
  50.         P4M1  =   0x00;
  51.         P1M0  =   0x00;   //
  52.         P1M1  |=   0x04;   //  设置P1.2为高阻输入模式
  53.         P0M0  =   0x00;   //0000,0000 端口4模式寄存器0  数码管用
  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.         //数码管驱动函数
  63.         shu_ma_guan();
  64.         //s数码管数据接收
  65.         shumaguan_shuju_chuli(ZHU_PIN_JIE_GUO_GetADCResult());
  66.         //设置占空比
  67.         //CCAP0H = CCAP0L = ZHAN_KONG_BI_JIE_GUO_GetADCResult();   
  68.         //设置频率
  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;                           //清零转换结果寄存器高8位
  78.         ADC_RESL=0;                          //清零转换结果寄存器低2位
  79.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START ;

  80. }

  81. //高频结果转换  P1.2
  82. unsigned int ZHU_PIN_JIE_GUO_GetADCResult()
  83. {
  84.         
  85.         unsigned  int  xdata zhupinjieguo;
  86.         ADC_RES=0;                           //清零转换结果寄存器高8位
  87.         ADC_RESL=0;
  88.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch1 | ADC_START;  //打开电源 速度180个时钟 选择通道2 启动转换
  89.         _nop_();                             //等待4个NOP
  90.         _nop_();
  91.         _nop_();
  92.         _nop_();
  93.         while (!(ADC_CONTR & ADC_FLAG));     //等待ADC转换完成  全部为1 表示转换完成
  94.         ADC_CONTR &= ~0X80;                  //关闭ADC电源  节约功耗
  95.         ADC_CONTR &= ~ADC_FLAG;              //Close ADC  清楚标识位
  96.         zhupinjieguo =(ADC_RES<<2)+ADC_RESL;    //将高2两位  和低8位的结果相加得到10位的结果

  97.         zhupinjieguo /= 4;                   //ad输出的结果最大是1024按照,但是只要0-300
  98.                                              //缩小倍率就是1023除以300就是3.41 故用1023除以3.41即可转换为300
  99.         return zhupinjieguo;                 //返回ADC结果
  100. }

  101. //数码管显示屏函数 初始化函数
  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)         //位选,选择点亮的数码管,
  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. //数码管 数据接收与处理函数
  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系统时钟,定时器0的溢出 脉冲
  150.                        //2、当CIDL=0时, 空闲模式下PCA计数器继续工作;
  151.                        //允许ECF溢出中断

  152.         CCON &=0X00;   //不需要中断标志位和中断溢出所以并且初始化的时
  153.                         //候需要关闭PWM所以全部设置位0        

  154.         CCAPM0 |=0X42; //允许比较器功能控制位  允许脉宽调节模式    P1.1
  155.             

  156.         //    CCAPM1 |=0X42; //同上                                      P1.0
  157.          
  158.         CL = 0;         //低位初值设置为0
  159.         CH = 0;         //高位初值设置为0
  160.          
  161.         CCAP0H = CCAP0L = 0x80;   //PWM    设置占空比为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;                //设置定时器模式
  172.         TL0 = 0xA0;                //设置定时初值
  173.         TH0 = 0xF6;                //设置定时初值
  174.         TF0 = 0;                //清除TF0标志
  175.         TR0 = 1;                //定时器0开始计时

  176. }


  177. //频率可调更新函数
  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;                //设置定时初值
  184.         TL0 = temp;                  //设置定时初值


  185. }



  186. //测试中断服务程序
  187. void Timer1_Init(void)                //1毫秒@18.432MHz
  188. {
  189.          
  190.   
  191.         AUXR |= 0x40;                //定时器时钟1T模式
  192.         TMOD &= 0x0F;                //设置定时器模式
  193.         TL1 = 0x40;                  //设置定时初值
  194.         TH1 = 0xA2;                  //设置定时初值
  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 发表于 2021-9-15 14:54 | 显示全部楼层
lkc8210 发表于 2021-9-15 13:30
普通电位器转动时电阻是不平滑的
有时会有毛刺电压产生
所以不要在转动时传送数值

大哥说的对  我也怀疑是这个电位器过来的数据不稳定导致的    比如我填一个实际是数据进去都不会出现任何问题     

我就是在想  怎么样 ADC按我的要求来  启动或者停止准换  这样等待数据稳定

我把程序贴出来的   
回复

使用道具 举报

ID:401564 发表于 2021-9-15 21:07 | 显示全部楼层
不将就123 发表于 2021-9-15 13:12
嗯嗯   我就是在想这么一个问题     我是将COUNT设置为了全局变量   就是我现在需要是查找  比如要50 那 ...

我知道你的意思,你是想通过电位器控制定时器
但你如果是查找一个ADC的数值的话,我说过了,很有可能是现实中电位器根本没法转到这个电压值的
比如:加在电位器上的电压是5.00V
你要查找2.33V,很有可能是根本转不到这个电压的,接触不好或者其它原因
你只能调节到2.32V,再动一下就是2.34V,这样就错过了2.33V了
或者有时候你转动的时候经过2.33V,但ADC并没有完成,它返回的值可能是2.30V,你还在转,等下就超过2.33V了
你没有想过这些吗?
只能是比较大小,或者是规定一个范围值,而不是定值
实在要定值,就只能用编码开关了
回复

使用道具 举报

ID:254747 发表于 2021-9-16 10:20 | 显示全部楼层
Y_G_G 发表于 2021-9-15 21:07
我知道你的意思,你是想通过电位器控制定时器
但你如果是查找一个ADC的数值的话,我说过了,很有可能是现实 ...

嗯嗯  谢谢大哥   我也在想这个问题  只能用编码器来解决它 取得精准的值   我现在准备尝试给一个范围试一试
回复

使用道具 举报

ID:254747 发表于 2021-9-16 21:35 | 显示全部楼层
Y_G_G 发表于 2021-9-15 21:07
我知道你的意思,你是想通过电位器控制定时器
但你如果是查找一个ADC的数值的话,我说过了,很有可能是现实 ...

非常感谢大师的指导  这个问题困惑了我好几天  现在得到了完美的解决   太感谢了  非常重要的经验  同时也感谢你的耐心解答  谢谢  
回复

使用道具 举报

ID:254747 发表于 2021-9-16 21:36 | 显示全部楼层
在这里非常感谢各位大师的指导与解答  这个问题现在解决了    解决的方案就是   不用查找  用比大小的方式解决的   将语句  if(count >=ADC)ADC的点位是旋转的值    改成这样的就可以了   谢谢大家
回复

使用道具 举报

ID:731195 发表于 2021-9-29 15:12 | 显示全部楼层
你选择的是什么型号电位器
回复

使用道具 举报

ID:960157 发表于 2021-10-7 16:00 来自手机 | 显示全部楼层
电位器抽头对地加个1uf电容器,消除接触不良毛刺。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表