找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2600|回复: 4
收起左侧

STC12C5A60S2单片机pwm可调之旋转编码器动态赋值问题

[复制链接]
ID:254747 发表于 2019-8-9 23:14 | 显示全部楼层 |阅读模式
经过不断的努力调试  现在程序基本可以动态赋值给定时器了 可以实现连续可调频率   但是需要把定时器重装初值的过程放到 旋转编码器的函数里面才可以 “  //  pinlvgengxin(Sd_Key_Value );”就是这个函数我放里面就能正常工作      如果通过旋转编码器的返回值来赋值的话,就不能正常工作了,请问有什么办法解决吗  单片机程序如下
  1. #include <STC12C5A60S2.H>
  2. #define FOSC 18432000
  3. unsigned char  Data_key();
  4. unsigned int TH,TL;XHZ;          //xhz在下面算出来的时候是一个长整形的数所以用 long
  5. unsigned char  Last_Bmb_Status;      //上一个B口的状态
  6. unsigned char  Curent_Bmb_Status;  //当前的状态
  7. unsigned char   Sd_flag=10;              //按键被转动,标志位,初始状态为0;     flag不是C语句的关键语言,可以是其它名字,但是在语句里面主要起
  8.                                            //暂停程序,转去执行其它程序的作用,在当前状态要做一个标记,故用标志这个单词;
  9. unsigned char  Sd_Key_Value;        //   键值  初始值为0
  10. sbit    BUZ=P3^0;
  11. sbit    Pin_Portry_A=P2^4;
  12. sbit    Pin_Portry_B=P2^3;      //编码器三个脚的定义,sd为开关按键,sd为按下的缩写单词;
  13. sbit    Pin_Portry_Sd=P2^2;
  14. sbit    LED=P3^7;
  15. void    pinlvgengxin(unsigned char x );

  16. /*
  17. void delay1_key_ms(unsigned int xms)          //表示在key.c这个文件中使用的延时函数
  18. {                                       
  19.      unsigned int i,j;                                         
  20.          for(i=xms;i>0;i--)
  21.            for (j=960;j>0;j--);
  22. }  */


  23. static void   Timer0Init(void)        
  24. {


  25.          XHZ=10;
  26.     AUXR |= 0x80;                //定时器时钟1T模式
  27.     TMOD &= 0xF0;                //设置定时器模式
  28.     TMOD |= 0x01;                //设置定时器模式
  29.         TH0 =TH=(65536-18432000/((unsigned long)XHZ*256))/256;                //设置定时初值
  30.     TL0 =TL=(65536-18432000/((unsigned long)XHZ*256))%256;                //设置定时初值
  31.         TF0 = 0;                //清除TF0标志
  32.         TR0 = 1;                //定时器0开始计时        
  33.         EA=1;
  34.         ET0=1;
  35. }

  36. void main()
  37. {
  38.         Timer0Init();
  39.     CCON = 0;                       
  40.     CL = 0;                        
  41.     CH = 0;
  42.     CMOD = 0x04;                    
  43.     CCAP0H = CCAP0L = 0x80;         //PWM0 port output 50% duty cycle square wave
  44.     CCAPM0 = 0x42;                  //PCA module-0 work in 8-bit PWM mode and no PCA interrupt
  45.          
  46.     CCAP1H = CCAP1L = 0x80;         //PWM1 port output 0% duty cycle square wave
  47.     PCA_PWM1 = 0x00;
  48.     CCAPM1 = 0x42;
  49.     CR = 1;                         //PCA timer start run

  50.     while (1)
  51.         {
  52.                
  53.            pinlvgengxin(Data_key() );
  54.             
  55.          }  

  56. }

  57. void  pinlvgengxin(unsigned char x )

  58. {

  59.                  
  60.                  TR0=0;
  61.                 XHZ=x;//Sd_Key_Value;//把Sd_Key_Value每次变化的值写XHZ
  62.          TH0 =TH=(65536-18432000/((unsigned long)XHZ*256))/256;                //设置定时初值
  63.          TL0 =TL=(65536-18432000/((unsigned long)XHZ*256))%256;                //设置定时初值
  64.                  TR0=1;
  65.                  
  66.         
  67. }  




  68. /*按键函数*/
  69. unsigned char  Data_key()
  70. {
  71.         
  72.            Last_Bmb_Status=Pin_Portry_B; //第一步读出B口的值,b口接在P2.1上面的,上电后单片机默认高电平,故B口也是高电平;
  73.         while(!Pin_Portry_A)  //当A口等于0表示,开个被转动,然后while取反为1,此时为真进入while语句,
  74.         {
  75.            Sd_flag=1;
  76.            Curent_Bmb_Status=Pin_Portry_B;//在把B口的值保存为当前状态加以判断;
  77.                                    //当flag为1的时候,表示开个被旋动过;
  78.         }

  79.         if(1== Sd_flag)  
  80.         {                                       
  81.             Sd_flag=0;     //开关旋动标志位清0      
  82.                     

  83.         if((0==Last_Bmb_Status)&&(1==Curent_Bmb_Status))  //顺时针旋转   如果Last __Bmb__Status=0,并且Curent__Bmb__Status=1;
  84.         {                                                                                                   //的时候满足条件,也就是if(0,1),故B口当前为(0,1)状态为顺时针模式
  85.         
  86.            
  87.            if(Sd_Key_Value<255)          //判断Sd_Key_Value是否小于225,如果是自++1
  88.               {
  89.                   Sd_Key_Value++;
  90.                         
  91.               }
  92.           else                                         //否则
  93.              {
  94.                   Sd_Key_Value=0;   //如果大于255的时候就 清0;防止溢出;
  95.                         
  96.              }
  97.            }
  98.             
  99.         if((1==Last_Bmb_Status)&&(0==Curent_Bmb_Status))  //逆时针旋转    如果Last __Bmb__Status=1,并且Curent__Bmb__Status=0;
  100.         {                                                                                                   //的时候满足条件,也就是if(1,0),故B口当前为(1,0)状态为逆时针模式
  101.         
  102.            
  103.           if(Sd_Key_Value>0)       //判断Sd_Key_Value是否大于255.如果大于就--1
  104.             {
  105.                     Sd_Key_Value--;
  106.                  
  107.             }
  108.          else                                    //否则
  109.             {
  110.              Sd_Key_Value=255;   //如果小于0的时候就给 Sd__Key___Value赋值为255.
  111.                           
  112.             }
  113.          
  114.          }
  115.            //  pinlvgengxin(Sd_Key_Value );
  116.                  


  117.         
  118.     }

  119.    return  Sd_Key_Value;    //把Sd_Key_Value的值返回到unsigned char  Data_key()函数里面  
  120.                             //在调用unsigned char  Data_key()这个函数的时候就相当于是调用
  121.                                                         //这个Sd_Key_Valued的实时值
  122. }





  123. void tm0_isr() interrupt 1 using 1
  124. {
  125.          

  126.      TH0 =TH;                //设置定时初值
  127.      TL0 =TL;                //设置定时初值
  128. }
复制代码


回复

使用道具 举报

ID:401564 发表于 2019-8-10 09:16 | 显示全部楼层
1,编码开关设定为1mS左右的中断,在定时器的中断程序中判断编码开关是正转动还是反转动
2,设定一个变量,进入定时器中断一次就减1,编码开关有效转动一次就赋值一次,可以是100或者200之类的,这样一来就可以实现:只要你编码开关还在转动,这个变量就一直在赋值,当编码开关不再转动,也要进入定时器中断很多次才能让这个变量为0
3,写入PWM要先查询之前设定的变量,不为0就不写入
回复

使用道具 举报

ID:254747 发表于 2019-8-10 11:22 | 显示全部楼层
Y_G_G 发表于 2019-8-10 09:16
1,编码开关设定为1mS左右的中断,在定时器的中断程序中判断编码开关是正转动还是反转动
2,设定一个变量 ...

非常感谢您的回答   我去尝试一下  那我就需要在开一个定时器了哦  因为定时器0的溢出是随时发生变化的
回复

使用道具 举报

ID:401564 发表于 2019-8-10 16:20 | 显示全部楼层
不将就123 发表于 2019-8-10 11:22
非常感谢您的回答   我去尝试一下  那我就需要在开一个定时器了哦  因为定时器0的溢出是随时发生变化的

是要在定时器中断程序里面检测编码开关的有效与否,定时器中断设定在1mS或者是2mS,这样的话就不会丢码了,而且,编码开关各类是有几种的,就算是一样的型号,编码有效的确认方式也是不同的
像我用的EC11就有两种:步数是一样的,一种是:编码开关停止转动之后,两边的引脚和中间的引脚是固定为短路状态的。
另一种是:编码开关停止转动之后,有时候是短路,有时候是开路
所以,你要先确定好你的开关是哪种的的,但如果你的代码现在已经能用了,就说明已经对了
回复

使用道具 举报

ID:254747 发表于 2019-8-12 13:59 | 显示全部楼层
Y_G_G 发表于 2019-8-10 16:20
是要在定时器中断程序里面检测编码开关的有效与否,定时器中断设定在1mS或者是2mS,这样的话就不会丢码了 ...

哎呀  非常 改下您的解答 ,目前所有的问题已经得到了解决  
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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