sprintf выводит некоторые странные данные

Я работаю над встроенным проектом, который включает чтение / запись структуры в EEPROM. Я использую sprintf, чтобы упростить отображение отладочной информации.

Есть две проблемы с этим кодом по некоторым причинам. Первый; sprintf печатает очень странный вывод. Когда я печатаю 'addr++', он будет следовать шаблону '0, 1, 2, 3, 4, 32, ...', который не имеет смысла.

void ee_read(char * buf, unsigned int addr, unsigned int len) {
    unsigned int i;

    sprintf(bf1, "Starting EEPROM read of %u bytes.\r\n", len); // Debug output
    debugr(bf1);

    IdleI2C1();
    StartI2C1();
    WriteI2C1(EE_ADDR | EE_W);
    IdleI2C1();
    WriteI2C1((unsigned char)addr>>8); // Address to start reading data from
    IdleI2C1();
    WriteI2C1((unsigned char)addr&0xFF);
    IdleI2C1();
    RestartI2C1();
    WriteI2C1(EE_ADDR | EE_R);
    IdleI2C1();
    for (i=0; i<len; i++) {
        buf[i] = ReadI2C1(); // Read a byte from EEPROM

        sprintf(bf1, "Addr: %u Byte: %c\r\n", addr, buf[i]); // Display the read byte and the address
        debugr(bf1);

        addr++; // Increment address

        IdleI2C1();
        if (i == len-1) { // This makes sure the last byte gets 'nAcked'
            NotAckI2C1();
        } else {
            AckI2C1();
        }
    }
    StopI2C1();
}

Вывод из вышесказанного находится здесь: https://gist.github.com/3803316 Обратите внимание, что вывод about был взят с%x в качестве значения адреса (поэтому addr является шестнадцатеричным)

Вторая проблема, которую вы, возможно, заметили с выводом, заключается в том, что он не останавливается, когда я> len. Это продолжается дальше, чем вывод, который я предоставил, и не останавливается, пока не перезапустится сторожевая собака микроконтроллера.

Изменить: вызов функции

Location loc;
ee_read(&loc, 0, sizeof(Location));

Объявления:

struct location_struct {
    char lat[12]; // ddmm.mmmmmm
    char latd[2]; // n/s
    char lon[13]; // dddmm.mmmmmm
    char lond[2]; // e/w
    char utc[11]; // hhmmss.sss
    char fix[2]; // a/v
};

typedef struct location_struct Location;

char bf1[BUFFER_SIZE];

Я не думаю, что это состояние гонки. Я отключаю прерывания, которые используют bf1. Даже в этом случае он повредит всю строку отладки, если это произойдет, и, конечно, это не будет повторяться.

Изменить Значение addr начинается с нуля, что можно увидеть здесь: https://gist.github.com/3803411

Редактировать Что это должно делать, копировать побитовую структуру расположения в EEPROM, а затем вызывать ее, когда это необходимо.

Закрытие Итак, я никогда не решал эту проблему. Проект отошел от EEPROM, и с тех пор я сменил ОС, компилятор и IDE. Вряд ли я повторю эту проблему.

1 ответ

Я скажу вам одну вещь неправильно с вашим кодом, эту строку:

(unsigned char)addr>>8

не делает то, что вам нужно.

Преобразует значение в addr в unsigned char который (при условии 8-битной char и либо 16-битный int или только используя младшие 16 битов шире int), всегда будет давать вам младшие восемь бит.

Если вы затем сдвинете вправо на восемь битов, вы всегда получите ноль.

Если вы хотите получить верхние восемь бит адреса, вам нужно использовать:

(unsigned char)(addr>>8)

так что сдвиг делается первым.

Другие вопросы по тегам