2017-03-10 61 views
0

我正在使用微控制器和I/O板。我的代碼檢查I/O板上某些固定按鈕的狀態(ON/OFF),並根據按鈕的狀態執行按位操作的int值,以表示0-15或0000至1111之間的數字二進制文件。AVR C串行通信:打印號碼固定按鈕

我的I/O板 enter image description here

我有我的船上DS1 4固定按鈕 - DS4,DS1是LSB,而DS4是MSB。因此,例如:

DS1 = ON, DS2 = OFF, DS3 = OFF, DS4 = OFF 
num = 0001 binary and 1 in decimal 

而且

DS1 = ON, DS2 = OFF, DS3 = ON, DS4 = OFF 
num = 0101 binary and 5 in decimal 

我有一個名爲「printDec」功能,需要一個int值,在位數方面發現它的大小,並將其轉換爲字符數組或字符串,然後一次將其傳輸到串行通信屏幕。

#include <avr/io.h> 
#include <util/delay.h> 

#include <stdlib.h> 
#include <string.h> 


#define F_CPU 16000000UL 


/* 
    Input Button 
    --------------------------------------- 
    Romeo Board : | d2 | d3 | d4 | d5 | 
    Atmega chip : | pd2 | pd3 | pd4 | pd5 | 
    I/O Board : | DS1 | DS2 | DS3 | DS4 | 

*/ 

void initUART(unsigned int baud); 
void transmitByte(unsigned char data); 
unsigned char receiveByte(void); 

int getNumOfDigits(int num); 
void printDec(int num); 

int main(void) { 

    int num = 0; 
    int old_num = 0; 

    DDRD = 0b00000000; 
    PORTD = 0b00111100; 

    int hasPrinted = 0; 

    initUART(9600); 

    while(1) { 

     // 1st bit LSB 
     if((PIND & 0b00000100) == 0) { 
      num = num | 0b00000001; 
     } else { 
      num = num & 0b11111110; 
     } 

     // 2nd bit 
     if((PIND & 0b00001000) == 0) { 
      num = num | 0b00000010; 
     } else { 
      num = num & 0b11111101; 
     } 

     // 3rd bit 
     if((PIND & 0b00010000) == 0) { 
      num = num | 0b00000100; 
     } else { 
      num = num & 0b11111011; 
     } 

     //4th bit MSB 
     if((PIND & 0b00100000) == 0) { 
      num = num | 0b00001000; 
     } else { 
      num = num & 0b11110111; 
     } 




     if(num != old_num) { 


      old_num = num; 
      printDec(num); 
      transmitByte('-'); 
      transmitByte('-'); 
      transmitByte('>'); 


     } 


     /* 

      Tested printDec without button it seems to work fine 

     if(hasPrinted == 0) { 

      printDec(15); 
      transmitByte(','); 

      printDec(16); 
      transmitByte(','); 

      printDec(21); 
      transmitByte(','); 

      printDec(num); 
      transmitByte(','); 

      num = num | 0b00001111; 
      printDec(num); 
      transmitByte(','); 

      num = num & 0b00000011; 
      printDec(num); 
      transmitByte(','); 

      hasPrinted = 1; 
     } 
     */ 
    } 

    return 0; 
} 


void initUART(unsigned int baud) { 

    /* 
     Initialize settings for uart functions. 
     Must be done once at the beginning of the program. 
    */ 

    //Normal mode UBRR formula 
    unsigned int ubrr = F_CPU/16/baud-1; 

    //shift MSB and store in UBRR0H 
    UBRR0H = (unsigned char) (ubrr >> 8); 

    //store LSB in UBRR0L 
    UBRR0L = (unsigned char) ubrr; 

    //Enable transmitter/receiver 
    UCSR0B = (1 << RXEN0) | (1 << TXEN0); 

    //8-Bit Characters, 0 Stop bits, No parity 
    UCSR0C = (1 << UCSZ00) | (1 << UCSZ01); 

} 

void transmitByte(unsigned char data) { 

    /* 
     Write byte to UART 
    */ 

    //Wait for empty transmit buffer 
    while(!(UCSR0A & (1 << UDRE0))); 

    //Start transmission by writing to UDR0 
    UDR0 = data; 

} 

unsigned char receiveByte(void){ 

    /* 
     Read byte from UART 
    */ 

    //Wait for incoming byte 
    while(!(UCSR0A & (1 << RXC0))); 

    //Return the byte 
    return UDR0; 
} 

int getNumOfDigits(int num) { 

    int s; 

    while(num != 0) { 

     num /= 10; 
     ++s; 
    } 

    return s; 
} 

void printDec(int num) { 

    unsigned char *str; 
    int size; 
    int i; 

    size = getNumOfDigits(num); 
    str = (char *) malloc(size+1); 
    sprintf(str, "%d", num); 

    for(i = 0; i < size; i++) { 

     transmitByte(str[i]); 

     _delay_ms(100); 
    } 

    free(str); 



} 

當我嘗試這個代碼與我的串行通信膩子,它打印正確的值了一段時間,然後所有的突然打印的所有這些奇怪的符號伴隨着我想要的價值。我不知道爲什麼這與按下按鈕,但沒有固定的按鈕很好地工作,我不明白爲什麼所有這些怪異的符號顯示在屏幕上。

enter image description here

+0

什麼奇怪的符號?您還可以打印字符和符號以及字符和符號的十六進制代碼,並使用該數據更新您的問題? –

+0

我更新了屏幕的輸出,它應該在那裏,我也可以發佈視頻,以更好地闡明它。 –

回答

1

的一個問題是這樣的:

int getNumOfDigits(int num) { 
    int s; 
    while (num != 0) { num /= 10; ++s; } 
    return s; 
} 

的局部變量s沒有初始化,所以你得到的垃圾。

也就是說,代碼相當臃腫,以傳輸大量的1或2位數字(從0到15),同樣考慮到上下文(嵌入式AVR)。

試想printDec()在此相反:

transmitByte(num/10 + '0'); 
transmitByte(num % 10 + '0'); 

它十進制用兩位數字(00 ... 15)將num。首先它需要十位數字,並通過添加'0'字符的ascii代碼,將其轉換爲想要的ascii代碼。那麼單位數字也是一樣。

如果你想從0到9的數字爲個位數,那麼這樣寫:

if (num >= 10) transmitByte(num/10 + '0'); 
transmitByte(num % 10 + '0'); 

這printDec()的版本更嵌入式 :-)

+0

非常感謝你乾淨的解決方案,它似乎工作 –