2016-03-19 8 views
1

У меня есть лабораторное задание, в котором мне нужно использовать Atmega328P для работы с АЦП и с USART передавать цифровое значение на ЖК-дисплей MILFORD-4X20-BKP. ЖК-дисплей должен отображать значение в 2-байтовом формате (десятичное, 0-255) в первой строке и формат слова (4 байта, 0-1023) в третьей строке.Массив в Proteus с использованием вопроса о выпуске WinAVR C

Мне было удачно это сделать, но из-за того, что я был не уверен в размерах массива, я изначально имел их всех достаточно больших, чтобы не иметь проблемы. Когда я сменил его на то, что, по моему мнению, было необходимо, у меня была странная ошибка. Это странный символ, показанный ниже (или, я думаю, внизу). Символ в этом положении будет зависеть от значения потенциометра.

Итак, вот мое мышление. Я выделил 36 (+1 для pos 0) позиции для баффа, который был отправлен на ЖК-дисплей. Я выделил 3 к buff2 для значения слова (4 п позиций) и, наконец, 4 для buff1 для значения 2 байта (5 л позиции)

buff[36]; buff1[4]; buff2[3]; 

3n позиции для значения произведений слов, но когда я поставил 4n для значения 2 байта появляется ошибка. Посмотрите первое изображение.

Ошибка также появляется в виде части значения 0-255, появляющейся в конце строки 3, в зависимости от разных значений массива buff и buff1. На второй фотографии есть buff[37], buff1[2], buff2[3]

Последнее примечание: если я изменю значение на buff1[5], ошибка исчезнет ... но почему? Размер массива для 2 байтов должен быть меньше, чем для 4 байтов.

The weird bug

The LCD

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

/* 
* 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 
     } 
} 
+0

Является ли код, показанный в вашем сообщении ==, коду, который вы скомпилировали, побежал и заметил вашу ошибку? – ryyker

+0

Основной код, который я опубликовал, - это код, который я использовал, да. Это должен быть тот же код, который привел к проблемам, описанным выше, и показан на первом снимке. Я повторил часть того же кода в моем вопросе, который, возможно, привел к некоторой путанице. (buff [36], buff1 [4], buff2 [3]). –

ответ

1

Ваша упоминаемая проблема, вероятно, из-за ненулевого завершающим нулем при использовании вызова USART_putstring(buff);. C строк by definition требуется, чтобы последний символ был \0 (NULL). Пример:

Учитывая char string[5];

|h|e|r|e|\0| является законным
|h|e|r|e|s| |a| |b|u|g|является населенным буфером, но не строки

Есть места в вашем примере, где вы пишете неофициальный символ NULL для последний элемент буфера. Например buff создается как массив с 36 элементами:

volatile char buff[36];  // var sent out value 

в линейке:

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, он не является строкой, и использование его как одного приведет к Undefined Behavior.

Здесь также buf2 создается с 3-х элементов:

volatile char buff2[3];  // var for the actual pot value 

Но на этой линии, индекс используется (только 0-2 действительны)

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 
     } 

Эти ошибки будут компилировать, но при этом будет отображаться указатель вне привязки во время выполнения.

Эта переменная имеет неопределенный размер, и должен быть помечено ошибку:

volatile uint16_t buffer[]; // 20 place array 

предположение, что вы хотели, чтобы это было:

volatile uint16_t buffer[20]; // 20 place array 

Позже, вы используете его здесь:

ISR(USART_RX_vect)    //this is the right vector ref, not above 
{ 
    buffer[i]=UDR0; 

Потому что я не уверен, на каком стандарте C вы работаете (т.е. если его что-то другое, кроме A NSI C) Я не знаю, укажет ли ваша среда флаг undefined для массива int во время компиляции. Но так как остальные размеры вашего массива определены, это кажется подозрительным.

Кроме того, я вижу, что вы я определен как:

volatile int i=0; 

ли границы i хорошо известны? Возможно ли, чтобы я когда-либо выходил за пределы значения 19? (предполагая, что массив был в какой-то момент инициализирован)

+0

Извините, я считаю, что включил теги, но не упомянул об этом в вопросе. Это WinAVR, на Proteus. TBH Я не уверен в правилах, которые это следует. Я думал, что неопределенный массив примет размер, который ему нужен, но, возможно, это глупая ошибка. Сначала я изучал программирование от Arduino. Нулевой персонаж имеет большой смысл. Я не могу вспомнить, будет ли компилятор автоматически добавлять их в строку, если я оставлю ее пустой, но я исправлю это завтра утром. Странные ошибки имеют больше смысла, поскольку все 3 массива имеют этот недостаток, поэтому я буду обновлять как можно скорее. Благодарю. –

+0

@TomiFodor - Нет, неопределенный массив автоматически не корректирует размер. Однако этот метод инициализации будет работать: char array [] = {"string"}; Инициализированный таким образом, строковый массив будет автоматически завершен с помощью NULL, и, конечно, размер массива будет 7, 6 для видимых символов и 1 для NULL. Добавление пространства для (и применения) NULL в ваших строках, вероятно, исправит ваши заявленные проблемы. – ryyker

+0

Хорошо, поэтому я сделал это, и он избавился от ошибки, но вот это раздражает. buff2, значение, которое, кажется, нуждается в массиве из 5 элементов, отлично работает с 3. Это, похоже, не имеет никакого смысла. –