2017-08-11 55 views
2

系統是基本的,但我有可怕的問題,我不能解決它,請幫助我。 當我的系統工作時PIC繼續運行,但一天清除寄存器4-5次。PIC 16F628A清除其寄存器?

如何系統應該工作:

-I有一個PIC,氣動缸和3傳感器(具有24V DC作品)。 - 主傳感器接收來自另一個系統的信號。 - 當主傳感器發出信號時,如果氣缸向後,氣缸應該前進,直到前傳感器看到它,如果氣缸前進,氣缸應該後退,直到後傳感器看到它。

程序:

#include <16F628A.h> 

#FUSES NOWDT     //No Watch Dog Timer 
#FUSES NOBROWNOUT    //No brownout reset 
#FUSES NOLVP     //No low voltage prgming, B3(PIC16) or 
B5(PIC18) used for I/O 

#use delay(crystal=4000000) 

#use fast_io(a) 
#use fast_io(b) 

#define goForward PIN_A0 
#define comeBackward PIN_A1 
#define main_sensor PIN_B0 
#define positionSensorForward PIN_B5 
#define positionSensorBackward PIN_B4 

int1 pistonPositionedForward=0, pistonPositionedBackward=1; 
int1 positionForwardReg=0, positionBackwardReg=0; 
int1 pistonForwarding=0, pistonBackwarding=0; 

#priority rb,ext 

#int_RB NOCLEAR 
void B_change() 
{ 

    positionForwardReg=input(positionSensorForward); 
    positionBackwardReg=input(positionSensorBackward); 

if(positionForwardReg&&pistonForwarding) //if forwarding and forward sensor see 
{ 
    disable_interrupts(INT_RB); 

    output_low(goForward); 
    pistonPositionedForward=1; 
    pistonPositionedBackward=0; 

    write_eeprom(0,1); 
    write_eeprom(1,0); 

    pistonForwarding=0; 
    pistonBackwarding=0; 

    clear_interrupt(int_ext); 
    enable_interrupts(INT_EXT); 
} 

else if(positionBackwardReg&&pistonBackwarding) //if backwarding and backward sensor see 
{ 
    disable_interrupts(INT_RB); 

    output_low(comeBackward); 
    pistonPositionedForward=0; 
    pistonPositionedBackward=1; 

    write_eeprom(0,0); 
    write_eeprom(1,1); 

    pistonForwarding=0; 
    pistonBackwarding=0; 

    clear_interrupt(int_ext); 
    enable_interrupts(INT_EXT); 
} 

clear_interrupt(int_rb); 

} 

#int_ext NOCLEAR 
void ext_interrupt() 
{ 

    disable_interrupts(INT_EXT); 

    positionForwardReg=input(positionSensorForward); 
    positionBackwardReg=input(positionSensorBackward); 

    if(positionForwardReg^positionBackwardReg) //if one of position sensor is see then position according to sensor, else position according to memory 
    { 
    pistonPositionedForward=positionForwardReg; 
    pistonPositionedBackward=positionBackwardReg; 
    } 

    if(pistonPositionedForward) 
    { 
    pistonBackwarding=1; 
    pistonForwarding=0; 
    output_high(comeBackward); 

    clear_interrupt(int_rb); 
    enable_interrupts(INT_RB); 
    } 
    else if(pistonPositionedBackward) 
    { 
    pistonForwarding=1; 
    pistonBackwarding=0; 
    output_high(goForward); 

    clear_interrupt(int_rb); 
    enable_interrupts(INT_RB); 
    } 
    clear_interrupt(int_ext); 
} 

void main() 
{ 
    //to remember last position after power off 
    pistonPositionedForward=read_eeprom(0); 
    pistonPositionedBackward==read_eeprom(1); 

    set_tris_a(0x00); 
    set_tris_b(0xFF); 

    output_a(0x00); 
    delay_ms(1000); 

    ext_int_edge(L_TO_H); 

    clear_interrupt(int_ext); 
    enable_interrupts(INT_EXT); 

    enable_interrupts(GLOBAL); 

    while(TRUE) 
    { 

    } 

} 

而我的電路: CIRCUIT

* J2,J3連接selonoid閥

* J4,J5,J6連接3個傳感器1.銷+ 24VDC,2 。引腳GND,3.pin傳感器數據

*** B1和B2連接的改變。現在B1連接到B5,B2連接至B4

,這些都是我想:

-I有3個PIC他們都這樣做

-I改爲24V電源

同樣的事情 - 我取消了7805和7812,我連7805

我通過LED調試的單獨5V電源istead。有時系統停止運行,只是在一個位置等待。取主傳感器信號但什麼都沒有,並且活塞位置前進和活塞位置後退寄存器值爲0.我不能發現問題,它如何清除這些寄存器?

回答

2

您對RB未連接的引腳配置爲輸入,沒有內部上拉跌宕集。電噪聲很可能會觸發PORTB上不需要的中斷,這已知會發生。

中斷的使用是使整個邏輯有點難以遵循這樣一個簡單的裝置。你有沒有嘗試重寫程序不使用中斷(EXT除外)?它不應該花很長時間,我認爲這可能會大大提高可靠性和可維護性,而不會影響物理系統的性能。

我建議你先配置未使用PORTA和PORTB引腳輸出,看看問題是否會消失。如果失敗,重寫不使用中斷應該不超過一個小時。這可能是有道理的,因爲這可能比你已經花在追逐問題上的時間要短。

閱讀描述,我想出了這個解決方案。

#include <16F628A.h> 

#FUSES NOWDT     //No Watch Dog Timer 
#FUSES NOBROWNOUT    //No brownout reset 
#FUSES NOLVP     //No low voltage prgming, B5(PIC18) used for I/O 

#use delay(crystal=4000000) 

#use fast_io(a) 
#use fast_io(b) 

#define FWD_MOVE  PIN_A0 
#define BACK_MOVE  PIN_A1 
#define PORTA_RESET  (0x00) // outputs=LO, unused pins as outputs 
#define PORTA_TRISTATE (0x00) 

#define EXT_SENSOR  PIN_B0 
#define FWD_REST  PIN_B5 
#define BACK_REST  PIN_B4 
#define PORTB_RESET  (0xCE) // can't use pull ups because of HW logic... 
#define PORTB_TRISTATE (0x31) 

#define EEPROM_STATUS_ADDR (0x0000) 
#define EEPROM_STATUS_FWD (0x01) 
#define EEPROM_STATUS_BACK (0x00) 

int1 extLast; 
int1 extCur; 

void main() 
{ 
    // setup 
    output_a(PORTA_RESET): 
    output_b(PORTB_RESET): 

    // setting to last known state... 

    // safety check. 
    output_low(FWD_MOVE); 
    output_low(BACK_MOVE); 

    // This will activate the outputs to make sure we have good 
    // positioning. 
    switch(eeprom_read(EEPROM_STATUS_ADDR)) 
    { 
    default: // EEPROM error... I'll let you decide what to do here. 
      // either move forward or back. 
      // this implementation goes back by default. 

     eeprom_write(EEPROM_STATUS_ADDR, EEPROM_STATUS_BACK); 
     disable_interrupts(GLOBAL); 

     // falling through... 

    case EEPROM_STATUS_BACK: 
     output_high(BACK_MOVE); 
     break; 
    case EEPROM_STATUS_FWD: 
     output_high(FWD_MOVE); 
     break; 
    } 

    // activate outputs... watch your fingers! 
    set_tris_a(PORTA_TRISTATE); 
    set_tris_b(PORTB_TRISTATE); 

    extLast = input(EXT_SENSOR); 
    for (;;) 
    { 
     // read external sensor, take action. 
     extCur = input(EXT_SENSOR); 
     if (extCur && !extlast) 
     { 
      // safety check. 
      output_low(FWD_MOVE); 
      output_low(BACK_MOVE); 

      // control logic 
      switch(eeprom_read(EEPROM_STATUS_ADDR)) 
      { 
      default: // should never happen. 

       // falling through... 

      case EEPROM_STATUS_BACK: 
       output_high(FWD_MOVE); 
       eeprom_write(EEPROM_STATUS_ADDR, EEPROM_STATUS_FWD); 
       disable_interrupts(GLOBAL); 
       break; 

      case EEPROM_STATUS_FWD: 
       output_high(BACK_MOVE); 
       eeprom_write(EEPROM_STATUS_ADDR, EEPROM_STATUS_BACK); 
       disable_interrupts(GLOBAL); 
       break; 
      } 
     } 
     extLast = extCur; 

     // mechanical interface: 
     // read the limit guards and stop movement when done. 
     if (input(FWD_REST)) 
     { 
      output_low(FWD_MOVE); 
     } 
     if (input(BACK_REST)) 
     { 
      output_low(BACK_MOVE); 
     } 
    } 
} 

當然,我無法在現場檢查上面的代碼:)。

審查示意圖之後,我還必須提醒在2個輸出MOSFET並聯添加1N4001二極管給他們免受反向電壓尖峯更好的保護。MOSFET內置二極管不夠堅固。 1N4148或1N914也可以在那裏工作。

16F628的堆棧空間非常有限。看起來您在調用write_eeprom期間遇到堆棧溢出問題。畢竟,從中斷調用write_eeprom可能不是一個好主意。

舊版CCS編譯器中存在一個bug,與使用write_eeprom有關。看來write_eeprom在調用過程中啓用了中斷。寫入後,我添加了禁止中斷的調用。我不知道這個bug是否被修正,因爲我從不使用CCS。

[編輯]檢查您的硬件後。我意識到你不能使用內部上拉,因爲硬件邏輯是積極的。 PIC中的上拉電阻旨在與開路集電極配置中的NPN晶體管配合使用(發射極至地)。我相應地更改了代碼。

您寫入EEPROM的方式並不好。 eeprom寫入需要時間,第二次寫入通常在eeprom中斷中處理。在eeprom_write中啓用全局中斷並揭露EEIE的CCS錯誤並不能解決問題。未處理的中斷確實會產生復位。

+0

我第一次寫沒有中斷,但也出現了相同的問題。之後,我寫中斷。但會嘗試配置爲輸出未使用的引腳。我會記住我的下一個項目,謝謝。但是我正在尋找程序,我認爲如果任何B引腳調用中斷程序,它不會改變任何想法。例如,b7引腳調用觸發中斷它不能清除寄存器,可以嗎? –

+0

「清除寄存器」的意思根本不清楚。在輸出端設置未連接的引腳,或者至少將引腳設置爲高電平是標準做法。 PIC輸入引腳非常敏感。也許你應該在問題中不要打斷你的代碼,這樣我們才能看到它。 –

+0

我的意思是,如你所見,有兩位可以記住這個位置。活塞定位前進和活塞定位後退。當系統運行時,其中一個必須爲1(真),但systam在一天內失敗4-5次,並且這兩個寄存器都是0(假),這似乎是不可能的。因爲我認爲任何意外的中斷都不能將它們都改爲0(假)。我會在星期一試試你的建議,非常感謝你 –