Глюки программирования mega128

Обсуждаем контроллеры компании Atmel.
Ответить
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт фев 13, 2014 13:17:42
Откуда: Донецк

Сообщение Who_are_you? »

Программирую систему на ATmega128
и неважно на СИ или Паскале в WinAvr или МикроПаскале

Но возникает ситуация когда прошу, например,
подпрограмме вывести на LCD текст, а она вываливается (перезапускает main);
или не выполняются переходы при работе с прерываниями.

Я предполагал что это из-за стека, но нигде не видел в реальных программах даже обращений к стеку.
Мои эксперименты со стеком ничего не дали.
Как добиться логичности, чтобы переходы были такие, как написаны в программе, а не с глюками?
Не могут же разные компиляторы иметь похожие проблемы!
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

компиляторы не должны, а вот сам кристалл может.
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Who_are_you? писал(а):Не могут же разные компиляторы иметь похожие проблемы!
если программист один и тот же - еще как могут! :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт фев 13, 2014 13:17:42
Откуда: Донецк

Сообщение Who_are_you? »

Спасибо за рекламу и критику.
А по существу?
Кристаллы разные на разных платах

На одной плате пока не было программ обработки прерывания - глюков не было.

На другой - такое ощущение, что чем больше подпрограмм (в том числе и обрабатывающих прерывания) -
тем больше глюков
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

вы предлагаете сказать, чего не хватает в вашей каше, заочно ? я бы предпочел сначала попробовать...

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

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт фев 13, 2014 13:17:42
Откуда: Донецк

Сообщение Who_are_you? »

Программа большая.
Писал не я, но отлаживать приходится мне и в сжатые сроки.
Хочется все переделать, но пока некогда.
Никаких объявлений работы со стеком нет. WinAvr.
WinAvr совместно с AvrStudio работать не хочет. несколько раз переустанавливал

Один из примеров ниже:
Если в PRFMenu убрать выделенное цветом, то все работает корректно.

Иначе выход из PRFMenu в ProfileMenu нормально,
а дальше возврат по ESC не в основное меню, а реально начинается перезагруз заново main.

Выделенное цветом в другом месте и других программах работает.
Раз нет возврата по программе, то я и думаю, что может со стеком у меня некорректности.
Как поймать?

Код: Выделить всё


ISR (USART1_RX_vect)    // межплатный обмен
{
 unsigned char rxbyte;
  {	
	rxbyte = UDR1;

	switch (ComState)
	{
		case 10 : if (rxbyte == 0x02)   // wait for STX = 0x02
				 {
					ComState = 20;
					RxBuf[0]= rxbyte;
                    rxptr=0;
				 }
				  break;
		case 20 :
				 rxptr ++;
				 RxBuf[rxptr] = rxbyte;
				
				 if (rxptr == 2)
				 {
                                        len[1] = RxBuf[1];   // HI(rxlen)
					len[0] = RxBuf[2];   // LO(rxlen)
					rxlen = *(int*)len;  // rxlen = ((unsigned char)len[1]<<8)|len[0];					
				 }
				 if (rxptr == rxlen)
					ComState = 0x0C;     // кадр принят
				 break;
		default : ComState = 0x0C;		 
	}    	              
  }
}
//;************* end USART1_RX_vect ******************


void ProfileMenu (void)   // меню профиля
{
 int xr1 = 40, xr2 = 311, yr1 = 48, yr2 = 63;         //координаты начальной активной области меню

 char *buffer="0";
 char cchh;
 unsigned char counter = 1; //переменная, в  которой хранится номер текущей выделенной области меню

 for (;;)
 { 
  if (menu_counter == 2)
  {
	Error_RS422 = true;
	LCD_Clear (1,1);
	Text_Menu_String_pgm (16,0,0, pr_menu1);//Text_Menu_String (16,0,0, "МЕНЮ ПРОФИЛЯ");
	LCD_Window (1, 1, 319, 239);
	/*LCD_Rectangle_Color*/LCD_Bar (xr1, yr1 + 16 * (counter - 1), xr2, yr2 + 16 * (counter - 1), 1);
	Text_Menu_String_pgm (16,1,3, pr_menu2);//
	Text_Menu_String_pgm (16,1,4, pr_menu3);//
	Text_Menu_String_pgm (16,1,5, pr_menu4);//
	Text_Menu_String_pgm (16,6,8, pr_menu5);//
	Text_Menu_String_pgm (16,4,9, pr_menu6);//
	Text_Menu_String_pgm (8,2,12, pr_menu7); //
	Text_Menu_String_pgm (8,11,13, pr_menu8);//
	Text_Menu_String_pgm (16,2,14, esc_menu1);	
	menu_counter ++;
  }
	
		    
  // от платы процессорной   *******************************************
	if (ComState == 0x0C)     // кадр получен 
      {     
        cmd[1]= RxBuf[5];
        cmd[0]= RxBuf[6];
						
            // 'er' -  команда не прошла    /////////////////
        if ((cmd[1] =='e') & (cmd[0] =='r'))    
          {                                  
			Error_RS422 = false;
           }
		   
            // 'ok' -  команда прошла    /////////////////
        if ((cmd[1] =='o') & (cmd[0] =='k'))    
          {                                  
			flag_OK = true;        //
           }		   
			
        ComState = 10;    // SetupRx
        rxptr = 0;			
      }  // end ComState	
	  	    
	    
   if (Error_RS422 == 0)  //false
	 {
	 	Text_Menu_String (8,20,1, "Error_RS422: ");   //  
		cchh = (char)RxBuf[7];  buffer = &cchh;  LCD_WriteText (8,buffer); // команда
        cchh = (char)RxBuf[8];  buffer = &cchh;  LCD_WriteText (8,buffer); // команда     
		itoa (RxBuf[3],buffer,10); LCD_WriteText (8,buffer);  //от кого
	 }
	 
   if (flag_OK == 1)  //
	 {	 
	   Text_Menu_String (16,20,1, "OK: ");   // 
	   cchh = (char)RxBuf[7];  buffer = &cchh;  LCD_WriteText (8,buffer); // команда
       cchh = (char)RxBuf[8];  buffer = &cchh;  LCD_WriteText (8,buffer); // команда 
	  }
  
  key_input = key_survey(); 
  switch (key_input)
  {
   case '1'  : menu_counter ++; counter = 1; PRFMenu();  break;
   case '2'  : menu_counter ++; counter = 2; PVMenu();   break;  //PV
   case '3'  : menu_counter ++; counter = 3; SignMenu(); break;
   
   case 0x28 :  /*LCD_Rectangle_Color*/LCD_Bar (xr1, yr1 + 16 * (counter - 1), xr2, yr2 + 16 * (counter - 1), 0);
				if (counter != 3) counter ++; else counter = 1;
				/*LCD_Rectangle_Color*/LCD_Bar (xr1, yr1 + 16 * (counter - 1), xr2, yr2 + 16 * (counter - 1), 1);   // DOWN
				break;
   case 0x26 :  /*LCD_Rectangle_Color*/LCD_Bar (xr1, yr1 + 16 * (counter - 1), xr2, yr2 + 16 * (counter - 1), 0);
                if (counter != 1) counter --; else counter = 3;
                /*LCD_Rectangle_Color*/LCD_Bar (xr1, yr1 + 16 * (counter - 1), xr2, yr2 + 16 * (counter - 1), 1);  // UP
				break;
  
   default   :  break;
  } 
  if (key_input == 0x0d)
  {
	switch (counter)
	{
		case 1 : menu_counter ++; PRFMenu(); break;
		case 2 : menu_counter ++; PVMenu();  break;
		case 3 : menu_counter ++; SignMenu(); break;
	    default : break;
	}
   }	
  if (menu_counter == 4) { menu_counter -=2; continue; }
  if (key_input == 0x1b)  { menu_counter ++;  break; }           // ESC  
 }
 //MainMenu();
 //menu_counter -=4;
 menu_counter =0;
 key_input = 0;
}
// ********************************************************



void PRFMenu (void)  // меню выбора профиля
{
 
 char *buffer="0";
 int k = 18,j = 6; //стартовые координаты изменяемой области
 PRF_temp = Settings.PRF;
 LCD_Clear (1,1);
 unsigned char rank_counter = 0; //счетчик разряда во вводимом числе 0 - 1, 1 - 2, 2 - 3
 unsigned char rank[3] = {0,0,0};
 rank[2] = PRF_temp/100;
 rank[1] = (PRF_temp - rank[2]*100)/10;
 rank[0] = PRF_temp - rank[2]*100 - rank[1]*10;
 int i = 0;
 LCD_Window (1, 16, 319, 223);
 LCD_Rectangle (79,94,192,112,1);
 Text_Menu_String_pgm (16,4,1, prf_menu1);//Text_Menu_String (16,4,1, "ВЫБЕРИТЕ ПРОФИЛЬ");
 
 Text_Menu_String_pgm (16,10,6, prf_menu2);//Text_Menu_String (16,10,6, "PRF=");
 /*LCD_Rectangle_Color*/LCD_Bar ((k+2*(2-rank_counter))*8, j*16-1, (k+2+2*(2-rank_counter))*8-2,(j+1)*16-1,1);
 for (i = 2; i >=  0; i --)
   {
	 itoa (rank[i], buffer, 10);
	 Text_Menu_String (16, k + 2*(2-i), 6, buffer);
   }
 Text_Menu_String_pgm (16,2, 12, enter_menu2);//Text_Menu_String (16,2, 12, "ПОДТВЕРЖДЕНИЕ ENTER");
 Text_Menu_String_pgm (16,2, 13, esc_menu2);//Text_Menu_String (16,2, 13, "ОТМЕНА        ESC");
 for (;;)
 {
   key_input = key_survey(); 
   Secondary_Navigating_Function_2 (k,j,rank, &rank_counter);
   if (key_input == 0x0d) 
     { PRF_temp = rank[2] * 100 + rank[1]*10+ rank[0]; 
       Settings.PRF = PRF_temp;  
	   
[color=#FF00FF]			// *************************************************				
	   for (j = 1; j < Device_sum+1; j++)   // Bloc_izm [j] -  пока для 2-х БИ делаем
	    {
	     TxBuf[4] = Bloc_izm [j];   // DST кому из БИ
         TxBuf[5]= 'p';                              //  
         TxBuf[6]= 'r';
         TxBuf[7]= rank[1];  //8
         TxBuf[8]= rank[0];  //9
         txlen = 11;         // 9 +2 byte CRC
         Add_Len();   // в TxBuf[1], TxBuf[2] вставить txlen
         SetupTx ();  //	для Би1
		 _delay_ms (20);   // tst   установить нужное время[/color]
	      }
		  
	    break;
	  }

   if (key_input == 0x1b)  break;  
  } 
 //ProfileMenu ();
 key_input = 0;
} 
// ********************************************************

Извините - цветом не выделилось, только остались сообщения о выделении в конце PRFMenu.
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Код: Выделить всё

char *buffer="0";
это объявление указателя buffer на строку из 2 байтов, один из которых \0

Код: Выделить всё

itoa (RxBuf[3],buffer,10);
а вот это попытка вывести в память по этому указателю строку, длина которой может быть 5 байтов, не считая \0
и подобных мест просто много. так как buffer - локальная переменная, то память под неё выделяется в стеке, и, если туда пишется больше 2 байт (туда - это по указателю), стек портится...

а вы все кристалл да кристалл...

Добавлено after 3 minutes 21 second:
и это я еще 2 минуты код смотрел...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт фев 13, 2014 13:17:42
Откуда: Донецк

Сообщение Who_are_you? »

ARV
- Спасибо за акцент на указатели

нужно будет внимательно просмотреть их.

А

Код: Выделить всё

 char *buffer="0"; 
переписать на ?

Код: Выделить всё

 char *buffer= NULL;

и
char *buffer используется очень часто как локальная переменная, потому, наверно,
её лучше сделать глобальной

А работу стека определяет сам WinAvr !!!???
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Who_are_you? писал(а):переписать на ?
и чего вы этим добьетесь? сделаете ничуть не лучше!
в Си под указатели никогда не выделяется память автоматически - НИКОГДА! вы должны ВСЕГДА самостоятельно выделять ДОСТАТОЧНОЕ количество памяти, на которую ссылается указатель, прежде чем что-либо писать в эту память по этому указателю.

правильно делать примерно так (примерно - это значит, что есть и иные варианты, это не единственный):

Код: Выделить всё

void my_func(int data){ // какая-то функция
   char str[10]; // локальный массив из 10 байт
   itoa(data, str, 10); // формируем строку в массиве: int займет максимум 6 байт в массиве - размер массива гарантированно не будет превышен
   lcd_put_string(str); // выводим строку
} // так как str - локальный массив, в этот момент он самоудаляется
Who_are_you? писал(а):А работу стека определяет сам WinAvr !!!???
а кто её должен определять? по-моему, в Си не предусмотрено возможностей по управлению стеком.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт фев 13, 2014 13:17:42
Откуда: Донецк

Сообщение Who_are_you? »

Спасибо ARV.
Есть функция:
// void LCD_WriteText (char font, char * text)
нужно вывести символ из RxBuf[7]
Мне кажется что-то не так или мне кажется?

Код: Выделить всё

#define   BUFFER_SIZE  255 // 
unsigned char RxBuf [BUFFER_SIZE];
char cchh;
преобразовую тип, запихиваю в подпрограмму:
cchh = (char)RxBuf[7]; LCD_WriteText (8,&cchh);
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Who_are_you? писал(а):Мне кажется что-то не так или мне кажется?
не так.

функция LCD_WriteText хочет не просто указатель на char, а, судя по названию функции, на строку, т.е. просто так передавать ей указатель на одиночный char нельзя - выведет символ и потом будет продолжать выводить мусор, пока не встретит 0.

если вам надо выводить один символ (именно символ, а не байт), следует поступать так

Код: Выделить всё

char tmp[2];
tmp[0] = RxBuf[7];
tmp[1] = 0;
LCD_WriteText(8, tmp);
кстати, 8 для идентификатора шрифта - моветон, правильнее было бы что-то типа

Код: Выделить всё

#define SMALL_FONT   8
LCD_WriteText(SMALL_FONT, tmp)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

Who_are_you? писал(а):Писал не я, но отлаживать приходится мне и в сжатые сроки.
Передайте эту работу более компетентному человеку, потому что с вашим уровнем знаний вы не сможете исправить все ошибки.
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт фев 13, 2014 13:17:42
Откуда: Донецк

Сообщение Who_are_you? »

А разве это не конфликт?

Код: Выделить всё

#define   BUFFER_SIZE  255 // 
unsigned char RxBuf [BUFFER_SIZE];
char tmp[2];
tmp[0] = RxBuf[7];
unsigned char - [0, 255], а
char - [−127, +127]

Добавлено after 2 minutes 31 second:
[uquote="Мурик",url="/forum/viewtopic.php?p=3160249#p3160249"]
Who_are_you? писал(а):Писал не я, но отлаживать приходится мне и в сжатые сроки.
Передайте эту работу более компетентному человеку, потому что с вашим уровнем знаний вы не сможете исправить все ошибки.[/uquote]

Да. в СИ я не силен, НО вариантов нет.
Последний раз редактировалось Who_are_you? Пт авг 11, 2017 14:14:05, всего редактировалось 1 раз.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Who_are_you? писал(а):А разве это не конфликт?
Варнинг наверное будет.

Добавлено after 2 minutes:
Мурик писал(а):Передайте эту работу более компетентному человеку,
Компетентный человек, тоже когда-то был некомпетентным и стадию некомпетентности миновать не удастся.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 174
Зарегистрирован: Пн дек 10, 2007 12:19:18
Откуда: Санкт-Петербург

Сообщение -= Александр =- »

Иногда такая хрень происходила, когда какое-нибудь прерывание разрешено, а обработчика для него не написано. Проверяй регистры настройки прерываний, не разрешил ли чего лишнего. Или сделай обработчик и направь все незанятые векторы туда - хоть поймешь кто из них срабатывает.
Еще вариант - вачдог сбрасывает кристалл.
Вообще предельно аккуратно с указателями. Ими можно такого наворотить, что понять будет невозможно в принципе что там творится.
Еще источник глюков - питание. Схему бы глянуть - может там что-то сбивает контроллер аппаратно.
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Чт фев 13, 2014 13:17:42
Откуда: Донецк

Сообщение Who_are_you? »

Почему в 1) случае выводится не всегда указанный текст,
а во 2) случае все четко

// void Text_Menu_String (char font, unsigned char x, unsigned char y, char * text) //
1)

Код: Выделить всё

Text_Menu_String (8,20,1, "Error_RS422: ");   //  
2)

Код: Выделить всё

char ER [] = "Error_RS422: ")
Text_Menu_String (8,20,1, ER);   //  
Разрешены прерывания только по UART ну и sei();
Друг Кота
Аватара пользователя
Сообщения: 15605
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

В первом случае - явно указана строка символов ASCII
Во втором как-то кривовато - или адрес начала массива или первый элемент массива, содержащего строку данных типа char.
Вероятность иной интерпретации со стороны функции Text_Menu_String определяется ее содержимым.
8)
Ответить

Вернуться в «AVR»