AVR C串行通信:打印编号固定按钮

时间:2017-03-10 16:38:26

标签: c putty avr

我正在使用微型控制器和I / O板。我的代码检查I / O板上某些固定按钮的状态(ON / OFF),并根据按钮的状态对int值执行按位操作,因此它代表0-15或0000到1111之间的数字。二进制文件。

我的I / O板 enter image description here

我的主板上有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数组或字符串,然后一次一个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);



}

当我使用串行通信putty尝试此代码时,它会打印正确的值一段时间,然后突然打印所有这些奇怪的符号以及我想要的值。我不确定为什么按下按钮这个工作正常,但没有固定按钮,我不明白为什么所有这些奇怪的符号出现在屏幕上。

enter image description here

1 个答案:

答案 0 :(得分:1)

一个问题是:

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

它以十进制传输num两位数字(00 ... 15)。首先它需要十位数,并且通过添加“0”字符的ascii代码,它将在所需的ascii代码中对其进行转换。然后是单位数字。

如果你想要一个从0到9的数字的单个数字,那么写下:

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

此版本的printDec()更多是嵌入式: - )