Например TDA7294

Форум РадиоКот • Просмотр темы - EEPROM запись в цикле.
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Вт апр 16, 2024 12:33:06

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 36 ]    , 2
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пт окт 20, 2017 18:20:09 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 1244
Зарегистрирован: Вс мар 29, 2009 22:09:05
Сообщений: 7517
Рейтинг сообщения: 3
Цитата:
но даже не знаю какой стандарт поддерживает avr-gcc в atmelstudio ведь не так давно вышел очередной стандарт с++17


Про это можете забыть сразу. :)))

Вообще про плюсы на контроллере, да еще и Гарвардской архитектуры, вспоминать грешно.

Чтобы использовать C++ с комфортом, необходимо как минимум динамическое выделение памяти, а для микроконтроллера это непозволительная роскошь - здесь нормальный менеджер памяти сам почти всю доступную память и скушает. :))) Отдельный поворот делу придает то, что AVR, например, не может выполнять код из RAM (Гарвардская архитектура, да).

Конечно, отдельные эстеты умудряются писать на плюсах и под мелкие МК, но к этому нельзя относиться всерьез.

Так что только ANSI C, причем, желательно, с учетом правил MISRA. :)

_________________
Разница между теорией и практикой на практике гораздо больше, чем в теории.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пт окт 20, 2017 18:33:18 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
:facepalm: какой там С++17, когда с перебором массива структур проблемы...

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

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пт окт 20, 2017 20:09:01 
Прорезались зубы
Аватар пользователя

Карма: 2
Рейтинг сообщений: 11
Зарегистрирован: Сб янв 14, 2012 22:53:50
Сообщений: 225
Рейтинг сообщения: 0
Вообще про плюсы на контроллере, да еще и Гарвардской архитектуры, вспоминать грешно.


Ну, это вы слегка погорячились. Практический пример преимущества использования плюсов под мк.

Так что при хорошем владении плас ничем не уступает Си, а местами даже дает преимущества.


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Сб окт 21, 2017 08:50:26 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Переделал немного код, добавил плавное включение. (осталось в момент плавного включения добавить обработку индикации).

Код:
Спойлер
Код:
#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>

//----------///init_pwm///----------//
void init_pwm()
{
   TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
   TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
   OCR0A=0x00;
   OCR0B=0x00;
   
   TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
   TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);
   OCR1AL=0x00;
   OCR1BL=0x00;

   TCCR2A=(1<<COM2A1) | (0<<COM2A0) | (1<<COM2B1) | (0<<COM2B0) | (1<<WGM21) | (1<<WGM20);
   TCCR2B=(0<<WGM22) | (0<<CS22) | (1<<CS21) | (0<<CS20);
   OCR2A=0x00;
   OCR2B=0x00;
}
//----------//
void init_int0()
{
   //настраиваем на срабатывание INT0 по переднему фронту
   EICRA |= (1<<ISC01)|(0<<ISC00);
   //разрешаем внешнее прерывание INT0
   EIMSK |= (1<<INT0);
}
//----------//
void init_io()
{
   DDRB=(0<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(0<<PB5)|(0<<PB6)|(0<<PB7);
   PORTB=0x00;
   DDRC=(1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC3)|(1<<PC4)|(1<<PC5)|(1<<PC6);
   PORTC=0x00;
   DDRD=(1<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD5)|(1<<PD6)|(1<<PD7);
   PORTD=0x00;
}
//----------//
//настройка параметров работы функций
#define BTN_LOCK_TIME      30               /*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME      1000            /*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/
//настройки портов
/*порт чтения кнопок*/
#define BTN_PORT         PORTB
#define BTN_DDR            DDRB
#define BTN_PIN            PINB
/*пины чтения кнопок*/
#define BTN_LINE_UP      (1<<7)
#define BTN_LINE_DN      (1<<6)
#define BTN_LINE_POWER   (1<<5)
#define BTN_LINE_SW      (1<<0)
//глобальные переменные
volatile uint8_t BtnFlags;               //байт флагов нажатия кнопки
#define BTN_SHRT_UP         (1<<0)         /*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN         (1<<1)         /*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER      (1<<2)         /*бит короткого нажатия кнопки POWER */
#define BTN_SHRT_SW         (1<<3)         /*бит короткого нажатия кнопки SW*/
#define BTN_LONG_UP         (1<<4)         /*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN         (1<<5)         /*бит длинного нажатия кнопки dn*/
#define BTN_LONG_SW         (1<<6)         /*бит короткого нажатия кнопки SW*/
//----------
//Функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
   BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER|BTN_LINE_SW);//на ввод
   BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER|BTN_LINE_SW);//подтяжка вкл
}
//----------
//Функция чтения данных о нажатии кнопок
char BtnGet (void)
{
   cli();
   char temp = BtnFlags;
   BtnFlags = 0;
   sei();
   return temp;
}
//----------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
   static unsigned char BtnLockBit;            //защелка (защита от дребезга)
   static unsigned char BtnLockCoun;         //счетчик защелки (защита от дребезга)
   static unsigned char BtnLongCoun;         //счетчик длинного нажатия
   static unsigned char BtnLastState;         //последнее состояние кнопок перед отпусканием

   char mask = 0;
   if (! (BTN_PIN & BTN_LINE_UP))      mask = BTN_SHRT_UP;
   if (! (BTN_PIN & BTN_LINE_DN))      mask = BTN_SHRT_DN;
   if (! (BTN_PIN & BTN_LINE_POWER))   mask = BTN_SHRT_POWER;
   if (! (BTN_PIN & BTN_LINE_SW))      mask = BTN_SHRT_SW;

   if (mask){                           //опрос состояния кнопки
      if (BtnLockCoun < (BTN_LOCK_TIME/10)){   //клавиша нажата
         BtnLockCoun++;
         return;                        //защелка еще не дощитала - возврат
      }
      BtnLastState = mask;
      BtnLockBit =1;                     //нажатие зафиксировано
      if (BtnLongCoun >= (BTN_LONG_TIME/10))
      return;                        //возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
      if (++BtnLongCoun >= (BTN_LONG_TIME/10))
      BtnFlags |= (BtnLastState<<4);         //счетчик досчитал до максимума - устанавливаем биты длинного нажатия
   }
   else{                              //клавиша отжата
      if (BtnLockCoun){
         BtnLockCoun --;
         return;                        //защелка еще не обнулилась - возврат
      }
      if (! BtnLockBit)                  //СТАТИЧЕСКИЙ ВОЗВРАТ
      return;
      BtnLockBit =0;                     //отжатие зафиксировано
      if (BtnLongCoun < (BTN_LONG_TIME/10))
      BtnFlags |= BtnLastState;         //установка бита короткого нажатия
      BtnLongCoun = 0;               //сброс счетчика длительности нажатия
   }
}
//----------****7SEG****----------
#define SEGA 6
#define SEGB 5
#define SEGC 1
#define SEGD 2
#define SEGE 3
#define SEGF 4
#define SEGG 0

#define ANOD1 4
#define ANOD2 7
#define ANOD3 4
//----------
void segchar (unsigned char seg)
{
   switch (seg)
   {
      case 0:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG);break;
      case 1:
      PORTC=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break;
      case 2:
      PORTC=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG);break;
      case 3:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG);break;
      case 4:
      PORTC=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 5:
      PORTC=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 6:
      PORTC=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 7:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break;
      case 8:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 9:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 99: //OFF Все сегменты
      PORTC=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break;
   }
}

#define CONFIG_AMOUNT 6
typedef struct
{
   char FlagPower;
   char ValuePWM;
}ConfigurationLamp;

EEMEM ConfigurationLamp E_ConfigLamp[CONFIG_AMOUNT];
ConfigurationLamp ConfigLamp[CONFIG_AMOUNT];
//----------

void LoadingEEPROM()
{
   eeprom_read_block((void*)ConfigLamp, (void*)E_ConfigLamp, sizeof(ConfigLamp));
}

void SaveEEPROM()
{
   eeprom_update_block((void*)ConfigLamp, (void*)E_ConfigLamp, sizeof(ConfigLamp));
}
void WriteValue(unsigned char Zona,unsigned char ValuePWM)
{
   switch (Zona)
   {
      case 0:OCR0A=ValuePWM*2.56;break;
      case 1:OCR0B=ValuePWM*2.56;break;
      case 2:OCR1AL=ValuePWM*2.56;break;
      case 3:OCR1BL=ValuePWM*2.56;break;
      case 4:OCR2A=ValuePWM*2.56;break;
      case 5:OCR2B=ValuePWM*2.56;break;
   }
}
char ReadValue(unsigned char Zona)
{
   static unsigned char ValuePWM=0;
   switch (Zona)
   {
      case 0:ValuePWM=OCR0A;break;
      case 1:ValuePWM=OCR0B;break;
      case 2:ValuePWM=OCR1AL;break;
      case 3:ValuePWM=OCR1BL;break;
      case 4:ValuePWM=OCR2A;break;
      case 5:ValuePWM=OCR2B;break;
   }
   return(ValuePWM/2.56);
}
unsigned char TempValuePWM=0;
void UpdateValue()
{
   for (unsigned char ZonaCount = 0; ZonaCount < CONFIG_AMOUNT; ZonaCount++)
   {
      TempValuePWM=ReadValue(ZonaCount);
      if (ConfigLamp[ZonaCount].FlagPower==1)
      {
         if (TempValuePWM==0)
         {
            while(TempValuePWM<ConfigLamp[ZonaCount].ValuePWM)
            {
               TempValuePWM++;
               WriteValue(ZonaCount,TempValuePWM);
               _delay_ms(50);
            }
         }
         WriteValue(ZonaCount,ConfigLamp[ZonaCount].ValuePWM);
      }
      else
      {
         WriteValue(ZonaCount,0);
      }
      
   }
}
unsigned char ZoneNumber=0;
unsigned char count = 0;
void WriteSeg(unsigned char Number)
{
   unsigned char data1=ConfigLamp[Number].ValuePWM%10;
   unsigned char data2=ConfigLamp[Number].ValuePWM/10;
   PORTB |=(1<<ANOD1);
   PORTD |=(1<<ANOD2);
   PORTD |=(1<<ANOD3);
   segchar(99);
   if(ConfigLamp[Number].FlagPower==1)
   {
      count++;
      if (count==1){
         PORTB &= ~(1<<ANOD1);
         segchar(data1);
         PORTD |=(1<<ANOD2);
         PORTD |=(1<<ANOD3);
      }
      if (count==2){
         PORTD &= ~(1<<ANOD2);
         segchar(data2);
         PORTB |=(1<<ANOD1);
         PORTD |=(1<<ANOD3);
      }
      if (count==3){
         PORTD &= ~(1<<ANOD3);
         segchar(Number+1);
         PORTB |=(1<<ANOD1);
         PORTD|=(1<<ANOD2);
      }
      if (count==3){count=0;}
   }
}
char Stop=1;
ISR(INT0_vect)
{
   WriteSeg(ZoneNumber);
   UpdateValue();
   BtnExe();
}
void BtnUpdate(void)
{
   char BtnMask = BtnGet ();
   if (BtnMask == BTN_SHRT_POWER)
   {
      ConfigLamp[ZoneNumber].FlagPower++;
      if (ConfigLamp[ZoneNumber].FlagPower>1)
      {
         ConfigLamp[ZoneNumber].FlagPower=0;
      }
      SaveEEPROM();
   }
   if ((BtnMask == BTN_SHRT_SW))
   {
      ZoneNumber++;
      if (ZoneNumber==6)
      {
         ZoneNumber=0;
      }
   }
   //одиночное нажатие +
   if ((BtnMask == BTN_SHRT_UP)& (ConfigLamp[ZoneNumber].ValuePWM < 99)&(ConfigLamp[ZoneNumber].FlagPower==1))
   {
      ConfigLamp[ZoneNumber].ValuePWM++;
      SaveEEPROM();
   }
   //одиночное нажатие -
   if ((BtnMask == BTN_SHRT_DN)& (ConfigLamp[ZoneNumber].ValuePWM > 0)&(ConfigLamp[ZoneNumber].FlagPower==1))
   {
      ConfigLamp[ZoneNumber].ValuePWM--;
      SaveEEPROM();
   }
   //Удержание +
   if ((BtnMask == BTN_LONG_UP) & (ConfigLamp[ZoneNumber].ValuePWM < 99)&(ConfigLamp[ZoneNumber].FlagPower==1))
   {
      while ((!(PINB&0b10000000))& (ConfigLamp[ZoneNumber].ValuePWM < 99))
      {
         ConfigLamp[ZoneNumber].ValuePWM++;
         _delay_ms(50);
      }
      SaveEEPROM();
   }
   //Удержание -
   if ((BtnMask == BTN_LONG_DN) & (ConfigLamp[ZoneNumber].ValuePWM > 0)&(ConfigLamp[ZoneNumber].FlagPower==1))
   {
      while ((!(PINB&0b01000000))& (ConfigLamp[ZoneNumber].ValuePWM > 0))
      {
         ConfigLamp[ZoneNumber].ValuePWM--;
         _delay_ms(50);
      }
      SaveEEPROM();
   }
}

int main(void)
{
   cli();
   LoadingEEPROM();
   init_io();
   BtnInit();
   init_int0();
   init_pwm();
   sei();
    while(1)
    {
      BtnUpdate();
   }
   return 0;
}

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Сб окт 21, 2017 09:45:41 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 1244
Зарегистрирован: Вс мар 29, 2009 22:09:05
Сообщений: 7517
Рейтинг сообщения: 0
philosoraptor, я читал и эту статью, и ей подобные. И тут есть несколько моментов.

1. Автор рассматривает исключительно задачу работы с периферией, причем исключительно с портами. Выше же шла речь о более широком применении С++, в частности, и в основной логике - иначе зачем вообще заморачиваться?

2. Автор использует исключительно статические классы и ни словом не заикнулся (логично) про создание их экземпляров. И все равно, несмотря на все изгибание C++ для применимости в эмбеде, не обошлось без ограничений:

- "От динамической конфигурации линий ввода-вывода сразу отказываемся из-за необходимости доступа к портам через указатель со всеми вытекающими последствиями."

- "Мы не можем прочитать состояние выходных линий регистра – он всегда работает на выход, поэтому функцию чтения состояния не реализуем и не объявляем. Попытка прочитать состояние такого пора вызовет ошибку компиляции."

А динамическая конфигурация бывает нужна. Например, чтобы имитировать открытый коллектор на AVR.

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

3. И несмотря на все ограничения код получился тяжеловесным и сложным для понимания. Даже сам автор в некоторый момент устал: "Обобщая доступ к отдельным битам в списке линий приходим к концепции среза. Не буду вдаваться в подробности их реализации".

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

Родственный пример (для AVR-libc) - функции задержки, например, _delay_ms(). Если подставить в нее не константу, а переменную, будет сюрприз. Здесь может произойти нечто подобное.

Кстати, рекурсия, используемая автором, запрещена стандартом MISRA.

Код:
struct MakePinList
{
private:
      // рекурсивно проходим все параметры
      // на следующей итерации Position увеличится на 1,
      // а T2 превратится в T1 и так далее
typedef typename MakePinList
<
      Position + 1,

...


5. В целом можно сказать, что фактически автор лишь использует механизм шаблонов C++ как продвинутый препроцессор. Впрочем, и без классического препроцессора не обходится:

Код:
#define MAKE_PORT(portName, className, ID) \
   class className{\
   public:\
      typedef uint8_t DataT;\
   public:\
...


Это вообще в некоторой степени противоречит идеологии C++.

_________________
Разница между теорией и практикой на практике гораздо больше, чем в теории.


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Сб окт 21, 2017 12:20:15 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Так в программирование неуместно употреблять один подход, и скорее даже не возможно написать код следуя всего лишь одной парадигме программирования т.к
даже на языке Си, который не является объектно-ориентированным, можно работать в соответствии с принципами объектно-ориентированного программирования, хотя это и сопряжено с определёнными сложностями, а функциональное программирование можно применять при работе на любом императивном языке, в котором имеются функции,
Я решил закончить данную прошивку в стиле функционального программирования, а уже следующие не мение интересную попробовать написать (не потеряв при этом быстродействие) сделав уклон на ООП.

Добавлено after 8 minutes 23 seconds:
А насчет MISRA C который являеться как бы ''стандартом разработки программного обеспечения на Си'" . предполгаю что на данный момент времени он не являеться актуальным т.к насколько мне известно они не удосужились внести С99 в описание своего стандарта, не говоря о уже о том что процесса сертификации MISRA не существует в принцепе.

Добавлено after 1 hour 7 minutes 32 seconds:
Я вот думаю как все таки более лаконично написать легко переносимую функцию? для работы с динамической индикацией семи сегментного индикатора.
А то segchar()+WriteSeg() выглядят как то не комильфо.

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Сб окт 21, 2017 12:30:14 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 1244
Зарегистрирован: Вс мар 29, 2009 22:09:05
Сообщений: 7517
Рейтинг сообщения: 0
Цитата:
предполгаю что на данный момент времени он не являеться актуальным


Это всего лишь ваше предположение. :) Впрочем, некоторые говорят, что и Си не является актуальным. :)))

Процесса сертификации MISRA не существует по простой причине: MISRA - это, так сказать, набор хороших советов, которые применимы для создания кода, используемого в разных применениях в разных отраслях с разными требованиями и подходами к сертификации. Например, устройство в целом может быть сертифицировано на некоторый уровень SIL, при этом для достижения этой цели логично использовать правила MISRA при написании прошивки - это уберет много граблей. Можно, конечно, не заморачиваться и идти путем проб и ошибок, самостоятельно переоткрывая рекомендации MISRA. :wink:

Цитата:
Я вот думаю как все таки более лаконично написать легко переносимую функцию?


Я для динамической индикации использую что-то вроде фреймбуфера, в который складываю паттерны для символов на индикаторе. Этот буфер выводится в порт по прерыванию. Заполняет его отдельная функция, которая заодно преобразует числа/символы в паттерны.

_________________
Разница между теорией и практикой на практике гораздо больше, чем в теории.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Сб окт 21, 2017 13:29:01 
Прорезались зубы
Аватар пользователя

Карма: 2
Рейтинг сообщений: 11
Зарегистрирован: Сб янв 14, 2012 22:53:50
Сообщений: 225
Рейтинг сообщения: 0
YS писал(а):
_delay_ms(). Если подставить в нее не константу, а переменную, будет сюрприз.

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

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

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Сб окт 21, 2017 13:52:51 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 1244
Зарегистрирован: Вс мар 29, 2009 22:09:05
Сообщений: 7517
Рейтинг сообщения: 0
Цитата:
Гарантии нет в любом случае, даже если строго следовать всем стандартам.


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

Я считаю, что на оптимизацию вообще полагаться не надо. Надо стараться, чтобы написанный код был как можно более прозрачен.

Цитата:
Например, если мы неплохо владеем С++, то легко сможем составить на нем и полностью обратно-совместимый с чистым Си код.


В этом случае обычно пишут библиотеку на чистом C, а на C++ делают только обертку для желающих. Такой подход гораздо лучше потому, что обеспечивает совместимость не только на уровне исходников, но и на бинарном уровне - скажем, DLL на чистом Си гораздо универсальнее. То же самое справедливо и для скомпилированных статических библиотек.

_________________
Разница между теорией и практикой на практике гораздо больше, чем в теории.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пн окт 23, 2017 03:28:10 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Ну вот и готов финишный код.
Конечно реализация плавного запуска желает желать лучшего, но она все же справляется со своими задачами.

Код:
Спойлер
Код:
#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>

//----------///init_pwm///----------//
void init_pwm()
{
   TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
   TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
   OCR0A=0x00;
   OCR0B=0x00;
   
   TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
   TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);
   OCR1AL=0x00;
   OCR1BL=0x00;

   TCCR2A=(1<<COM2A1) | (0<<COM2A0) | (1<<COM2B1) | (0<<COM2B0) | (1<<WGM21) | (1<<WGM20);
   TCCR2B=(0<<WGM22) | (0<<CS22) | (1<<CS21) | (0<<CS20);
   OCR2A=0x00;
   OCR2B=0x00;
}
//----------//
void init_int0()
{
   //настраиваем на срабатывание INT0 по переднему фронту
   EICRA |= (1<<ISC01)|(0<<ISC00);
   //разрешаем внешнее прерывание INT0
   EIMSK |= (1<<INT0);
}
//----------//
void init_io()
{
   DDRB=(0<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(0<<PB5)|(0<<PB6)|(0<<PB7);
   PORTB=0x00;
   DDRC=(1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC3)|(1<<PC4)|(1<<PC5)|(1<<PC6);
   PORTC=0x00;
   DDRD=(1<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD5)|(1<<PD6)|(1<<PD7);
   PORTD=0x00;
}
//----------//
//настройка параметров работы функций
#define BTN_LOCK_TIME      30               /*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME      1000            /*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/
//настройки портов
/*порт чтения кнопок*/
#define BTN_PORT         PORTB
#define BTN_DDR            DDRB
#define BTN_PIN            PINB
/*пины чтения кнопок*/
#define BTN_LINE_UP      (1<<7)
#define BTN_LINE_DN      (1<<6)
#define BTN_LINE_POWER   (1<<5)
#define BTN_LINE_SW      (1<<0)
//глобальные переменные
volatile uint8_t BtnFlags;               //байт флагов нажатия кнопки
#define BTN_SHRT_UP         (1<<0)         /*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN         (1<<1)         /*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER      (1<<2)         /*бит короткого нажатия кнопки POWER */
#define BTN_SHRT_SW         (1<<3)         /*бит короткого нажатия кнопки SW*/
#define BTN_LONG_UP         (1<<4)         /*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN         (1<<5)         /*бит длинного нажатия кнопки dn*/
#define BTN_LONG_SW         (1<<6)         /*бит короткого нажатия кнопки SW*/
//----------
//Функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
   BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER|BTN_LINE_SW);//на ввод
   BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER|BTN_LINE_SW);//подтяжка вкл
}
//----------
//Функция чтения данных о нажатии кнопок
char BtnGet (void)
{
   cli();
   char temp = BtnFlags;
   BtnFlags = 0;
   sei();
   return temp;
}
//----------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
   static unsigned char BtnLockBit;            //защелка (защита от дребезга)
   static unsigned char BtnLockCoun;         //счетчик защелки (защита от дребезга)
   static unsigned char BtnLongCoun;         //счетчик длинного нажатия
   static unsigned char BtnLastState;         //последнее состояние кнопок перед отпусканием

   char mask = 0;
   if (! (BTN_PIN & BTN_LINE_UP))      mask = BTN_SHRT_UP;
   if (! (BTN_PIN & BTN_LINE_DN))      mask = BTN_SHRT_DN;
   if (! (BTN_PIN & BTN_LINE_POWER))   mask = BTN_SHRT_POWER;
   if (! (BTN_PIN & BTN_LINE_SW))      mask = BTN_SHRT_SW;

   if (mask){                           //опрос состояния кнопки
      if (BtnLockCoun < (BTN_LOCK_TIME/10)){   //клавиша нажата
         BtnLockCoun++;
         return;                        //защелка еще не дощитала - возврат
      }
      BtnLastState = mask;
      BtnLockBit =1;                     //нажатие зафиксировано
      if (BtnLongCoun >= (BTN_LONG_TIME/10))
      return;                        //возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
      if (++BtnLongCoun >= (BTN_LONG_TIME/10))
      BtnFlags |= (BtnLastState<<4);         //счетчик досчитал до максимума - устанавливаем биты длинного нажатия
   }
   else{                              //клавиша отжата
      if (BtnLockCoun){
         BtnLockCoun --;
         return;                        //защелка еще не обнулилась - возврат
      }
      if (! BtnLockBit)                  //СТАТИЧЕСКИЙ ВОЗВРАТ
      return;
      BtnLockBit =0;                     //отжатие зафиксировано
      if (BtnLongCoun < (BTN_LONG_TIME/10))
      BtnFlags |= BtnLastState;         //установка бита короткого нажатия
      BtnLongCoun = 0;               //сброс счетчика длительности нажатия
   }
}
//----------****7SEG****----------
#define SEGA 6
#define SEGB 5
#define SEGC 1
#define SEGD 2
#define SEGE 3
#define SEGF 4
#define SEGG 0

#define ANOD1 4
#define ANOD2 7
#define ANOD3 4
//----------
void segchar (unsigned char seg)
{
   switch (seg)
   {
      case 0:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG);break;
      case 1:
      PORTC=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break;
      case 2:
      PORTC=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG);break;
      case 3:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG);break;
      case 4:
      PORTC=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 5:
      PORTC=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 6:
      PORTC=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 7:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break;
      case 8:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 9:
      PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break;
      case 99: //OFF Все сегменты
      PORTC=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break;
   }
}

#define CONFIG_AMOUNT 6
typedef struct
{
   char FlagPower;
   char ValuePWM;
}ConfigurationLamp;

EEMEM ConfigurationLamp E_ConfigLamp[CONFIG_AMOUNT];
ConfigurationLamp ConfigLamp[CONFIG_AMOUNT];
//----------

void LoadingEEPROM()
{
   eeprom_read_block((void*)ConfigLamp, (void*)E_ConfigLamp, sizeof(ConfigLamp));
}

void SaveEEPROM()
{
   eeprom_update_block((void*)ConfigLamp, (void*)E_ConfigLamp, sizeof(ConfigLamp));
}
//Функция записи значения PWM
void WriteValue(unsigned char Zona,unsigned char ValuePWM)
{
   switch (Zona)
   {
      case 0:OCR0A=ValuePWM*2.56;break;
      case 1:OCR0B=ValuePWM*2.56;break;
      case 2:OCR1AL=ValuePWM*2.56;break;
      case 3:OCR1BL=ValuePWM*2.56;break;
      case 4:OCR2A=ValuePWM*2.56;break;
      case 5:OCR2B=ValuePWM*2.56;break;
   }
}
//Функция считывания значения PWM
char ReadValue(unsigned char Zona)
{
   static unsigned char ValuePWM=0;
   switch (Zona)
   {
      case 0:ValuePWM=OCR0A;break;
      case 1:ValuePWM=OCR0B;break;
      case 2:ValuePWM=OCR1AL;break;
      case 3:ValuePWM=OCR1BL;break;
      case 4:ValuePWM=OCR2A;break;
      case 5:ValuePWM=OCR2B;break;
   }
   return(ValuePWM/2.56);
}
//Функция вывода значений на 7SEG индикатор.
unsigned char ZoneNumber=0;
unsigned char count = 0;
void WriteSeg(unsigned char NumberZon,unsigned char ValuePWM)
{
   
   unsigned char data1=ValuePWM%10;
   unsigned char data2=ValuePWM/10;
   PORTB |=(1<<ANOD1);
   PORTD |=(1<<ANOD2);
   PORTD |=(1<<ANOD3);
   segchar(99);
   if(ConfigLamp[NumberZon].FlagPower==1)
   {
      count++;
      if (count==1){
         PORTB &= ~(1<<ANOD1);
         segchar(data1);
         PORTD |=(1<<ANOD2);
         PORTD |=(1<<ANOD3);
      }
      if (count==2){
         PORTD &= ~(1<<ANOD2);
         segchar(data2);
         PORTB |=(1<<ANOD1);
         PORTD |=(1<<ANOD3);
      }
      if (count==3){
         PORTD &= ~(1<<ANOD3);
         segchar(NumberZon+1);
         PORTB |=(1<<ANOD1);
         PORTD|=(1<<ANOD2);
      }
      if (count==3){count=0;}
   }
}

/*****************************************Обновление Значений PWM********************************************************/
float TempValuePWM=0;
void UpdateValue()
{
   for (unsigned char ZonaCount = 0; ZonaCount < CONFIG_AMOUNT; ZonaCount++)
   {
      TempValuePWM=ReadValue(ZonaCount);
      if (ConfigLamp[ZonaCount].FlagPower==1)
      {
         if (TempValuePWM==0)
         {
            //Плавный Запуск
            TempValuePWM=1;
            while(TempValuePWM<ConfigLamp[ZonaCount].ValuePWM)
            {
               TempValuePWM=TempValuePWM+TempValuePWM/40;
               WriteValue(ZonaCount,TempValuePWM);
               WriteSeg(ZonaCount,TempValuePWM);
               _delay_ms(13);
            }
         }
         WriteValue(ZonaCount,ConfigLamp[ZonaCount].ValuePWM);
      }
      else
      {
         WriteValue(ZonaCount,0);
      }
      
   }
}

char Stop=1;
ISR(INT0_vect)
{
   WriteSeg(ZoneNumber,ConfigLamp[ZoneNumber].ValuePWM);
   UpdateValue();
   BtnExe();
}
void BtnUpdate(void)
{
   char BtnMask = BtnGet ();
   if (BtnMask == BTN_SHRT_POWER)
   {
      ConfigLamp[ZoneNumber].FlagPower++;
      if (ConfigLamp[ZoneNumber].FlagPower>1)
      {
         ConfigLamp[ZoneNumber].FlagPower=0;
      }
      SaveEEPROM();
   }
   if ((BtnMask == BTN_SHRT_SW))
   {
      ZoneNumber++;
      if (ZoneNumber==6)
      {
         ZoneNumber=0;
      }
   }
   //одиночное нажатие +
   if ((BtnMask == BTN_SHRT_UP)& (ConfigLamp[ZoneNumber].ValuePWM < 99)&(ConfigLamp[ZoneNumber].FlagPower==1))
   {
      ConfigLamp[ZoneNumber].ValuePWM++;
      SaveEEPROM();
   }
   //одиночное нажатие -
   if ((BtnMask == BTN_SHRT_DN)& (ConfigLamp[ZoneNumber].ValuePWM > 0)&(ConfigLamp[ZoneNumber].FlagPower==1))
   {
      ConfigLamp[ZoneNumber].ValuePWM--;
      SaveEEPROM();
   }
   //Удержание +
   if ((BtnMask == BTN_LONG_UP) & (ConfigLamp[ZoneNumber].ValuePWM < 99)&(ConfigLamp[ZoneNumber].FlagPower==1))
   {
      while ((!(PINB&0b10000000))& (ConfigLamp[ZoneNumber].ValuePWM < 99))
      {
         ConfigLamp[ZoneNumber].ValuePWM++;
         _delay_ms(50);
      }
      SaveEEPROM();
   }
   //Удержание -
   if ((BtnMask == BTN_LONG_DN) & (ConfigLamp[ZoneNumber].ValuePWM > 0)&(ConfigLamp[ZoneNumber].FlagPower==1))
   {
      while ((!(PINB&0b01000000))& (ConfigLamp[ZoneNumber].ValuePWM > 0))
      {
         ConfigLamp[ZoneNumber].ValuePWM--;
         _delay_ms(50);
      }
      SaveEEPROM();
   }
}

int main(void)
{
   cli();
   LoadingEEPROM();
   init_io();
   BtnInit();
   init_int0();
   init_pwm();
   sei();
    while(1)
    {
      BtnUpdate();
   }
   return 0;
}


Если кому интересно для чего писался этот код , то ловите ссылочку.
viewtopic.php?f=11&t=148259&p=3213287#p3213287

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пн окт 23, 2017 14:25:27 
Грызет канифоль

Карма: 9
Рейтинг сообщений: 80
Зарегистрирован: Чт ноя 06, 2014 13:09:06
Сообщений: 251
Рейтинг сообщения: 1
Код:
void BtnUpdate(void)
{
................................
................................
      ZoneNumber++;
// !!!! здесь может вызваться обработчик INT0_vect??? Если да, то внимательно посмотрите, что произойдет!!!!
      if (ZoneNumber==6)
      {
         ZoneNumber=0;
      }
..............................................
..............................................
}


Последний раз редактировалось viiv Пн окт 23, 2017 17:07:05, всего редактировалось 3 раз(а).

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пн окт 23, 2017 16:32:38 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Уважаемый viiv, я конечно еще не знаю всех тонкостей программирование мк. Но может все таки дадите более развернутый комментарий.

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пн окт 23, 2017 17:02:48 
Грызет канифоль

Карма: 9
Рейтинг сообщений: 80
Зарегистрирован: Чт ноя 06, 2014 13:09:06
Сообщений: 251
Рейтинг сообщения: 0
Обработчик прерываний асинхронный? т.е. может прервать программу в любом месте? Тогда посмотрите внимательно, что будет, если обработчик вызовится там, где у меня комментарий (при вызове обработчика ZoneNumber равняется 6).

2)
unsigned char count = 0; // используется только в WriteSeg() - нет причин делать данную переменную глобальной; Ограничте видимость функцией WriteSeg().
Это не единственное, "видимость" чего желательно ограничить.

3)
Конечно реализация плавного запуска желает желать лучшего, но она все же справляется со своими задачами.


Сколько времени Вы не выходите из обработчика? Вызов _delay_ms () в обработчике мне "глаза режет". :-)

4) float - применен неоправдано. Зачем нужен float?

5)
Цитата:
if ((BtnMask == BTN_SHRT_DN)& (ConfigLamp[ZoneNumber].ValuePWM > 0)&(ConfigLamp[ZoneNumber].FlagPower==1))

Warning-ов нет??? '&' и '&&' - это разные вещи.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пн окт 23, 2017 17:14:18 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Насчет _delay_ms () знаю что не комильфо, но тот цикл используется всего лишь один раз при включении а более элегантного решения в голову не пришло (.
Насчет всего остального спасибо еще немного покопаюсь в этом коде.
А насчет 5того пункта компилятор не выдавал Warningов , хотя согласен логическое И правильней писать &&, странно что эти условия еще и работали.

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Пн окт 23, 2017 17:52:39 
Грызет канифоль

Карма: 9
Рейтинг сообщений: 80
Зарегистрирован: Чт ноя 06, 2014 13:09:06
Сообщений: 251
Рейтинг сообщения: 0
Код:
if (ZoneNumber==6)


У Вас же есть специальная константа для этого (CONFIG_AMOUNT). Нет причин ее здесь не использовать - потенциальная причина ошибок.

Таких мест не одно.
Код:
while ((!(PINB&0b10000000))& (ConfigLamp[ZoneNumber].ValuePWM < 99))

BTN_PIN и BTN_LINE_UP - вроде для того и определили, чтобы в данном случае не PINB и 0b10000000 написАть, а что-то более понятное.

Ну и я бы, написал
Код:
if (ZoneNumber >= CONFIG_AMOUNT)
Т.е. по тексту сразу видно, что проверяется выход за переделы диапазона. А сравнение с константой на равенство, на мой взгляд, менее информативно :-)

ЗЫ. Логику не смотрел вообще. Но например, логика опроса кнопок станная.
Код:
#define BTN_SHRT_UP         (1<<0)         /*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN         (1<<1)         /*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER      (1<<2)         /*бит короткого нажатия кнопки POWER */
#define BTN_SHRT_SW         (1<<3)         /*бит короткого нажатия кнопки SW*/
#define BTN_LONG_UP         (1<<4)         /*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN         (1<<5)         /*бит длинного нажатия кнопки dn*/
#define BTN_LONG_SW         (1<<6)         /*бит короткого нажатия кнопки SW*/


Могут одновревенно стоять носколько бит? Если да, то (BtnMask == BTN_SHRT_UP) - неверно. Если нет, то и незачем определять, как маску - это сильно запутывет.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: EEPROM запись в цикле.
СообщениеДобавлено: Вт окт 24, 2017 02:07:53 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Спасибо за более конструктивную критику у себя внес некоторые изменения.

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 36 ]    , 2

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: Engineer_Keen и гости: 16


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y