音影先锋亚洲天堂网|电影世界尽头的爱完整版播放|国产 熟女 91|高清无码免费观看欧美日韩|韩国一区二区三区黄色录像|美女亚洲加勒比在线|亚洲综合网 开心五月|7x成人在线入口|成人网站免费日韩毛片区|国产黄片?一级?二级?三级

登錄 免費(fèi)注冊(cè) 首頁(yè) | 行業(yè)黑名單 | 幫助
維庫(kù)電子市場(chǎng)網(wǎng)
技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測(cè)控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng)
驅(qū)動(dòng)編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機(jī) | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計(jì) | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe

《角度測(cè)量器》C程序范例

作者:ocon 欄目:單片機(jī)
《角度測(cè)量器》C程序范例
這幾天呆在窩里無(wú)聊,做了個(gè)小禮物送給搞機(jī)械的朋友,貼出來(lái)給新人看看:

/*
《角度測(cè)量器》
用光電編碼器測(cè)量角度,每個(gè)脈沖為0.72度。
測(cè)量范圍:-198.0~450.0度
為保證不錯(cuò)過(guò)脈沖,計(jì)數(shù)用電平跳變中斷實(shí)現(xiàn),盡量加快處理過(guò)程。
數(shù)碼管掃描顯示和數(shù)據(jù)換算在主循環(huán)實(shí)現(xiàn)。
譯碼器用10米長(zhǎng)5芯屏蔽線與數(shù)顯器的兩片74HC595連接。
MCU為12F629,使用內(nèi)部4兆R(shí)C振蕩和內(nèi)部復(fù)位功能。
LED燈顯示工作狀態(tài),平時(shí)長(zhǎng)亮,收到光電編碼器脈沖時(shí)暫滅。
經(jīng)驗(yàn)教訓(xùn):有些早期批號(hào)74HC5953.3V下會(huì)發(fā)生數(shù)據(jù)異常移位。
完成時(shí)間:2006年1月31日
編譯器:CCSC V3.182
程序版本:V1.0
南寧?仉娮佑邢薰
http://www.ocon.cn/
作者:Wind
*/
#include "12f629.h"
#use delay(CLOCK=4000000,RESTART_WDT)
#use fast_io(A)
#define   NO      2      //連接74HC595的個(gè)數(shù)
#define   CPR      72      //光電編碼器分辨率
#define   ZO      275      //歸零位
#define   GPIO   0x5      //GP口地址
#bit   DOUT=GPIO.0
#bit   CLK =GPIO.1
#bit   INA =GPIO.2
#bit   INB =GPIO.3
#bit   LED =GPIO.4
#bit   STR =GPIO.5
int led_data[2];            //緩存74HC595顯示數(shù)據(jù)
int bcd[5]={0,0,0,0,0};   //5位BCD碼
int led_bit=0;            //當(dāng)前顯示位
SHORT fu=0;               //負(fù)號(hào)標(biāo)志
LONG count;                //16位計(jì)數(shù)器
int const segs[11]={0b11111100,0b0110000.html">100000,0b11011010,0b11110010,0b01100110,0b10110110,0b10111110,0b1110000.html">100000,0b11111110,0b11110110,0b00000000};
int const digs[4]={0b01111111,0b10111111,0b11011111,0b11101111};
//int16到5位BCD的轉(zhuǎn)換
void int16_to_bcd5(LONG counter, int * bcd5)
{
   const LONG c[5]={10000.html">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;
   }
}
//將數(shù)據(jù)寫(xiě)入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);   //數(shù)組循環(huán)右移一位
      CLK=1;
      CLK=0;
   }
   STR=1;      //輸出到數(shù)碼管
   STR=0;
}
//LED數(shù)碼管譯碼顯示
void out_led(int c)
{
   led_data[1]=0xf0;
   out_595(led_data);         //數(shù)碼管消隱
   led_data[0]=segs[bcd[c]];
   led_data[1]=digs[c];
   if(led_bit==2)
      bit_set(led_data[0],0);      //顯示小數(shù)點(diǎn)
   if(fu&&(led_bit==0))
      bit_set(led_data[0],1);      //顯示負(fù)號(hào)
   out_595(led_data);         //刷新數(shù)碼管數(shù)據(jù)
}
//EXT中斷處理,根據(jù)轉(zhuǎn)動(dòng)方向(脈沖相位)加減計(jì)數(shù)
#int_ext
get_data()
{
   if(bit_test(INB,0)&&(count<900))   //A相跳高時(shí),若B相為高則加,
      count++;
   if(!bit_test(INB,0)&&(count>0))   //B相為低則減
      count--;
   LED=1;
}
//主程序
void main()
{
   count =ZO;                     //角度零位值
    set_tris_a(0xC);                 //初始化IO口
   setup_comparator(NC_NC_NC_NC);   //關(guān)閉比較器,全部設(shè)成IO
   disable_interrupts(GLOBAL);       //關(guān)總中斷
   ext_int_edge(L_TO_H);            //設(shè)置成上跳沿觸發(fā)中斷
   enable_interrupts(INT_EXT);      //開(kāi)EXT中斷
   enable_interrupts(GLOBAL);         //開(kāi)總中斷
   while (1)
   {
      int i;
      LONG con;
      LED=0;
      if(count>=ZO)         //負(fù)數(shù)處理
      {
         fu=0;               //負(fù)數(shù)標(biāo)志
         con=count-ZO;
      }
      else
      {
         fu=1;
         con=ZO-count;
      }
      int16_to_bcd5(con*CPR,bcd);
      if(con*CPR<10000.html">10000)      //消去數(shù)碼管左邊多余的零,節(jié)電
         bcd[0]=10;
      if(con*CPR<1000)
         bcd[1]=10;
      //數(shù)碼管掃描循環(huán),每掃100次跳出重新計(jì)算一次BCD數(shù)據(jù)
      for(i=1;i<=100;i++)
      {
         if(i!=1)   //若剛忙完BCD運(yùn)算,則免去本次延時(shí)以提升顯示效果
            delay_us(500);
         out_led(led_bit);
         led_bit++;
         if(led_bit>=4)      //共掃描4位數(shù)碼管
         led_bit=0;
      }
   }
}

* - 本貼最后修改時(shí)間:2006-2-11 23:56:33 修改者:ocon

2樓: >>參與討論
ocon
電路圖1
 

3樓: >>參與討論
ocon
電路圖2
 

4樓: >>參與討論
旋風(fēng)羊
好東西收下
 
5樓: >>參與討論
陳雙君
你圖都不給我看一下的啊.
你圖都不給我看一下的。

6樓: >>參與討論
ZHOUYH
好貼呀!
 
7樓: >>參與討論
ocon
譯碼器
 

8樓: >>參與討論
ocon
數(shù)顯器
 

9樓: >>參與討論
ocon
整體
 

10樓: >>參與討論
xymxym
好貼!頂!
沖著樓主正月之際還在埋頭苦干的精神就該頂,更何況貼于此分享更該頂!頂頂頂.... ^_^

11樓: >>參與討論
蘭天白云
74HC595的驅(qū)動(dòng)能力很強(qiáng)嗎?
 
12樓: >>參與討論
ocon
和PIC差不多,驅(qū)動(dòng)幾個(gè)數(shù)碼管足夠了。
 
13樓: >>參與討論
jackwu
rotate_right()函數(shù)內(nèi)容?
rotate_right(eo,NO);   //數(shù)組循環(huán)右移一位


14樓: >>參與討論
ocon
CCSC的內(nèi)建函數(shù)
Syntax:
rotate_right (address, bytes)

Parameters:
address is a pointer to MEMORY, bytes is a count of the NUMBER of bytes to work with.

Returns:
undefined

Function:
Rotates a bit through an array or structure.  The address  may be an array identifier or an address to a byte or  structure (such as &data).  Bit 0 of the lowest BYTE in RAM is considered the LSB.

Examples:
struct {
   int cell_1 : 4;
   int cell_2 : 4;
   int cell_3 : 4;
   int cell_4 : 4; } cells;
rotate_right( &cells, 2);
rotate_right( &cells, 2);
rotate_right( &cells, 2);
rotate_right( &cells, 2);
// cell_1->4, 2->1, 3->2 and 4-> 3








15樓: >>參與討論
liao_43
我覺(jué)得你這個(gè)測(cè)量角度方法,響應(yīng)速度不是很快.
我估算了一下,在不丟失脈沖下,光電旋轉(zhuǎn)編碼器最大的轉(zhuǎn)速為10轉(zhuǎn)每秒.

16樓: >>參與討論
ocon
有錢(qián)途!你很認(rèn)真。這個(gè)東西后來(lái)進(jìn)行了改進(jìn),速度已不成問(wèn)題
/*
《角度測(cè)量器》
用光電編碼器測(cè)量角度,每個(gè)脈沖為0.72度。
測(cè)量范圍:0.0~360.0度
為保證不錯(cuò)過(guò)脈沖,用timer1計(jì)數(shù),在電平跳變中斷里判斷轉(zhuǎn)動(dòng)方向,盡量加快處理過(guò)程。
數(shù)據(jù)換算和數(shù)碼管掃描顯示在主循環(huán)中實(shí)現(xiàn)。
譯碼器用10米長(zhǎng)5芯屏蔽線與數(shù)顯器的兩片74HC595連接。
MCU為12F629,使用內(nèi)部4兆R(shí)C振蕩和內(nèi)部復(fù)位功能。
經(jīng)驗(yàn):有些早期批號(hào)74HC5953.3V下會(huì)發(fā)生數(shù)據(jù)異常移位。
編譯器:CCSC V3.182
程序版本:
V1.0 2006年1月31日   測(cè)量范圍為-198~450度
V1.1 2006年2月1日   測(cè)量范圍改成0.0~360度,循環(huán)復(fù)零,增加四舍五入
V1.2 2006年2月2日   增加絕對(duì)零位Z檢測(cè)
v1.3 2006年2月10日   為了增加精度用齒輪將分辨率放大6.4倍,取消零位Z檢測(cè),
改用timer1計(jì)數(shù)以提高速度,通過(guò)提取差值來(lái)計(jì)算角度。為避免在兩次讀取timer1
期間發(fā)生換向而導(dǎo)致計(jì)算錯(cuò)誤,將計(jì)算工作移到掃描循環(huán)中進(jìn)行以加快速度。
因機(jī)械的慣性,換向之前定會(huì)停一段時(shí)間,只要掃描周期小于此停止時(shí)間就可保證精度。

南寧?仉娮佑邢薰
http://www.ocon.cn/
作者:Wind
*/
#include "12f629.h"
#use delay(CLOCK=4000000,RESTART_WDT)
#use fast_io(A)
#define   NO      2      //連接74HC595的個(gè)數(shù)
#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顯示數(shù)據(jù)
int bcd[5]={11,11,11,11,11};   //5位BCD碼
int led_bit=0;            //當(dāng)前顯示位
LONG count=0;               //16位計(jì)數(shù)器
LONG count_new=0;         //計(jì)數(shù)器新值
LONG count_old=0;         //計(jì)數(shù)器舊值
SHORT direct=1;         //轉(zhuǎn)動(dòng)方向
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的轉(zhuǎn)換
void int16_to_bcd5(LONG counter, int * bcd5)
{
   const LONG c[5]={10000.html">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;
   }
}
//將數(shù)據(jù)寫(xiě)入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);   //數(shù)組循環(huán)右移一位
      CLK=1;
      delay_cycles(2);
      CLK=0;
   }
   STR=1;      //輸出到數(shù)碼管
   delay_cycles(2);
   STR=0;
}
//LED數(shù)碼管譯碼顯示
void out_led(int c)
{
   led_data[1]=0xf0;
   out_595(led_data);         //數(shù)碼管消隱
   led_data[0]=segs[bcd[c]];
   led_data[1]=digs[c];
   if(led_bit==2)
      bit_set(led_data[0],0);      //顯示小數(shù)點(diǎn)
   out_595(led_data);         //刷新數(shù)碼管數(shù)據(jù)
}
//計(jì)算計(jì)數(shù)器差值
LONG get_margin(LONG c_new,LONG c_old)
{
   if(c_new<c_old)   //如果計(jì)數(shù)器溢出翻轉(zhuǎn)
      return(65536-c_old+c_new);
   else
      return(c_new-c_old);
}
//根據(jù)差值、舊角度值、轉(zhuǎn)動(dòng)方向計(jì)算新的角度值
LONG get_count(LONG c,LONG ct,SHORT d)
{
   if(d==1)      //如果正轉(zhuǎn)
   {
      ct=c+ct;
      if(ct>=3200)
         ct=ct%3200;
   }
   else         //如果反轉(zhuǎn)
   {
      if(c>ct)
         ct=3200-(c-ct);
      else
         ct=ct-c;
   }
   return(ct);
}
//EXT中斷處理,根據(jù)脈沖相位判斷轉(zhuǎn)動(dòng)方向
#int_ext
void get_data()
{
   if(bit_test(INB,0))   //A相跳高時(shí),若B相為高則正轉(zhuǎn)
      direct=1;
   else               //B相為低則反轉(zhuǎn)
      direct=0;
}
//主程序
void main()
{
   disable_interrupts(GLOBAL);       //關(guān)總中斷
   setup_comparator(NC_NC_NC_NC);   //關(guān)閉比較器,全部設(shè)成IO
   port_a_pullups(FALSE);
   *OSCCAL=0xff;               //全速運(yùn)行
   set_tris_a(0b00101100);      //初始化IO口
   ext_int_edge(L_TO_H);            //設(shè)置成上跳沿觸發(fā)中斷
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
   set_timer1(0);
   enable_interrupts(INT_EXT);      //開(kāi)EXT中斷
   enable_interrupts(GLOBAL);         //開(kāi)總中斷
   while (1)
   {
      LONG cou;
      LONG margin;
      restart_wdt();
      count_new=get_timer1();      //獲得新的計(jì)數(shù)值
      margin=get_margin(count_new,count_old); //獲得差值
      count_old=count_new;            //刷新舊的計(jì)數(shù)值
      count=get_count(margin,count,direct);   //獲得新的角度值
      cou=(count*
17樓: >>參與討論
ocon
這個(gè)小工具用于校準(zhǔn)大型印刷機(jī)。
 
18樓: >>參與討論
liao_43
我覺(jué)得你的新的程序里還有點(diǎn)問(wèn)題.
"因機(jī)械的慣性,換向之前定會(huì)停一段時(shí)間,只要掃描周期小于此停止時(shí)間就可保證精度"
   我覺(jué)得齒輪嚙合會(huì)產(chǎn)生抖動(dòng),特別是齒輪在慢速轉(zhuǎn)動(dòng)時(shí),會(huì)使光電編碼器在極短時(shí)間內(nèi)來(lái)回?cái)[動(dòng),而你主程序處理的時(shí)間比較長(zhǎng),有可能漏掉脈沖.

19樓: >>參與討論
ocon
已經(jīng)經(jīng)過(guò)現(xiàn)場(chǎng)測(cè)試,目前沒(méi)有發(fā)現(xiàn)你說(shuō)的抖動(dòng)現(xiàn)象。
這個(gè)東西在檢修機(jī)器的時(shí)候用,機(jī)器運(yùn)行在人工點(diǎn)動(dòng)方式,效果很好。如果要處理好極短時(shí)間內(nèi)的頻繁換向,就不能用一般的單片機(jī),這樣成本會(huì)高很多,這是送給好友的小禮物,不能做得太貴了。

20樓: >>參與討論
liao_43
我前一段時(shí)間也做了一個(gè)角度測(cè)量器.
  用的光電編碼器是2000P/R,16F74,20MHZ,在頻繁換向時(shí),檢測(cè)脈波的速度可以達(dá)到50KHz,不過(guò)我覺(jué)得這個(gè)速度不理想.所以一直在想,怎樣才能做到檢測(cè)速度達(dá)到5MHZ.因?yàn)槲矣幸粋(gè)光電編碼器是81000P/R的,一直沒(méi)有用上.
   今天早上起床時(shí),靈感一來(lái),想到一個(gè)辦法,用12F629,在頻繁換向時(shí),也可以做到5MHz的檢測(cè)速度(理論上).有空時(shí),我再做一個(gè)試試,驗(yàn)證一下.

21樓: >>參與討論
ocon
有什么辦法?說(shuō)說(shuō)看
我試過(guò)在換向中斷里記錄timer1的即時(shí)值,但在角度刷新之前換多幾次就沒(méi)用了,沒(méi)那么多RAM來(lái)緩存。

22樓: >>參與討論
陳雙君
電路圖呢?
電路圖呢?

我看不懂的。

23樓: >>參與討論
kowajw
re:《角度測(cè)量器》C程序范例
關(guān)注

24樓: >>參與討論
長(zhǎng)天秋水
蠻有用的
謝謝樓主啊

參與討論
昵稱(chēng):
討論內(nèi)容:
 
 
相關(guān)帖子
定時(shí)不準(zhǔn)的問(wèn)題,請(qǐng)教各位大人。「兄x!
尋單片機(jī)
一個(gè)奇怪的問(wèn)題.通信影響工作電壓求助
ICD2使用請(qǐng)教
請(qǐng)教一下:16F716和16C716僅僅是存儲(chǔ)器的不同嗎?
免費(fèi)注冊(cè)為維庫(kù)電子開(kāi)發(fā)網(wǎng)會(huì)員,參與電子工程師社區(qū)討論,點(diǎn)此進(jìn)入


Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號(hào)