Estoy programando un ATMEGA328p en una placa de pruebas y estoy usando una tarjeta arduino para hacer la conversión de USB a serie. Parte del código que escribo involucra un bucle for que se usa para tomar la salida de 8 bits de la línea SPI MOSI (conectada a una tarjeta SD) y pegarla en un número binario de 64 bits para que pueda enviarla al monitor de serie. Lo he estado probando, y estoy recibiendo un bucle infinito y no sé qué está mal. El código se publica a continuación. No te preocupes por el código USART, funciona. El caso de prueba (la matriz púrpura [5]) se usa para averiguar por qué el bucle for es infinito.
Además, si conoce una forma más fácil de generar el código de 40 bits que genera una tarjeta SD después de usar los comandos SEND_IF_COND y SD_SEND_OP_COND, eso también sería útil.
#define USART_BAUDRATE 9600
#define F_CPU 16000000
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <avr/power.h>
void Init_USART(void);
void newLine(void);
void transmitByte(uint8_t my_byte);
void printNumber(uint8_t n);
void print64BitNumber(uint64_t bits);
void printBinaryByte(uint8_t byte);
void printString(const char myString[]);
int main(void){
Init_USART();
uint8_t purple[5];
purple[0] = 0b11110111;
purple[1] = 0b00010000;
purple[2] = 0b11111111;
purple[3] = 0b00110000;
purple[4] = 0b11111111;
uint8_t counter = 0;
uint64_t push_bit = 1;
uint64_t error_codes = 0;
for (int i=0; i<5; i++){
for (int loop_bit=7; ((loop_bit < 8)||(loop_bit < 254)); loop_bit--){
push_bit = 1;
printNumber(loop_bit);
print64BitNumber(error_codes);
newLine();
printNumber(counter);
newLine();
if(bit_is_set(purple[i],loop_bit)){
error_codes |= (push_bit << (loop_bit+(i*8)));
}
else{
error_codes &= ~(push_bit <<(loop_bit+(i*8)));
}
}
counter += 1;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
//USART Functions///////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void Init_USART(void)
{
clock_prescale_set(clock_div_1);
UCSR0B = (1<<RXEN0)|(1<<TXEN0); //Enables the USART transmitter and receiver
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00)|(1<<USBS0); //tells it to send 8bit characters (setting both USCZ01 and UCSZ00 to one)
//now it has 2 stop bits.
UBRR0H = (BAUD_PRESCALE >> 8); //loads the upper 8 bits into the high byte of the UBRR register
UBRR0L = BAUD_PRESCALE; //loads the lower 8 bits
}
void printBinaryByte(uint8_t byte){
uint8_t bit = 0;
//This code is really efficient. Instead of
//using large ints to loop, it uses small uint8_t's.
for (bit=7; bit<255; bit--){
if(bit_is_set(byte,bit)){
transmitByte('1');
}
else{
transmitByte('0');
}
}
}
//uint8_t is used for 8bit chars
void transmitByte(uint8_t my_byte){
do{}while(bit_is_clear(UCSR0A, UDRE0));
//UDR0 is the transmit register.
UDR0 = my_byte;
}
void newLine(void){
printString("\r\n");
}
void printString(const char myString[]){
uint8_t i = 0;
while(myString[i]){
while ((UCSR0A &(1<<UDRE0)) == 0){}//do nothing until transmission flag is set
UDR0 = myString[i]; // stick Chars in the register. They gets sent.
i++;
}
}
//Prints 64 bit number.
void print64BitNumber(uint64_t bits){
printBinaryByte(bits >> 56);
printBinaryByte(bits >> 48);
printBinaryByte(bits >> 40);
printBinaryByte(bits >> 32);
printBinaryByte(bits >> 24);
printBinaryByte(bits >> 16);
printBinaryByte(bits >> 8);
printBinaryByte(bits);
}
void printNumber(uint8_t n){//This function Prints a number to the serial monitor
//Algorithm to convert 8 bit binary to 3 digit decimal.
//N=16(n1)+1(n0)
//N=n1(1*10+6*1)+n0(1*1)
//N=10(n1)+1(6(n1)+1(n0))
//Also: N = 100(d2)+10(d1)+1(d0)
//Then make: a1 = n1 and a0 = (6(n1)+1(n0))
//Then get rid of the carries since n0 can be from 0-15, etc.
//c1 = a0/10 This is the number of 10's to carry over
//d0 = a0%10 This is the decimal that's outputed.
//c2 = (a1+c1)/10
//d1 = (a1+c1)%10
//d2 = c2
uint8_t d2, d1, q;
uint16_t d0;
//0xF is 15
//00010000 this is 16 (n)
//d0 = 00010000 & 00001111, d0 = 00000000
d0 = n & 0xF;
//If you AND n then the bits in the original number show in d0,d1 and d2
//d1 = (00010000 >> 4) same as 00000001, & 00001111, d1 = 00000001
//this sees if there's anything in the second 4 bits
d1 = (n>>4) & 0xF;
d2 = (n>>8);
//this sets d2 to 0.
d0 = 6*(d2+d1)+d0;
q = d0/10;
d0 = d0%10;
d1 = q + 5*d2 + d1;
if (d1!=0){
q = d1/10;
d1 = d1%10;
d2 = q+2*d2;
if (d2!=0){
transmitByte(d2 + '0');
//remember to add '0' because its an ASCII char
}
transmitByte(d1 + '0');
}
transmitByte(d0 + '0');
}