c - AVR C串行通信: Print number Fixed Buttons

标签 c putty avr

我正在使用微 Controller 和 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 值,根据位数查找其大小并将其转换为字符数组或字符串,然后一次一个字符地将其传输到串行通信屏幕。

 #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

最佳答案

有一个问题是这样的:

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() 更加嵌入式:-)

关于c - AVR C串行通信: Print number Fixed Buttons,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42723401/

相关文章:

linux - git commit 后,我​​在 putty 终端中看到 "Y"的长行

timer - 如何用定时器在AVR(ATmega8)中设置微秒延迟?

c - sqlite3_exec不返回任何输出

putty - TortoiseGit 在无密码登录设置中要求输入密码

java - 将私钥从 PuTTY 格式转换为 OpenSSH 格式后,是否需要向服务器添加新的公钥?

assembly - AVR 程序必须始终以相对跳转指令开头吗?

android - Android 上的蓝牙控制信号(DTR、DSR、RTS、CTS)

c - 将一个指向struct的指针和一个int传递给C中的函数以实现堆栈

c - 没有自引用结构的链表

c - 有没有办法将字符串数组拆分为 token 上的字符串子数组