AVR gcc,奇怪的数组行为

时间:2016-06-11 12:44:49

标签: c arrays gcc avr

这是我第一次看到这样的事情。我开始怀疑它是硬件故障。 每当我尝试发送数组的内容" test"并且该数组大于4个元素,或者我初始化它包含0xff的声明中的所有元素,而不是我尝试初始化的值。

这很好用。当我从数组中读取值时(将它们发送到lcd和uart),两个读数都与测试值一致:

uint8_t i=0;
uint8_t test[4] = {1,2,3,4};
     while(i<5){
     GLCD_WriteData(test[i]);
     USART_Transmit(test[i]);
     i++;
 }

这并不是,它返回0xff而不是test [i]值:

uint8_t i=0;
uint8_t test[5] = {1,2,3,4,5};
     while(i<5){
     GLCD_WriteData(test[i]);
     USART_Transmit(test[i]);
     i++;
 }

但这有效!它返回正确的值

uint8_t i=0;
uint8_t test[6] = {1,2,3,4,5};
     while(i<5){
     GLCD_WriteData(test[i]);
     USART_Transmit(test[i]);
     i++;
 }

这也有效:

uint8_t i=0;
uint8_t test[5];
test[0]=1;
test[1]=2;
test[2]=3;
test[3]=4;
test[4]=5;
     while(i<5){
     GLCD_WriteData(test[i]);
     USART_Transmit(test[i]);
     i++;
     }

在linux上编译时工作正常

我换了一个不同的mcu,它按照应有的方式工作。必须是硬件问题

4 个答案:

答案 0 :(得分:1)

在第一个例子中,你将超出数组测试的范围[4]。当数组只有4个项目时,你正在运行5次。

答案 1 :(得分:0)

我认为您的问题是您的USART过载。我假设GLCD_WriteData()非常快,USART_Transmit()缓冲字符进行传输,然后快速返回。我不知道你的硬件,所以我无法告诉 - 但USART的四字符缓冲区听起来很合理。

你的五个字符的例子不起作用,因为你尝试传输的实际字符丢失了 - 所以它改为输入0xFF。您需要检查USART缓冲区的状态并等待它显示该空间可用(注意 NOT 为空 - 这样效率低!)。

在8250和16450 UART芯片中有两个状态位:

  • TSRE T ransmit S hift R egister E mpty; < / LI>
  • THRE表示 T ransmit H olding R egister E mpty。< / LI>
即使THRE不是忙碌,也可以设置

TSRE。我测试TSRE并且不发送下一个字符直到那个房间 - 或者设置缓冲区和中断处理程序。

答案 2 :(得分:0)

如果它不是I / O硬件,那么我唯一能想到的就是编译器生成错误的代码。 select * from table where descript like '%ali%' order by locate('ali', descript) asc 的确切声明是什么?是否期望USART_Transmit()?或者别的,比如uint8_t(出于某种原因)?

如果它是其他内容,例如int,请尝试以下代码:

int

如果它始终有效,那么您就遇到了编译问题,而不是硬件问题。

编辑:提供while(i<5){ int c = test[i]; // Whatever USART_Transmit wants GLCD_WriteData(test[i]); USART_Transmit(c); i++; } // while 的代码:

  

USART_Transmit()
     void USART_Transmit( uint8_t data ) {
     //Wait for empty transmit buffer
     while( !( UCSR0A & (1<<UDRE0)) );
     //Put data into buffer, sends the data
     UDR0 = data;

你得到的东西比JTAG更好 - 你有一台液晶显示器!虽然我不知道它有多少个字符,或者传输一个字符需要多长时间......

您可以尝试以下方式:

}

假设UDRE0为3,那么如果它正在工作,那么该代码将产生类似char Hex(uint8_t nibble) { return nibble<10 ? '0'+nibble : 'A'+nibble-10; } // Hex ... void Send(uint8_t c) { uint8_t s; UDR0 = c; // Send character NOW: don't wait! do { s = UCSR0A; // Get current USART state //s = UCSR0A & (1<<UDRE0); // Or this: isolate ready bit... GLCD_WriteData('x'); GLCD_WriteData(Hex(s >> 4)); // Write state-hi hex GLCD_WriteData(Hex(s & 0xF)); // Write state-lo hex } while (!(s & (1<<UDRE0))); // Until is actually ready } // Send(c) ... Send('A'); Send('B'); Send('C'); 的序列。如果它产生x00x00x00x00x00x08x00x00x00x00x08x00x00x00x08,那么你的UCSR0A位和它的硬件都会被卡住。

答案 3 :(得分:0)

老问题,但提供我的反馈,因为这是我在搜索相同问题的解决方案时收到的第一个地方,甚至得到与原始问题中的代码示例完全相同的结果。

据我所知,这是一个糟糕的 Makefile,导致 avr-objcopy 遗漏了一些部分。

例如在我的例子中,用于构建我的示例十六进制的原始参数导致了这个问题:

${OBJCOPY} -j .text -O ihex led.elf led.hex

哪个效果更好:

${OBJCOPY} -O ihex -R .eeprom led.elf led.hex