Главная arrow Форум  
17.09.2019 г.
Главная
Проекты
Статьи
Начинающим
Архив новостей
Ссылки
Контакты
Поиск
Файлы
Форум
Карта сайта
Авторизация





Забыли пароль?
Ещё не зарегистрированы? Регистрация
Поддержи наш сайт!
Через WebMoney

 R785211844650
 Z210696637574
 E368177590409

Форум ARV Research
Добро пожаловать, Гость
Пожалуйста Вход или Регистрация.
Забыли пароль?
Си для МК и не только, вопросы и ответы (1 просматривает)
_GEN_GOTOBOTTOM Ответить

TOPIC: Си для МК и не только, вопросы и ответы

#7711
Apparatchik (Пользователь)
Специалист
Постов: 123
graphgraph
Си для МК и не только, вопросы и ответы 18.07.2012 22:18 Репутация: 0  
ARV писал(а):
кстати, последние вопросы отношения к Eclipse не имеют, не стоит вопросы по языку Си задавть в этой теме.
Тему вопросы по Си ненашол, решил создать.
ARV писал(а):
во-первых, разумеется, можно. лучше всего однотипные действия оформить в виде функции и передавать в нее нужный массив для работы. например, как-то так: my_function(effect ? tscr : scr);
во-вторых, вам следует запомнить, что в случае с одномерным массивом его ИМЯ и есть указатель на его первый элемент. если же вам все-таки хочется использовать оператор взятия адреса, то применять его надо к первому элементу. то есть &scr[0] == scr

Вот откуда мы пришли (на всякий случай).

Вот целиком функция:
Code:

  void setscr(uint8_t auint8_t buint8_t c// обновление экрана, если long_effect равна 2, то гасим ненужные разряды для температуры {     uint8_t i;     if (effect == 0) { // нету эфекта         if (long_effect != 2) {             scr[0] = 10;             scr[1] = 10;             scr[5] = 10;         } else {             scr[0] = 10;             scr[1] = 10;             scr[5] = 10;         }         scr[2] = 10;         scr[3] = 10;         scr[4] = 10;     }     else {         if (long_effect != 2) {             tscr[0] = 10;             tscr[1] = 10;             tscr[5] = 10;         } else {             tscr[0] = 10;             tscr[1] = 10;             tscr[5] = 10;         }         tscr[2] = 10;         tscr[3] = 10;         tscr[4] = 10;         for (0; (6); i++)             if (tscr[i] != scr[i])                 fr[i] = 1;             else                 fr[i] = 0// узнаём в каком разряде поменялась цифра     }     iocr 0;     flscr 0// сброс флага, чтения времени }


Если делать еще одну функцию. то придется параметры a, b, c тоже передавать, чуствую что можно оптимизировать "внутри", но никак непойму как, в голову приходит только указатель (мож я и не прав конечно), но с ними не работает как надо. Функция хоть и маленькая, но иногда каждый байт памяти на щету, к тому же хочется научится.

Содержимое поста отредактировано: Apparatchik, в: 18.07.2012 22:19
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7713
ARV (Администратор)
Администратор
Постов: 2384
graph
В ответ на: Си для МК и не только, вопросы и ответы 19.07.2012 09:16 Репутация: 175  
можно пойти минимум двумя путями:
1. использовать расширение GCC - локальные функции, т.е. внутри функции setscr определить функцию с одним параметром-указателем на массив, а параметры a,b,c будут ей доступны напрямую.
2. сделать еще одну функцию и передавать ей все нужные параметры - что вы и упомянули. но в этом случае саму функцию обязательно сделать static (для простых "однофайловых" проектов рекомендую вообще все функции делать static).

эффективность обоих методов заранее я предсказать не могу, первый представляется более удачным, хотя и менее переносимым, т.к. все-таки мы применяем отклонение от стандарта языка.

есть и третий путь, наиболее эффективный, но и более сложный - проанализировать весь алгоритм и изменить его так, чтобы добиться оптимальности.
Не стыдно не знать, стыдно не учиться
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7714
Apparatchik (Пользователь)
Специалист
Постов: 123
graphgraph
В ответ на: Си для МК и не только, вопросы и ответы 19.07.2012 20:24 Репутация: 0  
Все-таки с указателем получилось, функция приобрела вид:
Code:

  void setscr(uint8_t auint8_t buint8_t c// обновление экрана, если long_effect равна 2, то гасим ненужные разряды для температуры {     uint8_t i;     volatile uint8_t *mas;          if (effect == 0)         mas scr;     else         mas tscr;     if (long_effect != 2) {         mas[0] = 10;         mas[1] = 10;         mas[5] = 10;     } else {         mas[0] = 10;         mas[1] = 10;         mas[5] = 10;     }     mas[2] = 10;     mas[3] = 10;     mas[4] = 10;     if (effect != 0)         for (0; (6); i++)             if (tscr[i] != scr[i])                 fr[i] = 1;             else                 fr[i] = 0// узнаём в каком разряде поменялась цифра     iocr 0;     flscr 0// сброс флага, чтения времени }


и вроде все работает как и раньше
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7715
ARV (Администратор)
Администратор
Постов: 2384
graph
В ответ на: Си для МК и не только, вопросы и ответы 19.07.2012 20:49 Репутация: 175  
все равно как-то настораживают многочисленные деления на 10...
Не стыдно не знать, стыдно не учиться
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7716
Apparatchik (Пользователь)
Специалист
Постов: 123
graphgraph
В ответ на: Си для МК и не только, вопросы и ответы 19.07.2012 20:51 Репутация: 0  
ARV писал(а):
все равно как-то настораживают многочисленные деления на 10...
В эту функцию передаются три двух разрядных числа, например 23, как еще их можно разделить по разрядам? Массив это экран, в котором один элемент это один разряд.
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7717
ARV (Администратор)
Администратор
Постов: 2384
graph
В ответ на: Си для МК и не только, вопросы и ответы 20.07.2012 11:46 Репутация: 175  
не скажу с однозначной уверенностью, что мой метод лучше, но я обычно делаю так:
1. создал функцию вывода числа в переданную позицию "экранной области"
print_number(uint8_t *pos, uint8_t num);
2. потом использую ее примерно так:
print_number(&screen[3], a);
print_number(&screen[5], b);
print_number(&screen[0], c);

об этом подходе и его вариациях я писал статью http://arv.radioliga.com/content/view/106/49/

P.S. в принципе, в функции вместо указателя на экранную позицию можно вполне обойтись номером этой позиции - экран-то один и глобальный, че на него указатели плодить... получается гораздо экономнее.

Содержимое поста отредактировано: ARV, в: 20.07.2012 11:49
Не стыдно не знать, стыдно не учиться
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7718
Apparatchik (Пользователь)
Специалист
Постов: 123
graphgraph
В ответ на: Си для МК и не только, вопросы и ответы 23.07.2012 19:41 Репутация: 0  
Добрый вечер.

Понадобился сторожевой таймер, на мега8 работает отлично, но нужно на мега168 и возникли проблемы. Я специально "вешал" мк чтоб проверить, в Вашей статье написано что нужно как можно раньше выключать, я пробовал выключать первой строкой в main но видимо поздно - мк виснет тоесть перегружается (вроде). Пробовал скопировать Ваш код из статьи:
Code:

  #include <stdint.h> #include <avr/wdt.h> // объявление «неинициализируемой» переменной uint8_t mcusr_mirror _attribute_ ((section (І.noinitІ))); // объявление функции «запоминания» значения MCUSR void get_mcusr(void\ __attribute__((naked)) /* без пролога и эпилога */ __attribute__((section(І.init3І))); /* в секции автоматической инициализации пользователя */ void get_mcusr(void){ mcusr_mirror MCUSR; MCUSR 0; wdt_disable(); }


даже при объявлении неинициализируемой переменной компилятор ругается (Eclipse) , и еще я непонял почему именно неинициализируемой ведь если она будет нулем а потом ей присвоить значение MCUSR то что поменяется?

P.S. с "руганью" компилятора вроде разобрался, остальное прошу разъяснить. Функцию get_mcusr () ведь нужно вызывать в начале main?

Содержимое поста отредактировано: Apparatchik, в: 23.07.2012 20:12
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7719
ARV (Администратор)
Администратор
Постов: 2384
graph
В ответ на: Си для МК и не только, вопросы и ответы 23.07.2012 20:25 Репутация: 175  
во-первых, если атрибутов несколько, их можно указывать в одном макросе __attribute__, то есть так: __attribute__((naked, section("init3"))
во-вторых, название секции должно быть в двойных кавычках, как любая строка Си - у вас в примере этого нет
в-третьих, если функция в одной из init-секции, то вызывать ее ниоткуда не надо - она будет автоматом выполнена перед входом в main на соответствующем этапе инициализации.
в-четвертых, по поводу переменных. как известно, все глобальные переменные в Си, если явно для них начальное значение не указано, будут обнулены перед входом в main. поэтому совершенно невозможно сохранить в какой-либо переменной значение после сброса, т.к. оно будет автоматически затерто. когда вы работаете с WDT, информация о состоянии программы (т.е. значение некоторых переменных) чаще всего должна пережить сброс, поэтому ее просто необходимо сохранять в переенных, которые не обнуляются автоматически при старте программы. вот в чем разница.

что там у вас виснет и при каких условиях - я не понял, и потому пока ничем помочь не могу.
Не стыдно не знать, стыдно не учиться
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7720
Apparatchik (Пользователь)
Специалист
Постов: 123
graphgraph
В ответ на: Си для МК и не только, вопросы и ответы 23.07.2012 20:37 Репутация: 0  
Спасибо, вроде все понял, буду эксперементировать дальше.
ARV писал(а):

что там у вас виснет и при каких условиях - я не понял, и потому пока ничем помочь не могу.
Чтобы понять работу WDT я специально вводил мк в вечный цикл и пробовал выключать WDT макросом wdt_disable(); в начале main, но непрокатило и тогда начал копать глубже. Еще раз спасибо.
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7721
ARV (Администратор)
Администратор
Постов: 2384
graph
В ответ на: Си для МК и не только, вопросы и ответы 23.07.2012 21:05 Репутация: 175  
если склероз меня не подводит, минимальный интервал WDT это около 15 миллисекунд - по масштабам МК это довольно много... то есть вероятность того, что main не успеет отключить WDT до его срабатывания весьма мала, если, конечно, тактируетесь вы не от часового кварца

Содержимое поста отредактировано: ARV, в: 23.07.2012 21:05
Не стыдно не знать, стыдно не учиться
  Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
_GEN_GOTOTOP Ответить
© Copyright 2007 Best of Joomla, Работает на FireBoardполучить последние сообщения прямо на Ваш рабочий стол