【问题标题】:sprintf is outputting some strange datasprintf 正在输出一些奇怪的数据
【发布时间】:2012-09-29 06:21:00
【问题描述】:

我正在从事一个嵌入式项目,该项目涉及将结构读/写到 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 请注意,关于输出是用 %x 作为地址值的(所以 addr 是十六进制)

您可能已经注意到输出的第二个问题是,当 i > 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。我不太可能复制这个问题。

【问题讨论】:

  • 提供bf1的变量声明
  • 想法:与 EEPROM/I2C 相关的例程会损坏某些寄存器(可能是系统或 I/O 寄存器,而不仅仅是通用寄存器)或内存(可能是内存映射设备的内容)的内容。此外,您是否可能在某个地方出现竞争条件,在线程/ISR/main() 之间以不安全的方式共享全局变量?
  • 注释掉行,直到它停止奇怪的行为。然后找出是哪一行导致它。
  • 我评论了所有 I2C 的东西,得到了预期的结果(42 行:'addr: 0 byte: .\r\n' 'addr: 1 byte: .\r\n' ...这表明@AlexeyFrunze 可能会处理 I2C 损坏寄存器的问题。我将“addr”重命名为“address”,这根本没有任何区别。
  • @Clifford 不幸的是我没有调试器......我遇到了段错误。我把上面的描述说得更清楚了。

标签: c embedded printf microchip c18


【解决方案1】:

我会告诉你一个你的代码有问题,这一行:

(unsigned char)addr>>8

没有做你似乎需要的事情。

它将addr 中的值转换为unsigned char(假设为8 位char 和16 位int 或仅使用更宽int 的低16 位),将总是给你低八位。

如果你将它右移八位,你总是会得到零。

如果您的意图是获取地址的高八位,则需要使用:

(unsigned char)(addr>>8)

以便首先完成轮班。

【讨论】:

    猜你喜欢
    • 2019-03-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2014-08-10
    • 2017-04-29
    • 2018-08-07
    • 1970-01-01
    相关资源
    最近更新 更多