Перейти к содержанию
    

Помогите понять, в чем ошибка в куске кода

Есть такой код:

  /*****************************************************
  Chip type           : ATmega8535
  Program type        : Application
  Clock frequency     : 7,372800 MHz
  Memory model        : Small
  External SRAM size  : 0
  Data Stack size     : 128
  *****************************************************/
  
  #include <mega8535.h>
  
  // 1 Wire Bus functions
  #asm
  .equ __w1_port=0x18;PORTB
  .equ __w1_bit=0   
  #endasm        
  
  #include <1wire.h>
#include <delay.h>              // стандартная функция задержек
#include <stdio.h>              // Standard Input/Output functions
  #include <string.h>
  
  #define   LED PORTB.1           // выход на индикатор чтения
  #define  BEEP PORTB.2           // выход BEEP
  #define ALARM PORTB.3           // выход ALARM
  
  #define MAX_DEVICES 1 //определяем максимальное количество устройств на шине
  
  unsigned char rom_code[MAX_DEVICES][9]; //выделяет память (9 бит умноженное на кол-во устройств)
  
  unsigned char my_code_1[9]={0x01,0x1E,0x06,0xCA,0x0C,0x00,0x00,0x70,0x01};
  unsigned char my_code_2[9]={0x01,0xFD,0xE2,0xCC,0x0C,0x00,0x00,0xCC,0x01};
  
  //функция инициализации микроконтроллера  
  void initialization(void)       
  {
  // Port B initialization
  // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out 
  // State7=T State6=T State5=T State4=T State3=0 State2=0 State1=0 State0=0 
  PORTB=0x00;
  DDRB=0x0F;
  
  // Timer(s)/Counter(s) Interrupt(s) initialization
  TIMSK=0x04;
  
  // USART initialization
  // USART Baud rate: 115200
  // Communication Parameters: 8 Data, 1 Stop, No Parity
  // USART Receiver: Off
  // USART Transmitter: On
  // USART Mode: Asynchronous
  UBRRL=0x03;
  UCSRA=0x00;
  UCSRB=0x08;
  UCSRC=0x86;
  UBRRH=0x00;
  UBRRL=0x03;
  
  // Analog Comparator initialization
  // Analog Comparator: Off
  // Analog Comparator Input Capture by Timer/Counter 1: Off
  ACSR=0x80;
  SFIOR=0x00;
  
  // 1 Wire Bus initialization
  w1_init();
  
  #asm("wdr")
  
  // Watchdog Timer initialization
  // Watchdog Timer Prescaler: OSC/2048k
  #pragma optsize-
  WDTCR=0x1F;
  WDTCR=0x0F;
  
  #asm("wdr")
  
  #ifdef _OPTIMIZE_SIZE_
  #pragma optsize+
  #endif
  
  } 
  
  void test_key(void)     //проверка кода ключа
  {
  if(memcmp(rom_code,my_code_1,9)==0)
  printf("CodeOK\n\r");
  else
  printf("CodeError\n\r");
  }   
  
  //функция звукового сигнала BEEP
  void beep(void)                 
  {
  unsigned char a=0; 
  unsigned char b=0;
  
    for (b=0;b<2;b++) 
    {
       for(a=0;a<150;a++)
       {
       BEEP=1;
       delay_us(377);
       BEEP=0;
       delay_us(377);
       };
       
    delay_ms(100);
    }; 
  }
   
  
  //oбработка прерывания по переполнению таймера TIMER1
  interrupt [TIM1_OVF] void timer1_ovf_isr(void)   
     {
     unsigned char i,j,devices;
            
     TCCR1B=0x00;     //останавливаем таймер TIMER1
     LED=1;           //моргаем светодиодом
     delay_ms(10);
     LED=0;
     
    //ищем устройство командой 0xf0, в rom_codes ложится 9 байт (family-1,serial-6,CRC8-1,некоторые устройства возвращают 9 байт) 
     devices=w1_search(0xf0,rom_code);
     
     printf("%-u DEVICE DETECTED\r",devices);   //вывод через UART количества найденных устройств
        
        for (j=0;j<9;j++) //задаем, какую часть кода выводить
        {
        printf("0x%02X ",rom_code[i][j]);
        }    
     printf("\r");
                    
     test_key();
        
     TCCR1B=0x03;     //запускаем таймер TIMER1   
     }
   
  
  void main(void)
  {
  initialization();
  beep();
   
  #asm("sei")   // Разрешение прерываний
  
  TCCR1B=0x03;  // запуск счетчика TIMER1
  
     {
     begin:
     #asm("wdr")
     goto begin;
     }      
             
  }

 

Он подразумевает, что считывается DS1990 каждые ~0,5с, и выводит на СОМ следующее:

1 DEVICE DETECTED

0x01,0x1E,0x06,0xCA,0x0C,0x00,0x00,0x70,0x01 //номер ключа

CodeOK

 

Вот теперь вопрос, иногда вместо реального номера ключа пишет:

0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

хотя устройство на шине определяется и выводится Code OK.

 

иногда вместо нулей выводится неправильный код, сразу после включения (мусор в ОЗУ?))

 

Иногда работает как часы...

 

Вчера пару часов пытался выяснить закономерность, неполучилось.

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

P.S. Mega шилась раз 50 - 100, может здесь засада?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

RE: P.S. Mega шилась раз 50 - 100, может здесь засада?

У меня на макетке МК в день перешиваются раз по 10! и на всех (пока ))) ) ферификация проходит успешно, хотя МК уже более года, так что трабл явно не здесь.

Если датчики ВСЕГДА определяются успешно, значит, вероятно, причина в передаче данных от МК к РС. Попробуйте printf заменить чем то своим, проверенным и надежным, или, для начала, сбавьте скорость) а то у Вас аж 115200

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

for (j=0;j<9;j++) //задаем, какую часть кода выводить

{

printf("0x%02X ",rom_code[j]);

}

Утебя не определено значение переменная i.

Надо писать так.

printf("0x%02X ",rom_code[devices][j]);

Если конечно devices =1

Изменено пользователем SergSit

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для начала, отладте все по частям - устройство опознается каждый раз? ОК едем дальше. Убираем printf() и сбрасываем буфер обычной процедурой(как в даташите) в hex-терминал. Нормально? заменяем printf() на sprintf() и выбрасываем буфер одним ударом.

И так далее в этом ключе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

for (j=0;j<9;j++) //задаем, какую часть кода выводить

{

printf("0x%02X ",rom_code[j]);

}

Утебя не определено значение переменная i.

Надо писать так.

printf("0x%02X ",rom_code[devices][j]);

Если конечно devices =1

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вроде тоже ошибку дал(((. Если мы определяем массив rome_code[devices][9], при devices на 1, то обращение к первой строке выглядит так: rome_code[0][]. Поэтому надо писать так

printf("0x%02X ",rom_code[0][j]); при devices=1.

Если у тебя в один момент времени на шине может находиться только один ключ DS1990 двухмерный массив определять не надо. Можно определить так rome_code[8](девятый байт не надо т.к. его в ключах DS1990 нет). По такой схеме у меня все работает.

printf("0x%02X ",rom_code[j]);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кажется проблема была в питании, подзарядил аккумулятор и со старым кодом пошло (старый был взят и examples).

Хотя не понимаю, в чем виноват аккумулятор, на нем было 12,5 вольт на холостом ходу, а потребления никакого от макетки.

Но я изменил код в соответствии с советами многоуважаемых форумчан, за что всем ОГРОМНОЕ СПАСИБО!

/*****************************************************
  
  Chip type           : ATmega8535
  Program type        : Application
  Clock frequency     : 7,372800 MHz
  Memory model        : Small
  External SRAM size  : 0
  Data Stack size     : 128
  *****************************************************/
  
  #include <mega8535.h>
  
  // 1 Wire Bus functions
  #asm
  .equ __w1_port=0x18;PORTB
  .equ __w1_bit=0   
  #endasm        
  
  
  
  unsigned char rom_code[9]; //выделяет память (9 бит умноженное на кол-во устройств)
  
  unsigned char my_code_1[9]={0x01,0x1E,0x06,0xCA,0x0C,0x00,0x00,0x70,0x01};

  

  
  void test_key(void)
  {
  if(memcmp(rom_code,my_code_1,9)==0)    // сравниваем код, полученный от ключа с заданным
  printf("CodeOK  ");                                     // вывод сообщения
  else
  printf("CodeError  ");
  }   
  
  //функция звукового сигнала BEEP
  void beep(void)                 
  {
  unsigned char a=0; 
  unsigned char b=0;
  
    for (b=0;b<2;b++) 
    {
       for(a=0;a<150;a++)
       {
       BEEP=1;
       delay_us(377);
       BEEP=0;
       delay_us(377);
       };
       
    delay_ms(100);
    }; 
  }
   
  
  //oбработка прерывания по переполнению таймера TIMER1
  interrupt [TIM1_OVF] void timer1_ovf_isr(void)   
     {
     unsigned char j,devices;
            
     TCCR1B=0x00;     //останавливаем таймер TIMER1
     LED=1;           //моргаем светодиодом
     delay_ms(10);
     LED=0;
     
    //ищем устройство командой 0xf0, в rom_codes ложится 9 байт (family-1,serial-6,CRC8-1,некоторые устройства возвращают 9 байт) 
     devices=w1_search(0xf0,rom_code);
     
        if (devices==1)                 // если устройство присуствует, выводим подтверждение и номер
        {
        printf("Device Detected ");
           for (j=0;j<9;j++) //задаем, какую часть кода выводить
           {
           printf("0x%02X ",rom_code[j]);
           }    
     printf(" ");
        };
                    
     test_key();
        
     TCCR1B=0x03;     //запускаем таймер TIMER1   
     }
   
  
  void main(void)
  {
  initialization();
  beep();
   
  #asm("sei")   // Разрешение прерываний
  
  TCCR1B=0x03;  // запуск счетчика TIMER1
  
     {
     begin:
     #asm("wdr")
     goto begin;
     }      
             
  }

 

(девятый байт не надо т.к. его в ключах DS1990 нет)

 

Понятно, по даташиту нет, я согласен, но 9 у меня всегда равен 01h, не знаю почему... Пробовал для эксперимента смотреть дальше в ОЗУ = 00h.

Этот момент для меня не понятен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

для начала, сбавьте скорость) а то у Вас аж 115200

Зачем это? Кварц правильный, не надо ничего сбавлять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И я свои пять копеек.

 

С каких пор хорошим тоном является делание громоздких операций в прерывании?

Нельзя было установкой флага обойтись? А остальное делать в main.

 

А вызов printf() из прерывания - вообще песня.

А delay_ms(10) в прерывании?

 

Считаю, что в данной задаче никакой обоснованной необходимости в прерывании не было. Нужен тик таймера - запустите таймер и анализируйте поллом в main. Тем более что ничего другого не делается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

для начала, сбавьте скорость) а то у Вас аж 115200

Зачем это? Кварц правильный, не надо ничего сбавлять.

 

Кроме кварца важно еще как сделан физический интерфейс. 115200 не каждому подсилу.

 

С каких пор хорошим тоном является делание громоздких операций в прерывании?

Нельзя было установкой флага обойтись? А остальное делать в main.

 

А вызов printf() из прерывания - вообще песня.

А delay_ms(10) в прерывании?

 

Наверно 123 читал. И похоже не внимательно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вызов printf() из прерывания - вообще песня.

А delay_ms(10) в прерывании?

Да уж... Чайникам от чайника. В итоге чайник на чайнике сидит и чайником по морде бьет. :cranky:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Код я переписал, заработало все. Если интересно, могу выложить после обеда.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С каких пор хорошим тоном является делание громоздких операций в прерывании?

Нельзя было установкой флага обойтись? А остальное делать в main.

 

А вызов printf() из прерывания - вообще песня.

А delay_ms(10) в прерывании?

 

Считаю, что в данной задаче никакой обоснованной необходимости в прерывании не было. Нужен тик таймера - запустите таймер и анализируйте поллом в main. Тем более что ничего другого не делается.

 

Насчет красивости учту:)

Чем плохо printf() в прерывании, если времени гарантированно хватает (ну просто вагон)?

 

Кроме кварца важно еще как сделан физический интерфейс. 115200 не каждому подсилу.

 

преобразователь на FT232 с гальванической развязкой, с железом проблем нет, стабильно работает

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чем плохо printf() в прерывании, если времени гарантированно хватает (ну просто вагон)?

 

Надеюсь defunct вам сейчас объяснит!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...