微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PIC 嵌入式 C printf 损坏的输出 - 很奇怪

如何解决PIC 嵌入式 C printf 损坏的输出 - 很奇怪

我有一个 69 元素数组 MBRespon[i] 的十六进制数据,我从 PIC18F46K40 上的两个 USART 发送出去。第一个 USART 循环遍历数据并正常传输所有内容,完成后,代码通过第二个循环,在第二个 UART 中使用以下命令打印格式化数据:

printf("   Byte %02i : 0x%02x \r\n",i,MBRespon[i]);

起初看起来数据打印得很好,但是在第 57 个字节附近仔细检查后,它发送了错误内容。起初我认为这可能是 EUSART2_TX_BUFFER_SIZE 问题,确实改变缓冲区大小确实有影响;当与 32 不同时,more 会损坏。

#define EUSART2_TX_BUFFER_SIZE 32   // 32 Works (Sort of)
#define EUSART2_RX_BUFFER_SIZE 32   // 32 Works (Sort of)

如果我将数组中的元素数量减少到 58 个或更少,那就没问题了,再多就会损坏。

我的代码

  void PrintModRespon(){

    int i=0;
    
    printf("Modbus Response Count %i:\r\n",MBResCnt);
    while(!EUSART2_is_tx_ready());      // Hold the program until TX is ready
    
    for(i=0; i< MBResCnt ; i++ ){
        while(!EUSART2_is_tx_ready()); // Hold the program until TX is ready

        printf("   Byte %02i : 0x%02x \r\n",MBRespon[i]); 
   
        while(!EUSART2_is_tx_done());   // Hold until done.

    }
    
    while(!EUSART2_is_tx_ready());      // Hold the program until TX is ready
    printf("\r\n\n");
    while(!EUSART2_is_tx_done());
     
}

添加while(!EUSART2_is_tx_ready());while(!EUSART2_is_tx_done());,因为我认为这可能是 UART 没有准备好/忙碌,但它们没有任何区别。

UART1 输出(好的):

 06 03 40 00 01 00 02 00 03 ....etc.... 00 1a 00 1b 00 1c 00 1d 00 1e 00 1f 00 20 5c 30 

UART2 输出(坏的):

Modbus Response Count 69:
   Byte 00 : 0x06
   Byte 01 : 0x03
   Byte 02 : 0x40
   Byte 03 : 0x00
   Byte 04 : 0x01
   Byte 05 : 0x00
   Byte 06 : 0x02
   Byte 07 : 0x00
   Byte 08 : 0x03

...等等...

   Byte 53 : 0x00
   Byte 54 : 0x1a
   Byte 55 : 0x00
   Byte 56 : 0x1b
   Byte 57 : 0x14    // <-- This is NOT in the array!
   Byte 58 : 0x1c
   Byte 59 : 0x00
   Byte 60 : 0x1d
   Byte 61 : 0x00
   Byte 62 : 0x1e
   Byte 63 : 0x00
   Byte 64 : 0x1f
   Byte 65 : 0x00
   Byte 66 : 0x20
   Byte 67 : 0x5c
   Byte 68 : 0x30

奇怪的是,作为另一个测试,我将 printf 函数更改为:

printf("   Byte %02i : 0x%02x \r\n",0x00 +i);

I.E 不使用数据数组,它输出 69x 增量值很好!这表明这不是 UART 缓冲区/时序问题?

Modbus Response Count 69:
   Byte 00 : 0x00
   Byte 01 : 0x01
   Byte 02 : 0x02
 
...etc.

   Byte 51 : 0x33
   Byte 52 : 0x34
   Byte 53 : 0x35
   Byte 54 : 0x36
   Byte 55 : 0x37
   Byte 56 : 0x38
   Byte 57 : 0x39
   Byte 58 : 0x3a
   Byte 59 : 0x3b
   Byte 60 : 0x3c
   Byte 61 : 0x3d
   Byte 62 : 0x3e
   Byte 63 : 0x3f
   Byte 64 : 0x40
   Byte 65 : 0x41
   Byte 66 : 0x42
   Byte 67 : 0x43
   Byte 68 : 0x44

非常感谢任何建议。我已经坚持了好几天了!

解决方法

这很可能是填充问题,因为结构的第一个元素有奇数个字节。

在定义结构时,如果元素不符合处理器的默认对齐方式,编译器将在元素之间创建一字节的填充。 16 位处理器将希望大多数事物在字边界(即甚至地址)上对齐,包括字节数组(例如字符数组)。只占一个字节的元素除外。

在 16 位 Microchip MPU 上,如果您尝试访问奇地址上的字或双字数据,则会导致内存故障。编译器正在努力防止这种情况发生。

如果您的结构仅包含字节大小的元素(char、uint8_t 等)或相同的数组,您可以通过在结构声明中添加限定符 __attribute__((packed)) 来强制字节对齐。这可能很危险,因为您最终可能会得到具有奇数地址的元素。只要奇数寻址元素仅作为字节访问(例如字符数组),这是可以的,但请谨慎操作。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。