⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 anglemachine.c

📁 《角度测量器》 用光电编码器测量角度
💻 C
字号:
*/
#include "12f629.h"
#use delay(CLOCK=4000000,RESTART_WDT)
#use fast_io(A)
#define   NO      2      //连接74HC595的个数
#define   CPR      72   //36000/500光电编码器分辨率
#define   GPIO   0x5      //GP口地址
#define   WPU      0x95   //
#define   OSCCAL   0x90   //
#bit   DOUT=GPIO.0
#bit   CLK =GPIO.1
#bit   INA =GPIO.2
#bit   INB =GPIO.3
#bit   STR =GPIO.4
#bit   INZ =GPIO.5
int led_data[2];            //缓存74HC595显示数据
int bcd[5]={11,11,11,11,11};   //5位BCD码
int led_bit=0;            //当前显示位
long count=0;               //16位计数器
long count_new=0;         //计数器新值
long count_old=0;         //计数器旧值
short direct=1;         //转动方向
int const segs[13]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0x0,0x92,0x2};
int const digs[4]={0x7f,0xbf,0xdf,0xef};
//int16到5位BCD的转换
void int16_to_bcd5(long counter, int * bcd5) 
{
   const long c[5]={10000,1000,100,10,1};
   int i;
   long k;
   for(i=0;i<5;i++)
   {   
      k=0;
      while(counter>=c[i])
      {
         counter-=c[i];
         ++k;
      }
      bcd5[i]= k; 
   }
}
//将数据写入74HC595
void out_595(int* eo)
{
   int i;
   CLK=0;
   STR=0;
   for(i=1;i<=NO*8;++i)
   {
      if((*(eo)&0x01)==0)      //将最低位输出到DOUT
         DOUT=0;
         else
         DOUT=1;
      rotate_right(eo,NO);   //数组循环右移一位
      CLK=1;
      delay_cycles(2);
      CLK=0;
   }
   STR=1;      //输出到数码管
   delay_cycles(2);
   STR=0;
}
//LED数码管译码显示
void out_led(int c)
{
   led_data[1]=0xf0;
   out_595(led_data);         //数码管消隐
   led_data[0]=segs[bcd[c]];
   led_data[1]=digs[c];
   if(led_bit==2)
      bit_set(led_data[0],0);      //显示小数点
   out_595(led_data);         //刷新数码管数据
}
//计算计数器差值
long get_margin(long c_new,long c_old)
{
   if(c_new<c_old)   //如果计数器溢出翻转
      return(65536-c_old+c_new);
   else
      return(c_new-c_old);
}
//根据差值、旧角度值、转动方向计算新的角度值
long get_count(long c,long ct,short d)
{
   if(d==1)      //如果正转
   {
      ct=c+ct;
      if(ct>=3200)
         ct=ct%3200;
   }
   else         //如果反转
   {
      if(c>ct)
         ct=3200-(c-ct);
      else
         ct=ct-c;
   }
   return(ct);
}
//EXT中断处理,根据脉冲相位判断转动方向
#int_ext
void get_data()
{
   if(bit_test(INB,0))   //A相跳高时,若B相为高则正转
      direct=1;
   else               //B相为低则反转
      direct=0;
}
//主程序
void main()
{
   disable_interrupts(GLOBAL);       //关总中断
   setup_comparator(NC_NC_NC_NC);   //关闭比较器,全部设成IO
   port_a_pullups(FALSE);
   *OSCCAL=0xff;               //全速运行
   set_tris_a(0b00101100);      //初始化IO口
   ext_int_edge(L_TO_H);            //设置成上跳沿触发中断
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
   set_timer1(0);
   enable_interrupts(INT_EXT);      //开EXT中断
   enable_interrupts(GLOBAL);         //开总中断
   while (1)
   {
      long cou;
      long margin;
      restart_wdt();
      count_new=get_timer1();      //获得新的计数值
      margin=get_margin(count_new,count_old); //获得差值
      count_old=count_new;            //刷新旧的计数值
      count=get_count(margin,count,direct);   //获得新的角度值
      cou=(count*11.25);
      if((cou%10)>=5)   //四舍五入
         cou+=10;
      int16_to_bcd5(cou,bcd);
      if(cou<10000)      //消去数码管左边多余的零,节电
         bcd[0]=10;
      if(cou<1000)
         bcd[1]=10;
      out_led(led_bit);
      led_bit++;
      if(led_bit>=4)      //共扫描4位数码管
         led_bit=0;
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -