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

Сброс бита в регистре ADMUX - глюк IAR'а - ?

Есть подпрограмма, в которой нужно сбросить бит в р-ре.

Что не нравится IAR при сбросе бита в ADMUX? ("err_clr_bit.png")

Здесь же добавил сброс 0-го бита в другом р-ре. Там все нормально.

 

И попутно еще вопрос по локальной переменной ("local.png")

 В команде

asm ("LDS R14, i")

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

При глобальной переменной все нормально.

Ошибка также возникает если вместо i использовать элемент union, который описан в хидерном файле:

union
{
  uint Word;

  struct
  {
    char c1; char c2;
  } Symv;
} Int_Char;

 

Err_clr_bit.png

local.png

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


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

Пища для размышлений.

//  ADMUX &= ~(1<<MUX0);
        CBI     0x07, 0x00
//  ADMUX &= -(1<<MUX0);
        IN      R16, 0x07
        OUT     0x07, R16

 

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


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

Попробовал сбросить бит MUX1. Все нормально. ("Err_clr_bit_n.png")

Но есть еще небольшая проблема связаная с отладкой программы. ("proteus.png")

В Proteus не могу пройти по шагам после  адреса 0xFF. Сам код выполняется , но остановиться на нем я не могу.

Не зная в ком проблема: IAR или Proteus. И это все в той же п/п.

Вот привожу ее полностью

void Result_ADC (void)
{
  uchar i;
  static uint  sum_adc;
  static uchar ch_adc;
  uchar low_adc, high_adc;
  uint  adc_value;

    low_adc  = ADCL;
    high_adc = ADCH;
    adc_value = high_adc * 256 + low_adc;
    sum_adc += adc_value;
 
    if (--count_cycle_adc == 0) 
    {
      count_cycle_adc = N_CYCLE_ADC;

      Int_Char.Word = sum_adc;
//      asm ("LDS R14, Int_Char.Symv.c1");
      i = Int_Char.Symv.c1;
//      asm ("LDS R14, i");
      i = Int_Char.Symv.c2;
//      asm ("LDS R15, i");

        for (i = 0; i < 3; i++)
        {
          asm ("LSR R14");
          asm ("ROR R15");
        }

        switch (ch_adc)
        {
          case 0:
            asm ("STS   adc_ch_0_low,  R15");
            asm ("STS   adc_ch_0_high, R14");
            ch_adc = 1;
            ADMUX |= (1 << MUX0);
          break;

          case 1:
            asm ("STS   adc_ch_1_low,  R15");
            asm ("STS   adc_ch_1_high, R14");
            ch_adc = 0;
//            asm ("CBI 0x07, 0x0");
            ADMUX &= -(1 << MUX0);
            ADMUX &= -(1 << MUX1);

          break;
        }
      sum_adc = 0;
    }

    ADCSRA |= (1 << ADIF);
    ADCSRA |= (1 << ADSC);

}

В хидерном файле есть такая инфрмация:


void Result_ADC (void);

#define N_CYCLE_ADC       8

union
{
  uint Word;

  struct
  {
    char c1; char c2;
  } Symv;
} Int_Char;

uchar count_cycle_adc;
uchar adc_ch_0_low, adc_ch_0_high, adc_ch_1_low, adc_ch_1_high;

 

 

Err_clr_bit_n.png

proteus.png

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


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

Между -(1<<MUX0) и ~(1<<MUX0) разницу вообще не наблюдаете? Первое это 0xFF, а второе 0xFE, между нами девочками.

 

И объясните уже, нахрена тут asm? Вы только мешаете компилятру работать своими вставками. Поверьте, он умнее вас.

Точно так же как какие-то левые union...

 

IAR достаточно умный, чтобы вот так уметь.

//  uint16_t adc_value = ADC;
        IN      R16, 0x04  //ADCL
        IN      R17, 0x05  //ADCH
//  adc_value += ADC;  
        IN      R18, 0x04
        IN      R19, 0x05
        ADD     R18, R16
        ADC     R17, R19
//  DDRC = adc_value;
        OUT     0x14, R18
//  DDRB = adc_value>>8;
        OUT     0x17, R17

Просто не мешайте ему.

 

Совет на будущее. Не надо придумывать непонятные типы данных. В стандарте языка есть stdint.h - пользуйтесь. Стандартный uint16_t на любой платформе останется 16-битным беззнаковым целым и любой компилятор/программист однозначно поймёт что это, в отличии от uint. 

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


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

6 hours ago, VladislavS said:

Между -(1<<MUX0) и ~(1<<MUX0) разницу вообще не наблюдаете? Первое это 0xFF, а второе 0xFE, между нами девочками.

Я прекрасно понимаю разницу между выражениями.  Но подвело зрение. Пора, наверное, уже брать очки, а все не хочется. Большое спасибо за выявление моей ошибки. Я бы так и не увидел ее, если бы Вы явно не указали на нее. Но в уме не укладывается, каким образом вместо тильды попал минус - они на разных концах клавиатуры.

6 hours ago, VladislavS said:

И объясните уже, нахрена тут asm?

...

IAR достаточно умный, чтобы вот так уметь.

Согласен. Сам так делал. Но тут как-то сразу не сообразил. Просто я использую union в другом месте, где нужен доступ у переменной либо как int либо как char. Вот автоматом и сюда вставил.

6 hours ago, VladislavS said:

 В стандарте языка есть stdint.h - пользуйтесь. Стандартный uint16_t ...

Я часто встречал такое описание, но оно как-то мне было не по душе. К тому же я пишу на C и всегда пользовался библиотекой CLIB. А этот файл есть в DLIB. Ну что ж, попробую использовать DLIB.

 

А как на счет отладки в Proteus'е? Есть ли какие идеи? Сама п/программа работает и у меня нет необходимости влезать сейчас туда. Но хотелось бы выяснить на будущее. Где искать - в IAR'е или в Proteus'е?

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

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


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

7 минут назад, IF_P сказал:
6 часов назад, VladislavS сказал:

 В стандарте языка есть stdint.h - пользуйтесь. Стандартный uint16_t ...

Я часто встречал такое описание, но оно как-то мне было не по душе. К тому же я пишу на C и всегда пользовался библиотекой CLIB. А этот файл есть в DLIB. Ну что ж, попробую использовать DLIB.

Вы можете и дальше использовать CLIB, если не нужны дополнительные функции. Просто в ручную подключайте stdint.h - это всего лишь файл описаний.
Точно так же, как и для использования bool в ANSI C просто подключаете stdbool.h
#include    <stdbool.h>
#include    <limits.h>
#include    <float.h>
#include    <stdlib.h>
#include    <string.h>
#include    <math.h>
и т.д.

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


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

Я скопировал "stdint.h" в CLIB и подключил его в проект. Без подключения DLIB не получается. С подключением работает.err_iar.thumb.png.c9c6a5d557e2b40f486fb304b7c7ec08.png

Вот что я еще заметил. Невозможность пройти по шагам в отладке возникает при включенной оптимизации "High-Size" ("no_adc_value.png").

При отключеной оптимизации все нормально. ("yes_adc_value.png")686675179_noadc_value.thumb.png.7eeaec66620c39ec0760eb0fe50b9804.pngyes_adc_value.thumb.png.b45dc8e7d6245ede07d4cdcc370e8b8a.png

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

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


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

for (i = 0; i < 3; i++)
{
  asm ("LSR R14");
  asm ("ROR R15");
}

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

//  uint16_t x = ADC;  
        IN      R16, 0x04
        IN      R17, 0x05
//  x >>= 3;          
        LSR     R17
        ROR     R16
        LSR     R17
        ROR     R16
        LSR     R17
        ROR     R16
//  DDRC = x;
        OUT     0x14, R16
//  DDRD = x>>8;
        OUT     0x11, R17

Давайте лучше ваш алгоритм приведём в порядок вместо разгадывания шарад с протеусом.

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


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

#define N_CYCLE_ADC       8
uint16_t adc_ch_0, adc_ch_1;

void Result_ADC()
{
  static uint16_t sum_adc = 0;
  static uint8_t counter = N_CYCLE_ADC;
  
  sum_adc += ADC;
  
  if (--counter == 0) 
  {
    if(ADMUX & 0x01)
    {
      adc_ch_1 = sum_adc/N_CYCLE_ADC;
      ADMUX &= ~(1<<MUX0);
    }
    else
    {
      adc_ch_0 = sum_adc/N_CYCLE_ADC;
      ADMUX |= (1<<MUX0);
    }
    counter = N_CYCLE_ADC;
    sum_adc = 0;
  }
  
  ADCSRA |= (1 << ADSC);
}

Так задумывалось? Что-то мне подсказывает, что это будет оптимальней ваших изысканий.

//  void Result_ADC()
??Result_ADC:
//  {
//    static uint16_t sum_adc = 0;
//    static uint8_t counter = N_CYCLE_ADC;   
//    sum_adc += ADC;
        LDS     R18, (adc_ch_0 + 4)
        LDS     R19, (adc_ch_0 + 5)
        IN      R16, 0x04
        IN      R17, 0x05
        ADD     R18, R16
        ADC     R19, R17
//    if (--counter == 0) 
        LDS     R16, (adc_ch_0 + 6)
        DEC     R16
        BRNE    ??Result_ADC_1
//    {
//      sum_adc/N_CYCLE_ADC;
        LSR     R19
        ROR     R18
        LSR     R19
        ROR     R18
        LSR     R19
        ROR     R18
//      if(ADMUX & 0x01)          
        SBIS    0x07, 0x00
        RJMP    ??Result_ADC_2
//      {
//        adc_ch_1 = sum_adc/N_CYCLE_ADC;
        STS     (adc_ch_0 + 2), R18
        STS     (adc_ch_0 + 3), R19
//        ADMUX &= ~(1<<MUX0);
        CBI     0x07, 0x00
        RJMP    ??Result_ADC_3
//      }
//      else
//      {
/         adc_ch_0 = sum_adc/N_CYCLE_ADC;
??Result_ADC_2:
        STS     adc_ch_0, R18
        STS     (adc_ch_0 + 1), R19
//        ADMUX |= (1<<MUX0);
        SBI     0x07, 0x00
//      }
//      counter = N_CYCLE_ADC;
??Result_ADC_3:
        LDI     R16, 8
//      sum_adc = 0;
        LDI     R18, 0
        LDI     R19, 0
??Result_ADC_1:
        STS     (adc_ch_0 + 6), R16
        STS     (adc_ch_0 + 4), R18
        STS     (adc_ch_0 + 5), R19
//    }
//    ADCSRA |= (1 << ADSC);
        SBI     0x06, 0x06
//  }
        RET

Насчёт пошаговой отладки. При включенной оптимизации компилятор очень сильно видоизменяет код. Поэтому не всегда получается сопоставить строкам Си-кода соответствующие ассемблерные директивы. Вот отладчик и не может шагать по коду. Надо просто переходить в окно дизасма и там шагать.

 

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

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


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

4 hours ago, VladislavS said:

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

Попробую.

4 hours ago, VladislavS said:

Насчёт пошаговой отладки. При включенной оптимизации компилятор очень сильно видоизменяет код.

Что касается отладки, то вот сейчас начал разбираться с листингом после оптимизации.

    152          void Result_ADC (void)
   \                     ??Result_ADC:
    153          {
    154            static uint  sum_adc;
    155            static uchar ch_adc;
    156            uchar low_adc, high_adc;
    157            uint  adc_value;
    158          
    159              low_adc  = ADCL;
   \   00000000   B104               IN      R16, 0x04
    160              high_adc = ADCH;
    161              adc_value = high_adc * 256 + low_adc;
    162              sum_adc += adc_value;
   \   00000002   B135               IN      R19, 0x05
   \   00000004   2F20               MOV     R18, R16
   \   00000006   9100....           LDS     R16, (message_buf + 22)
   \   0000000A   9110....           LDS     R17, (message_buf + 23)
   \   0000000E   0F02               ADD     R16, R18
   \   00000010   1F13               ADC     R17, R19
   \   00000012   9300....           STS     (message_buf + 22), R16
   \   00000016   9310....           STS     (message_buf + 23), R17

Для локальных переменных low_adc и high_adc не выделяется память, а используются р-ры.

Операцию

adc_value = high_adc * 256 + low_adc;

компилятор вообще выбросил за ненадобностью, т.к. эта информация уже хранится в р-рах R16 и R19. Переменная adc_value действительно не нужна, но я добавил ее только для отладки в Proteus'е. Мне так удобно видеть изменение АЦП в десятиричном виде. В реале я бы ее потом выбросил. Вот поэтому отладчик и не "видит" эти строки.

А что касается Вашего кода, то мой компилятор выдает немного другой код. Хотя он и не сильно отличается.

   \                                 In  segment CODE, align 2, keep-with-next
    150          void Result_ADC()
   \                     ??Result_ADC:
    151          {
    152            static uint16_t sum_adc = 0;
    153            static uint8_t counter = N_CYCLE_ADC;
    154            
    155            sum_adc += ADC;
   \   00000000   9120....           LDS     R18, (adc_ch_0 + 4)
   \   00000004   9130....           LDS     R19, (adc_ch_0 + 5)
   \   00000008   B104               IN      R16, 0x04
   \   0000000A   B115               IN      R17, 0x05
   \   0000000C   0F20               ADD     R18, R16
   \   0000000E   1F31               ADC     R19, R17
    156            
    157            if (--counter == 0) 
   \   00000010   9100....           LDS     R16, (adc_ch_0 + 6)
   \   00000014   950A               DEC     R16
   \   00000016   F4B1               BRNE    ??Result_ADC_1
    158            {
    159              if(ADMUX & 0x01)
   \   00000018   9536               LSR     R19
   \   0000001A   9527               ROR     R18
   \   0000001C   9536               LSR     R19
   \   0000001E   9527               ROR     R18
   \   00000020   9536               LSR     R19
   \   00000022   9527               ROR     R18
   \   00000024   9B38               SBIS    0x07, 0x00
   \   00000026   C006               RJMP    ??Result_ADC_2
    160              {
    161                adc_ch_1 = sum_adc/N_CYCLE_ADC;
   \   00000028   9320....           STS     (adc_ch_0 + 2), R18
   \   0000002C   9330....           STS     (adc_ch_0 + 3), R19
    162                ADMUX &= ~(1<<MUX0);
   \   00000030   9838               CBI     0x07, 0x00
   \   00000032   C005               RJMP    ??Result_ADC_3
    163              }
    164              else
    165              {
    166                adc_ch_0 = sum_adc/N_CYCLE_ADC;
   \                     ??Result_ADC_2:
   \   00000034   9320....           STS     adc_ch_0, R18
   \   00000038   9330....           STS     (adc_ch_0 + 1), R19
    167                ADMUX |= (1<<MUX0);
   \   0000003C   9A38               SBI     0x07, 0x00
    168              }
    169              counter = N_CYCLE_ADC;
   \                     ??Result_ADC_3:
   \   0000003E   E008               LDI     R16, 8
    170              sum_adc = 0;
   \   00000040   E020               LDI     R18, 0
   \   00000042   E030               LDI     R19, 0
    171            }
   \                     ??Result_ADC_1:
   \   00000044   ....               RJMP    ?Subroutine0
   \   00000046                      REQUIRE _A_ADC
   \   00000046                      REQUIRE _A_ADMUX
   \   00000046                      REQUIRE _A_ADCSRA
    172            
    173            ADCSRA |= (1 << ADSC);
    174          }

В итоге большое спасибо за помощь, особенно за тильду. А то я "смотрю в книгу, вижу фигу".

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


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

46 минут назад, IF_P сказал:

А что касается Вашего кода, то мой компилятор выдает немного другой код.

Вот!!! Именно поэтому ваши ассемблерные костыли это огромное зло. Код вне функции влияет на то как компилятор будет распределять ресурсы и внутри функции. А вы там уже жёстко регистров понаписали. Забудьте про asm, он нужен только в экстренных случаях. И не так как вы его используете.

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


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

По поводу отладки в протеусе - он очень тяжко и плохо воспринимает debug инфу от разных компиляторов, кроме WinAVR от 2010 года. Он даже с более новыми версиями avr-gcc некорректно работает при отладке, точно также пропускает строки кода. А вы хотите с IAR заставить его работать. Он ведь официально IAR для AVR не поддерживает.

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


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

1 hour ago, NStorm said:

По поводу отладки в протеусе - он очень тяжко и плохо воспринимает debug инфу от разных компиляторов

Я бы так не сказал. Я не "заставляю" его работать, а просто работаю с ним и IAR'ом. Отладку в Proteus'е я делаю уже более 10 лет. В нем я отлаживаю до 95% кода. Остальное отлаживаю в железе. И то потому, что либо нет моделей, либо сложно моделировать и в железе проще. Конечно, попадались глюки самого Proteus'а. Но потом их исправляли. Что-то было с пропуском строк раз или два, но сейчас не помню. Да я и не разбирался тогда с ними. Возможно, это было связано с самой программой, а не с Proteus'ом, как в выше приведенном случае. Просто Proteus сопоставляет листинг программы и ubrof. А в моем случае в ubrof'е, в результате оптимизации, не было того кода, что в листинге. Вот он и пропустил эти строки. Я выше уже написал это.

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


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

Протеус и знать ничего не знает о ubrof афаик. Это проприетарный формат IAR'а. Он берет обычную coff/dwarf дебаг информацию из elf файла. Вы просто отключили оптимизацию и стало работать. Хотя должно работать и с оптимизацией. Я вам говорю реально простой пример - берем ASR-GCC 9.3 и комплируем им проект с опцией -Os -g - хрень полная получается в отладке протеуса полная. Тот же самый исходник с теми же самыми опциями, просто собранный AVR-GCC 4.х из WinAVR-2010.... прекрасно пошагово дебажится в протеусе без пропусков и проблем.

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


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

14 hours ago, NStorm said:

Протеус и знать ничего не знает о ubrof афаик. Это проприетарный формат IAR'а.

Да неужели?

А может все таки для начала стоит почитать документация по Proteus'у? Например, вот такую: ("Proteus Manual.pdf").

И вот что написано в этом документе: ("Ubrof.png")

Обратите внимание на слова "where possible "- т.е. где возможно. А если такой возможности нет, то, следовательно, строки пропускаются.
Приведу еще раз пример из моей программы:

   152          void Result_ADC (void)
   \                     ??Result_ADC:
    153          {
    154            static uint  sum_adc;
    155            static uchar ch_adc;
    156            uchar low_adc, high_adc;
    157            uint  adc_value;
    158          
    159              low_adc  = ADCL;
   \   00000000   B104               IN      R16, 0x04
    160              high_adc = ADCH;
    161              adc_value = high_adc * 256 + low_adc;
    162              sum_adc += adc_value;
   \   00000002   B135               IN      R19, 0x05
   \   00000004   2F20               MOV     R18, R16
   \   00000006   9100....           LDS     R16, (message_buf + 22)
   \   0000000A   9110....           LDS     R17, (message_buf + 23)
   \   0000000E   0F02               ADD     R16, R18
   \   00000010   1F13               ADC     R17, R19
   \   00000012   9300....           STS     (message_buf + 22), R16
   \   00000016   9310....           STS     (message_buf + 23), R17

Строки 159-161 Proteus пропускает. А что бы Вы делали на его месте? Локальные переменные low_adc и  high_adc (с.159-160) не существуют - они заменены р-рами. А строку 161 компилятор вообще выбросил за ненадобностью.

А что касается WinAVR или других систем, то я с ними не работал и поэтому ничего сказать не могу.

 

P.S.

Или вот еще.

 

Ubrof.png

 

Manual.png

ubrof.thumb.gif.c7a7cce434536e7d21d78d5c33e02799.gif

 

Proteus Manual.pdf

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

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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