AVR C 串行通信:打印数字固定按钮

AVR C Serial Communication: Print number Fixed Buttons

我正在使用微控制器和 I/O 开发板。我的代码检查 I/O 板上某些固定按钮的状态 (ON/OFF),并根据按钮的状态对 int 值执行按位运算,因此它表示 0-15 或二进制为 0000 到 1111。

我的 I/O 看板

我的板上有 4 个固定按钮 DS1 - 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 值,根据位数找到它的大小并将其转换为 char 数组或字符串,然后将它传输到串行通信屏幕上的一个字符一个时间。

 #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);



}

当我用我的串行通信腻子尝试这段代码时,它打印了一段时间的正确值,然后突然打印了所有这些奇怪的符号以及我想要的值。我不确定为什么这在按下按钮时效果很好,但在固定按钮上却不行,我不明白为什么所有这些奇怪的符号都会出现在屏幕上。

一个问题是:

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

本地 var 未初始化,所以你得到垃圾。

也就是说,代码非常臃肿,无法传输 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() 更嵌入 :-)