Проблема в коде, термостат

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 8
Зарегистрирован: Вт сен 23, 2014 05:49:26
Откуда: Белгород

Сообщение Lueksr »

Здравствуйте ребята, выручайте новичка, в авр не силен, пишу в cvavr. Собственно проблема тут где-то в меню, в таком состоянии контроллер не подает признаков жизни, стоит закоментировать содержание функции menu, как все начинает работать и в меню заходит. Что это может быть? Он ведь в функцию не входит если кнопку не трогать и работает в основном цикле, как это может повлиять на запуск мк?

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

#include <mega8.h>
#include <delay.h>
#include <string.h>
#include <stdio.h>
#include <math.h>



#define MENU_DELAY 3
#define EXIT_MENU_DELAY 1000

//Подключение LCD
#asm
   .equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h>

//Подключение датчика температуры
#asm
.equ __w1_port=0x12; PORTC
.equ __w1_bit=3
#endasm   
#include <1wire.h>
#include <ds18b20.h>
 eeprom   float gis;
 eeprom   float settemp;
  eeprom   float cal;
 eeprom   float adv; 
 eeprom int eepkey; 

void menu()
{
    int count=0;  
    float trash;
    int wh, mod;
    char buffer_lcd [16]; 
    int num=0;  
    float mgis=gis;
    float msettemp=settemp;
    float mcal=cal;
    float madv=adv;
    
    lcd_clear();
    lcd_gotoxy(6,0);  
    lcd_putsf("MENU");
      while(!PINB.1)
      {
            
      }
       
    
    
    while(1)
    {   
      
       
        switch(num)
        {
            case 0: 
            {   
                wh=msettemp;
                mod=modf(msettemp,&trash)*10;
                sprintf(buffer_lcd,"SET_TEMP %d.%dC      ",wh,mod);  
                break;
            }
            case 1: 
            {   
                wh=mgis;
                mod=modf(mgis,&trash)*100;
                sprintf(buffer_lcd,"HYSTERESIS %d.%dC      ",wh,mod); 
                break;        
            }
            
            case 2: 
            {   
                wh=mcal;
                mod=modf(mcal,&trash)*100;
                if(mod<0)
                {
                    mod=mod*-1;
                }
                sprintf(buffer_lcd,"CAL_SENS %d.%dC         ",wh,mod);
                break;
            }
            
            case 3: 
            {   
                wh=madv;
                mod=modf(madv,&trash)*100;
                sprintf(buffer_lcd,"ADV_OFF %d.%dC     ",wh,mod);
                break;
            }
        }  
        lcd_gotoxy(0,1);
        lcd_puts(buffer_lcd);
      
        
        
        if(!PINB.1)
        {
            delay_ms(30);
            if(!PINB.1)
            {
                count++;
                if(count>=100)
                {   
                    gis=mgis;
                    settemp=msettemp;
                    cal=mcal;
                    adv=madv;
                
                
                    break;
                }    
            }       
        } 
        
        if(PINB.1)
        {
             if(count>0)
             {
             count=0;
             if(num<3)
             {
                num++;
             } 
             else
             {
                num=0;
             }
            
            }     
            
        }
         
        
        if(!PINB.2)
        {
            delay_ms(50);
            if(!PINB.2)
            {  
                 switch(num)
                 {
                     case 0: 
                     {
                        msettemp=msettemp+0.1;   
                        if(msettemp>40)
                        {
                            msettemp=36;
                        } 
                        break;
                     }
                     case 1: 
                     {   
                        mgis=mgis+0.01;   
                        if(mgis>5)
                        {
                            mgis=0;
                        } 
                        break;        
                     }
            
                     case 2: 
                     {   
                        mcal=mcal+0.01;   
                        if(mcal>5)
                        {
                            mcal=-5;
                        } 
                        break;
                     }
            
                    case 3: 
                    {   
                         madv=madv+0.01;   
                        if(madv>5)
                        {
                            madv=0;
                        } 
                         break;
                    }    
            
            
            
                }
        
        }
        
      delay_ms(150);    
    } 
}
 }


void main(void)
{
    int  wh, mod, count=0,;
    float temp, trash;
    char buffer_lcd [16];
    
    if(eepkey!=233)
    {
        settemp=36;
        gis=0.1; 
        cal=0;
        adv=0;
        eepkey=233;
    }

      
    // Настройка ввода вывода
        PORTB=0b00001110;
        DDRB=0b00000001;

    // Инициализация LCD
    lcd_init(16);

   // Приветствие
    lcd_clear();
    lcd_gotoxy(4,0);  
    lcd_putsf("INCUBATOR");
    lcd_gotoxy(1,1);  
    lcd_putsf("CONTROLLER V1.0");
    delay_ms(2000);
   

    // Инициализация 1WRITE
    w1_init(); 
        
    

    // Инициализация DS18B20
    if(ds18b20_init( 0, 30, 60, DS18B20_12BIT_RES ) )
    {
      
       while(1){ 
            
            // Читаем температуру
            temp=ds18b20_temperature(0);
            temp=temp+cal;
           // Ошибка датчика
      
            
            //Выводим температуру на дисплей
            wh=temp; 
             mod=modf(temp,&trash)*10;
            if(mod<0)
            {
                mod=mod*-1;
            }
            sprintf(buffer_lcd,"TEMP:%d.%dC",wh,mod);
            lcd_clear();
            lcd_gotoxy(0,0);           
            lcd_puts(buffer_lcd);
            //Управление нагрузкой
            if(temp<=settemp-gis)
            {
                    PORTB.0=1;
            }   
            if(temp>=settemp)
            {
                    PORTB.0=0;
            } 
            //Вывод состояния нагревателя
            if(PORTB.0)
            {
                lcd_gotoxy(0,1);
                lcd_putsf("HEATER:ON ");
            }  
            else
            {
                lcd_gotoxy(0,1);
                lcd_putsf("HEATER:OFF ");
            } 
            //Вход в меню
            if(!PINB.1)
            {  
                delay_ms(30);
                if(count>=MENU_DELAY)
                    {
                         count=0; 
                         // Меню-------------------------------------------------------------------
                         menu();
                        //------------------------------------------------------------------------
                    }
                    count++;
                    
                
            
            }
            else
            {
                count=0;
            }
       }    
    
        
    }
    // Ошибка датчика
    else    
    {
        lcd_clear();
        lcd_gotoxy(2,0);  
        lcd_putsf("SENSOR ERROR");
    }
    }
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 508
Зарегистрирован: Пт фев 22, 2013 18:00:43
Откуда: Беларусь, г. Гомель

Сообщение rxstart1 »

у тебя void menu(), надо так void menu(void)
Реклама
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Lueksr писал(а):стоит закоментировать содержание функции menu,
В main() у тебя написано: если на ножке B.1 стоит "0" - войти в меню

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

void main(void)
{
...
            //Вход в меню
            if(!PINB.1)
            {  
                delay_ms(30);
                if(count>=MENU_DELAY)
                    {
                         count=0; 
                         // Меню-------------------------------------------------------------------
                         menu();
В самой функции меню сказано: пока на ножке B.0 установлен "0" - ждать

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

void menu()
{
....
    lcd_clear();
    lcd_gotoxy(6,0);  
    lcd_putsf("MENU");
      while(!PINB.1)
      {
            
      }
Родился
Сообщения: 8
Зарегистрирован: Вт сен 23, 2014 05:49:26
Откуда: Белгород

Сообщение Lueksr »

mas123 писал(а):В main() у тебя написано: если на ножке B.1 стоит "0" - войти в меню
Ну, жмем мы кнопку, тикает count, до тикал до MENU_DELAY, заходим в меню, пока кнопка продолжает оставаться нажатой крутимся в бесконечном цикле, кнопку отпустили работает меню. Бесконечный цикл там нужен для того чтобы сразу после входа в меню не листались пункты меню, тк эта функция на той же кнопке висит, и выход на ней же, только длинное нажатие.
P.S. Забыл упомянуть, про протосе все работает отлично
Реклама
Эиком - электронные компоненты и радиодетали
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Lueksr писал(а):P.S. Забыл упомянуть, про протосе все работает отлично
Это не показатель. Уже сколько раз выяснялось, что реальное "железо" и этот иммитатор - две большие разницы. :))
Уточняй по зависанию: выходит AVR'ка из этого цикла "while(!PINB.1)" или нет? По тексту на экране должно быть видно.
Реклама
Родился
Сообщения: 8
Зарегистрирован: Вт сен 23, 2014 05:49:26
Откуда: Белгород

Сообщение Lueksr »

mas123 писал(а):
Lueksr писал(а):P.S. Забыл упомянуть, про протосе все работает отлично
Это не показатель. Уже сколько раз выяснялось, что реальное "железо" и этот иммитатор - две большие разницы. :))
Уточняй по зависанию: выходит AVR'ка из этого цикла "while(!PINB.1)" или нет? По тексту на экране должно быть видно.
Убрал этот цикл, безтолку, у меня даже main не выполняется, вообще чип не стартует.
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 672
Зарегистрирован: Ср фев 29, 2012 01:58:32
Откуда: Харьков, Украина

Сообщение eess9 »

Lueksr писал(а):Убрал этот цикл, безтолку, у меня даже main не выполняется, вообще чип не стартует.
А откуда такая уверенность? Если это так (во что мне верится слабо), то проверяйте наличия питания на МК и лог "1" на выводе ресет; очень желательно через 10кОм на +питания. Еще вариант - фьюзы запрограмированы на внешний кварц, а оный отсутствует.
Родился
Сообщения: 8
Зарегистрирован: Вт сен 23, 2014 05:49:26
Откуда: Белгород

Сообщение Lueksr »

eess9 писал(а):А откуда такая уверенность? Если это так (во что мне верится слабо), то проверяйте наличия питания на МК и лог "1" на выводе ресет; очень желательно через 10кОм на +питания. Еще вариант - фьюзы запрограмированы на внешний кварц, а оный отсутствует.
Потому что прилепил светодиод и в начале main его зажег, ну верней не зажегся он(. В железе и фьюзах все четко фьюзы на внешний и он есть, резюк на ресет стоит, питание чистенькое. Говорю же убираю тело в MENU() ну не все а там где свитчи, все работает. Компилю с ним, заливаю и контроллер как мертвый. В отчаянье уже..
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

А проверь-ка настройки проекта.
Влезает ли вся программа, вместе с menu() в память?
Как сконфигурированы стеки - хватает ли их глубины на вызов п/п изнутри menu()?
И каков размер DATA-стека? Вот я вижу, что menu() под данные сразу требует ~44 байта...
Lueksr писал(а):Потому что прилепил светодиод и в начале main его зажег
Эм, надеюсь, зажег диодик после конфигурирования ножек порта на выход?
Родился
Сообщения: 8
Зарегистрирован: Вт сен 23, 2014 05:49:26
Откуда: Белгород

Сообщение Lueksr »

4502 программа, еще куча места, про стек тоже думал накрутил в 2 раза, сейчас 512 разницы нет. Погляди я с еепром не накосячил не где, первый раз его пользую. Естественно после конфигурирования диод зажег, ты уш меня совсем запинал))
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Lueksr писал(а):стек тоже думал накрутил в 2 раза, сейчас 512
512 - это что именно? У меня IAR знает про: HEAP, Data Stack (CSTACK), Return address stack (RSTACK).
Какие именно стеки ты "накрутил" и не вышел ли с этой "накруткой" за размер SRAM у контроллера? У 8-й Атмеги всего 1 Кб памяти.
Lueksr писал(а):Погляди я с еепром не накосячил не где,
Тут напутать сложно. Для отладки логично было бы выключить все те части кода, в которых не уверен.
Посмотри ассемблерный листинг, что сгенерил компилятор и пройдись по нему - может там увидишь место зависания.

А, ну вот - ты память грохаешь очень шикарно.

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

char buffer_lcd [16]; 
...
 sprintf(buffer_lcd,"SET_TEMP %d.%dC      ",wh,mod);  
 sprintf(buffer_lcd,"HYSTERESIS %d.%dC      ",wh,mod); 
 sprintf(buffer_lcd,"CAL_SENS %d.%dC         ",wh,mod);
 sprintf(buffer_lcd,"ADV_OFF %d.%dC     ",wh,mod);
Вопрос на засыпку - какого размера выделен буфер и сколько байт займут строчки после отработки sprintf().
Родился
Сообщения: 8
Зарегистрирован: Вт сен 23, 2014 05:49:26
Откуда: Белгород

Сообщение Lueksr »

mas123 писал(а):Вопрос на засыпку - какого размера выделен буфер и сколько байт займут строчки после отработки sprintf().
16 байт занимает 16 charo'в или я не прав? И строчка одна, там же эти sprintf в switch'e. Непонял о чем ты.
Вложения
1213.JPG
(42.83 КБ) 384 скачивания
Потрогал лапой паяльник
Сообщения: 312
Зарегистрирован: Вс июл 29, 2012 16:25:39

Сообщение mas123 »

Lueksr писал(а):Непонял о чем ты.
Понятно, ну что же: познакомься с любимой игрушкой всех программистов - переполнение буфера. 8)

Твой буфер занимает 16 байт: char buffer_lcd [16];
Предположим, что значения "wh" и "mod" равны 0.

Для наглядности я все пробелы заменил на "`"
Вот это: sprintf(buffer_lcd,"SET_TEMP`%d.%dC``````",wh,mod);
превратиться в "SET_TEMP`0.0C``````", что занимает 19 байт плюс завершающий "/0" - итого 20 байт. Sprintf испортит 4 байта после buffer_lcd.

Вот это: sprintf(buffer_lcd,"HYSTERESIS`%d.%dC``````",wh,mod);
превратиться в "HYSTERESIS`0.0C``````", что займет 22 байта (вместе с завершающим "/0") - повредили 6 байт.

Что именно расположено сразу после buffer_lcd[] - неизвестно. Вполне может быть, что там оказался стек, со всеми вытекающими радостями.
Если "wh" или "mod" имеют значение больше 9 - то потребуется "убить" ещё байтик.
Ответить

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