我正在使用微型控制器和I / O板。我的代码检查I / O板上某些固定按钮的状态(ON / OFF),并根据按钮的状态对int值执行按位操作,因此它代表0-15或0000到1111之间的数字。二进制文件。
我的主板上有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尝试此代码时,它会打印正确的值一段时间,然后突然打印所有这些奇怪的符号以及我想要的值。我不确定为什么按下按钮这个工作正常,但没有固定按钮,我不明白为什么所有这些奇怪的符号出现在屏幕上。
答案 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()更多是嵌入式: - )