首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用WinAVR C大小问题的Proteus数组

使用WinAVR C大小问题的Proteus数组
EN

Stack Overflow用户
提问于 2016-03-19 00:02:13
回答 1查看 407关注 0票数 1

我有一个实验室任务,需要我用一个Atmega328P做一个模数转换器,并使用USART,将数字值传输到米尔福德-4x20-BKP液晶显示器。LCD需要在第一行上以2字节格式(小数,0-255)显示值,在第三行上显示word格式(4字节,0-1023)。

我成功地做到了这一点,但是由于我不确定数组的大小,我一开始就把它们都大到没有问题。当我把它改成我认为必要的东西时,我有一个奇怪的窃听器。它是下面所示的奇怪符号(或者我猜在下面)。该位置的符号将取决于电位器的值。

这就是我的想法。我分配了36 (+1的pos 0)位置给buff,这是发送到LCD的。我为单词值(4n个位置)分配了3到buff2,最后为2个字节值(5n个位置)为buff1分配了4个

代码语言:javascript
复制
buff[36]; buff1[4]; buff2[3];

单词值的3n位置有效,但当我将4n作为2字节值时,就会出现错误。看第一张照片。

bug还以0-255值的一部分出现在第3行的末尾,这取决于buff和buff1的不同数组值。第二张照片有buff[37], buff1[2], buff2[3]

最后请注意,如果我将值更改为buff1[5],bug disappears..but为什么?2字节的数组大小应该小于4字节的数组大小。

奇怪的虫子

液晶显示器

我正在尽我最大的努力解释我的问题,但不知道我是否足够清楚。我知道我的数组正在交叉进入对方的内存地址,但我不知道如何和地点。

代码语言:javascript
复制
/*
 * Serial Lcd.c
 * 
 * Use's a 4x20 serial LCD display.
 *
 * Adapted by Phil J to suit Atmega328P: 15/2/2015 (corrected Usart_Rx Int Vector address ref. for 328)
 *
 * Editted by Tomi Fodor
 *
 */ 

#define F_CPU 16000000UL
#define BAUDRATE 9600 - change to External 16MHz crystal on MCU

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "stdlib.h"
#include "USART.h"

// Global Variables
// Note the use of the volatile keyword to ensure that the compiler knows that these variables can be changed at 
// any time, including by the ISR

volatile int i=0; 
volatile uint16_t buffer[]; // 20 place array
volatile char buff[36];     // var sent out value
volatile char buff1[4];     // var for the pot value / 4 ***** HAS TO BE AT LEAST 4 FOR SOME REASON (5 w/o bug), SHOULD BE FINE AT 2
volatile char buff2[3];     // var for the actual pot value
volatile uint16_t StrRxFlag=0;
volatile int Ana, Bell;     // pot value

int main(void)
{
   buff[4]=' ';buff[5]='P';buff[6]='o';buff[7]='t';buff[8]=' ';buff[9]='V';buff[10]='a';buff[11]='l';buff[12]='(';buff[13]='D';buff[14]=')'; // constants to be displayed
   _delay_ms(500);

   ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);    // Enables the ADC, sets the ADC to use the division factor 64 for the ADC clock 
   USART_interrupt_init();
   USART_putstring("Ready ");           // Send String to the LCD
// USART_putstring(buff3);                  
   USART_send('\r');                // Send carriage return
// USART_send('\n');                // Send linefeed
   _delay_ms(500);              // Allows for the LCD module to initialize

   while(1)
      {
     USART_send(254);       // LCD control mode
     USART_send(0);         // LCD HOME command
     USART_send(254);
     USART_send(1);         // LCD CLEAR SCREEN
     buff[0] = ' ';         // Required for offset of display
     buff[4] = ' ';         // Signifies terminator of pot
     ADCSRA |= (1<<ADSC);       // Starts A-D conversion
     while (ADCSRA & (1<<ADSC));    // Wait till A-D conversion is complete
     Ana = ADCW/4;          // Get A-D result
     Bell = ADCW;           // Get actual A-D result
     itoa(Ana,buff1,10);        // Creats the dec value of the Analogue value [stdlib.h]
     itoa(Bell,buff2,10);       // actual

     if (buff1[1] == '\0')      // If only 1 digit
        {
           buff[1] = ' ';       // Not hundreds
           buff[2] = ' ';       // Not tens
           buff[3] = buff1[0];  // Place in single digit
        }
     else if(buff1[2] == '\0')  // If only 2 digits
        {
           buff[1] = ' ';       // Not hundreds
           buff[2] = buff1[0];  // Shift
           buff[3] = buff1[1];  // Shift
        }
     else
        {
           buff[1] = buff1[0];  // Shift
           buff[2] = buff1[1];  // Shift
           buff[3] = buff1[2];  // Shift
        }

     for(i=0;i<25;i++)
        {
           buff[i+15] = ' ';
        }
buff[25]=' ';buff[26]='P';buff[27]='o';buff[28]='t';buff[29]=' ';buff[31]='V';buff[32]='a';buff[33]='l';buff[34]='(';buff[35]='D';buff[36]=')'; // constants to be displayed

     if (buff2[1] == '\0')      // If only 1 digit
        {
           buff[21] = ' ';      // Not thousands
           buff[22] = ' ';      // Not hundreds
           buff[23] = ' ';      // Not tens
           buff[24] = buff2[0]; // Place in single digit
        }
     else if(buff2[2] == '\0')  // If only 2 digits
        {
           buff[21] = ' ';      // Not thousands
           buff[22] = ' ';      // Not hundreds
           buff[23] = buff2[0]; // Shift
           buff[24] = buff2[1]; // Shift
        }
     else if(buff2[3] == '\0')  // If only 3 digits
        {
           buff[21] = ' ';      // Not thousands
           buff[22] = buff2[0]; // Shift
           buff[23] = buff2[1]; // Shift
           buff[24] = buff2[2]; // Shift
        }
     else
        {
           buff[21] = buff2[0]; // Shift
           buff[22] = buff2[1]; // Shift
           buff[23] = buff2[2]; // Shift
           buff[24] = buff2[3]; // Shift
        }

          USART_putstring(buff);
          USART_send('\r'); 
         _delay_ms(500);
    }
}

//ISR(USART0_RX_vect) - not for 328
ISR(USART_RX_vect)              //this is the right vector ref, not above
{   
   buffer[i]=UDR0;              //Read USART data register
   if(buffer[i++]=='\r')            //check for carriage return terminator and increment buffer index
      { 
     // if terminator detected
     StrRxFlag=1;           //Set String received flag 
     buffer[i-1]=0x00;      //Set string terminator to 0x00
     i=0;               //Reset buffer index
      }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-19 00:22:29

您所引用的问题很可能是由于使用调用USART_putstring(buff);时非空终止字符串造成的。C字符串https://stackoverflow.com/a/12203414/645128要求最后一个字符为\0 ( NULL )。示例:

给定char string[5];

|h|e|r|e|\0|是合法的

|h|e|r|e|s| |a| |b|u|g|是一个填充的缓冲区,但不是字符串。

在您的示例中,有些地方将非空字符写入缓冲区的最后一个元素。例如,buff是作为一个包含36个元素的数组创建的:

代码语言:javascript
复制
volatile char buff[36];     // var sent out value

在队伍中:

代码语言:javascript
复制
buff[25]=' ';buff[26]='P';buff[27]='o';buff[28]='t';buff[29]=' ';buff[31]='V';buff[32]='a';buff[33]='l';buff[34]='(';buff[35]='D';buff[36]=')'; // constants to be displayed

索引35 (最后一个合法索引)使用D字符填充。索引36 (不合法)使用)填充,至少会导致运行时错误。那么,根据定义,因为它不是NULL终止,所以它不是一个字符串,使用它作为一个字符串将导致https://en.wikipedia.org/wiki/Undefined_behavior

这里还使用3个元素创建了buf2:

代码语言:javascript
复制
volatile char buff2[3];     // var for the actual pot value 

但是在这一行中,使用了索引3:(只有0-2是有效的)

代码语言:javascript
复制
else
        {
           buff[21] = buff2[0]; // Shift
           buff[22] = buff2[1]; // Shift
           buff[23] = buff2[2]; // Shift
           buff[24] = buff2[3]; // Shift <<< only buff2[0] - buff2[2] are legal
        }

这些错误将进行编译,但在运行时会导致指针不受约束.

这个变量有一个未定义的大小,应该已经标记了一个错误:

代码语言:javascript
复制
volatile uint16_t buffer[];  // 20 place array

你的假设是:

代码语言:javascript
复制
volatile uint16_t buffer[20];  // 20 place array

稍后,你在这里使用它:

代码语言:javascript
复制
ISR(USART_RX_vect)              //this is the right vector ref, not above
{   
   buffer[i]=UDR0;   

因为我不知道您在使用什么C标准(也就是说,如果它不是ANSI C),所以我不知道您的环境是否会在编译时为int数组标记一个未定义的大小。但是,由于定义了其他数组大小,这个数组看起来很可疑。

另外,我看到你把我的定义定义为:

代码语言:javascript
复制
volatile int i=0;

i的界限众所周知吗?我有可能超越19的价值吗?(假设数组在某个时间点初始化)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36096202

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档