2016-02-07 36 views
-1

我想要建立一個5位加/減計數器。當我能夠使仿真工作時,我會更加高興地購買這些零件來構建它。我到目前爲止使用的是ATmega8,但坦率地說,只要組件相當便宜,任何解決方案都適用於我。ATmega8加/減計數器不正確計數

我在網上找到了一個簡單的加號計數器,並且改變了它以包含一個down函數。我從代碼中刪除了一些可怕的_delay_ms(1000)聲明,這些聲明可能是爲了在輸入被保留時防止多次計數?它使櫃檯非常緩慢而且沒有反應。這是我到目前爲止: Circuit diagram

我遇到的問題是,它不計數,當它倒數不顯示零。

代碼: 的#include 的#include 的#include 的#include

#define F_CPU 4000000 

volatile uint16_t digits[5]={0,0,0,0,0}; //INITIALISE VARIABLE TO STORE INDIVIDUAL DIGITS OF THE NUMBER 

void breakup(uint16_t num) { //FUNCTION TO FIND THE INDIVIDUAL DIGITS OF THE NUMBER 
           // AND STORE THEM IN A GLOBAL VARIABLE 
    DDRD=0xFF; // INITIALISE PORTD AS ALL OUTPUT 
    PORTD=0x00; 
    unsigned int i=0; 
    while (num!=0) { 
     digits[i]=num%10; 
     num=num/10; 
     i++; 
    } 
    for(i=0;i<5;i++) { 
     PORTD=(1<<i); // 'i'th PORTD GIVEN HIGH 
     display(digits[i]); 
     _delay_us(600); 
     PORTD=(0<<i); //'i'th PORTD GIVEN LOW 
    } 
} 

void display (uint16_t num) { // Bit patterns changed from the original to correct for my hardware layout. 
    DDRB=0b11111111; 
    PORTB=0xFF; 
    switch(num) { 
     case 0: 
     PORTB=0b00111111; 
     break; 
     case 1: 
     PORTB=0b00000110; 
     break; 
     case 2: 
     PORTB=0b01011011; 
     break; 
     case 3: 
     PORTB=0b01001111; 
     break; 
     case 4: 
     PORTB=0b01100110; 
     break; 
     case 5: 
     PORTB=0b01101101; 
     break; 
     case 6: 
     PORTB=0b01111101; 
     break; 
     case 7: 
     PORTB=0b00000111; 
     break; 
     case 8: 
     PORTB=0b01111111; 
     break; 
     case 9: 
     PORTB=0b01101111; 
     break; 
     default: 
     PORTB=0xFF; 
    } 
} 

int main(void) { 
    DDRB=0xFF; //Initialise PORTB as all outputs. 
    DDRC=0x00; //Initialise PORTC as all inputs. 
    PORTC=0b01000000; //Enable internal pullup for the reset pin. 
    char x; 
    char down_button_press = 0; 
    char up_button_press = 0; 
    uint16_t i, c=5; 
    while(1) { 
     x=PINC&0b00000001; //Check condition of PC0 DOWN button. 
     if (x==0 && down_button_press==0) { 
      c--; 
      breakup(c); //Pass c to the breakup routine and display. 
      down_button_press++; 
     } 
     if (x==1) { 
     down_button_press = 0; 
     } 
     x=PINC&0b00000010; //Check condition of PC1 UP button. 
     if (x==0 && up_button_press==0) { 
      c++; 
      breakup(c); //Pass c to the breakup routine and display. 
      up_button_press++; 
     } 
     if (x==1) { 
     up_button_press = 0; 
     } 
     else 
     breakup(c); 
    } 
} 

計數並在最後倒計時的代碼位基本上是相同的,所以我不知道爲什麼它倒計時,但不起來。在按下按鈕時試圖停止計數器進行多次計數,我已經包含了一種鎖存器&& up_button_press==0。它不應該是debouncing代碼,它只是讓我每次按下按鈕時獲得單個增量和單個遞減。 我設法找出是不指望了,因爲當按鈕後變爲高電平向上鎖存未被清除 - 所以&& up_button_press==0條件是不正確的:

if (x==1) { 
    up_button_press = 0; 
    } 

如果有人能幫助我把事情做好,我會很感激。如果有幫助,我可以添加Proteus仿真文件?

+0

對不起,但故事和圖片不相關,但使您的問題不太清楚。我建議刪除它。 (旁註:不知道哪些固態光盤對她有好處,但無論如何)。 SO不是諮詢或編碼服務。見[問]。 (並且在表達式中使用空格大大增強了可讀性)。 – Olaf

+0

SSD =在此上下文中的七段顯示。 – Ctx

+0

我不是問這些問題的專家。我已經刪除了混亂的位。 –

回答

1

有,因爲你知道一些代碼的問題。

1)關於代碼塊,在breakup()與開始:

while (num!=0) { 

該循環應該總是迭代的5倍,而不管num

值這將導致所有可能的數字在顯示,包括0

以下代碼是我將如何實現所需的功能。

注意到大多數魔法數字的轉換都有一個有意義的名字。

注意清除main()函數中的邏輯。

請注意可能的顯示值從16k到99999的擴展名。

注意清除雜亂和不需要的變量。

注意使用有意義的(和唯一的)變量名稱。

我想知道爲什麼使用內部上拉電阻而不是PINxy輸出設置7段數字。但是我將它與OP發佈的代碼保持一致。

#include <stdint.h> 

#define F_CPU 4000000 

#define NUM_DIGITS (5) 
#define MAX_DISPLAYED_VALUE (99999) 

#define UP_BUTTON (0b00000010) 
#define DN_BUTTON (0b00000001) 

#define DIGIT_0 (0b00111111) 
#define DIGIT_1 (0b00000110) 
#define DIGIT_2 (0b01011011) 
#define DIGIT_3 (0b01001111) 
#define DIGIT_4 (0b01100110) 
#define DIGIT_5 (0b01101101) 
#define DIGIT_6 (0b01111101) 
#define DIGIT_7 (0b00000111) 
#define DIGIT_8 (0b01111111) 
#define DIGIT_9 (0b01101111) 

// prototypes 
void initialize(void); 
void display (uint8_t digitValue); 
void breakup (uint32_t num); 

uint8_t digits[]={0,0,0,0,0}; //INITIALISE VARIABLE TO STORE INDIVIDUAL DIGITS OF THE NUMBER 



int main(void) 
{ 

    uint32_t num = 0; // initialize value to display 

    initialize();  // initialize hardware 

    while(1) 
    { 
     if (PINC & DN_BUTTON) 
     { // then down button pressed 
      if(num > 0) 
      { 
       num--; 
      } 
     } 

     else if (PINC & UP_BUTTON) 
     { // then up button pressed 
      if(num < MAX_DISPLAYED_VALUE) 
      { 
       num++; 
      } 
     } // end if which button 
     breakup(num); 
    } // end while forever 
} // end function: main 



void breakup(uint32_t num) 
{ //FUNCTION TO FIND THE INDIVIDUAL DIGITS OF THE NUMBER 
           // AND STORE THEM IN A GLOBAL VARIABLE 
    for(size_t i=0; i< NUM_DIGITS; i++) 
    { 
     digits[i]= (uint8_t)(num%10); 
     num=num/10; 
    } 

    for(size_t i=0; i<NUM_DIGITS; i++) 
    { 
     display(digits[i]); // preset the value to display 
     PORTD=(1<<i); // select which 7 segment digit 
     _delay_us(600); 
     PORTD = 0; // unselect all the seven segment displays 
    } 
} 



void display (uint8_t digitValue) 
{ // Bit patterns changed from the original to correct for my hardware layout. 

    switch(digitValue) 
    { 
     case 0: 
      PORTB=DIGIT_0; 
      break; 

     case 1: 
      PORTB=DIGIT_1; 
      break; 

     case 2: 
      PORTB=DIGIT_2; 
      break; 

     case 3: 
      PORTB=DIGIT_3; 
      break; 

     case 4: 
      PORTB=DIGIT_4; 
      break; 

     case 5: 
      PORTB=DIGIT_5; 
      break; 

     case 6: 
      PORTB=DIGIT_6; 
      break; 

     case 7: 
      PORTB=DIGIT_7; 
      break; 

     case 8: 
      PORTB=DIGIT_8; 
      break; 

     case 9: 
      PORTB=DIGIT_9; 
      break; 

     default: 
      break; 
    } // end switch 
} // end function: display 



void initialize() 
{ 
    DDRB=0xFF;   // all outputs 
    //PORTB=0xFF;  // enable all internal pullups 

    DDRC=0x00;   // all inputs. 
    PORTC=0b01000000; //Enable internal pullup for the reset pin. 

    DDRD=0xFF;   // all outputs 
    PORTD=0x00;  // disable all internal pullups 
} // end function: initialize 
+0

這是非常讚賞,但我在構建這個代碼期間得到16錯誤。我不知道有足夠的C來理解爲什麼。你能發現它不顯示00000的原因嗎? –

+0

請發佈,這裏作爲評論,其中一個錯誤。 – user3629249

+0

我的答案中的第一對幾行指出了爲什麼0不顯示的問題。具體而言,如果值爲0,則從不輸入處理循環 – user3629249

2

你的錯誤是在這裏:

x=PINC&0b00000010; //Check condition of PC1 UP button. 
... 
if (x==1) { 
    up_button_press = 0; 

x是2如果按下按鈕(因爲你的面具是0x2檢查PORTC的第二位),所以檢查:

if (x==2) { 
    up_button_press = 0; 
+0

這確實會改變一些東西,但是現在向上按鈕必須保持被按下才能顯示數字。無論如何,它給了我一些東西可以玩。讓我花一點時間看看我能用它做些什麼。謝謝。 –

+0

@PeteG - 那是因爲你正在使用'else breakup(c);'在while循環的底部。 –

+0

輝煌!我只是解決了這個問題,現在它正在工作。謝謝@Ctx –