Jump to content
Sign in to follow this  
-=FISHER=-

Запись "заводских" настроек в EEPROM AtMega8

Recommended Posts

Приветствую всех!

 

Меня интересует вопрос, как правильно записать первоначальные, так сказать "заводские" настройки в EEPROM ? Имею массив структур из двух элементов, каждый из которых хранит в себе информацию о параметрах работы одного из каналов OC1A и OC1B, но не суть. Записываю и читаю данные вот таким способом:

ch chanel[CHANELS_COUNT]; //массив структур для двух каналов

ch EEMEM chanel_ee[CHANELS_COUNT]; //массив структур для двух каналов в EEPROM

//********************************************************************************

eeprom_update_block (&chanel, &chanel_ee, sizeof(chanel)); //запись структуры в EEPROM
	
eeprom_read_block (&chanel, &chanel_ee, sizeof(chanel)); //чтение структуры из EEPROM

Я пробовал так: сначала записываю в коде все исходные параметры в переменные ОЗУ, потом пишу строчку записи структуры из ОЗУ в EEPROM, затем прошиваю МК, запускаю. Все значения попадают в память. Далее убираю из прошивки строчки с записью и оставляю только строчки с чтением из EE (при этом в памяти все значения остаются, проверял считыванием EEPROM). Но вот только когда я запускаю МК с прошивкой без записи в EE, то значения не хотят попадать в ОЗУ!(( То есть не считываются, хотя по факту находятся там, на тех же адресах.

Подскажите пожалуйста, что делаю не так и как правильно?

Share this post


Link to post
Share on other sites

Когда вы пишите в коде так

//        массив     заводское содержимое  
EEMEM int buf[10] = {0,1,2,3,4,5,6,7,8,9};

и в опциях компилятора (в makefile) включете режим создания файла *.eep, то автоматически будет создан файл с указанным расширением, в котором будет находиться та самая "начальная" или "заводская" информация о содержимом массива, что вы и указали в инициализации. Остается этот файл (это обычный HEX с другим расширением) прошить в EEPROM при программировании МК, и все. Никаких телодвижений более не требуется.

Share this post


Link to post
Share on other sites
1 hour ago, ARV said:

Когда вы пишите в коде так

То есть обязательно заполнять данные во время инциализации, а не в main?

1 hour ago, ARV said:

Никаких телодвижений более не требуется.

А потом соответственно удалить инициализацию переменно в EEPROM? Ведь иначе наверное память при каждом включении будет заполняться "заводскими" настройками?

Оставляя только чтение из EEPROM при включении МК? 

1 hour ago, ARV said:

Когда вы пишите в коде так


//        массив     заводское содержимое  
EEMEM int buf[10] = {0,1,2,3,4,5,6,7,8,9};

А как это выглядеть для массива структур?..

Spoiler

 


typedef struct  //структура для хранения всех свойств канала
{
	unsigned char Delay_TurnOn, //задержка включения
				  Delay_ShutDown, //задержка выключения
				  Bright_Day, //яркость канала днём (при выключенных габаритах)
				  Bright_Night, //яркость канала ночью (при включенных габаритах)
				  Bright_Current, //текущая яркость
				  Bright_Target; //целевая яркость
				  
	unsigned int  Speed_Rise, //скорость розжига канала
				  Speed_Fall, //скорость затухания канала
				  Speed_Gab, //скорость для габаритов
				  Speed_Temp, //временная скорость канала
				  Speed_Target, //целевая скорость канала
				  Speed_Change; //скорость настройки яркости
} ch;

ch chanel[CHANELS_COUNT]; //массив структур для двух каналов в ОЗУ

ch EEMEM chanel_ee[CHANELS_COUNT]; //массив структур для двух каналов в ПЗУ

//***********************************************************************************

	chanel[0].Bright_Current=255; //при инициализации каналы полностью погашены
	chanel[0].Bright_Target=255; //при инициализации каналы полностью погашены
	chanel[0].Bright_Day=60; //(0-255) uint8_t установка дневной яркости 
	chanel[0].Bright_Night=230; //(0-255) uint8_t установка ночной яркости	
	chanel[0].Delay_TurnOn=1; //(0-10) uint8_t установка задержки включения
	chanel[0].Delay_ShutDown=2; //(0-10) uint8_t установка задержки выключения
	chanel[0].Speed_Rise=500; //(0-500) uint16_t  установка скорости розжига
	chanel[0].Speed_Fall=100; //(0-500) uint16_t установка скорости затухания
	chanel[0].Speed_Gab=10; //(0-100) uint8_t установка скорости изменения яркости до габаритов
	chanel[0].Speed_Change=50; //установка скорости розжига	

//********************************* ПАРАМЕТРЫ КАНАЛА 1 ***************************	
 	
	chanel[1].Bright_Current=255; //при инициализации каналы полностью погашены
	chanel[1].Bright_Target=255; //при инициализации каналы полностью погашены	
	chanel[1].Bright_Day=50; //(0-255) установка дневной яркости
	chanel[1].Bright_Night=230; //(0-255) установка ночной яркости
	chanel[1].Delay_TurnOn=4; //(0-10) установка задержки включения
	chanel[1].Delay_ShutDown=2; //(0-10) установка задержки выключения	
	chanel[1].Speed_Rise=500; //(0-500) установка скорости розжига
	chanel[1].Speed_Fall=100; //(0-500) установка скорости затухания
	chanel[1].Speed_Gab=10; //(0-100) установка скорости затухания	
	chanel[1].Speed_Change=50; //установка скорости затухания

 

Share this post


Link to post
Share on other sites

Вебинар STM32G0 – новый лидер бюджетных 32-битных микроконтроллеров от STMicroelectronics

Компания Компэл приглашает вас 25 сентября принять участие в вебинаре, который посвящен новому семейству микроконтроллеров STM32G0. Вебинар рассчитан на технических специалистов и тех, кто хорошо знаком с семейством STM32. На вебинаре будут освоены современные методы тестирования производительности микроконтроллеров на примере самых бюджетных 32-битных семейств общего назначения STM32G0 и STM32F0 и проведено их подробное сравнение.

Подробнее

Я использую Atmel Studio 7, и после компиляции, даже без изменения настроек создается файл с расширением *.eep

Share this post


Link to post
Share on other sites
Just now, -=FISHER=- said:

То есть обязательно заполнять данные во время инциализации, а не в main?

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

Just now, -=FISHER=- said:

А потом соответственно удалить инициализацию переменно в EEPROM? Ведь иначе наверное память при каждом включении будет заполняться "заводскими" настройками?

Память не будет никак заполняться, потому как инициализирующая часть попадает только в файл *.eep и никак не влияет на остальное. Если вы не прошьете этот файл в EEPROM, то в main не увидите никаких данных из этого массива.

Just now, -=FISHER=- said:

А как это выглядеть для массива структур?..

Точно так же, как всегда. Существует 2 способа проинициализировать структуру:

1. указать список значений в фигурных скобках

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

Соответственно для массива с структур будет список списков :)

typedef struct  //структура для хранения всех свойств канала
{
	unsigned char Delay_TurnOn, //задержка включения
				  Delay_ShutDown, //задержка выключения
				  Bright_Day, //яркость канала днём (при выключенных габаритах)
				  Bright_Night, //яркость канала ночью (при включенных габаритах)
				  Bright_Current, //текущая яркость
				  Bright_Target; //целевая яркость
				  
	unsigned int  Speed_Rise, //скорость розжига канала
				  Speed_Fall, //скорость затухания канала
				  Speed_Gab, //скорость для габаритов
				  Speed_Temp, //временная скорость канала
				  Speed_Target, //целевая скорость канала
				  Speed_Change; //скорость настройки яркости
} ch;
// в структуре всего 12 полей, поэтому можно проинициализировать структуру так:
ch my_struct = {1,2,3,4,5,6,7,8,9,10,11,12};
// при этом надо указывать значения только последовательно по порядку. если указать меньше 12 полей - остальные будут инициализированы нулями
ch my_struct1 = {1,2,3}; // и будет warning

// но более правильно инициализировать поля "поименно", в этом случае можно указывать их в любом порядке, а неуказанные будут обнулены
ch my_struct2 = {.Speed_Target = 10, .Bright_Current = 12};

 

Share this post


Link to post
Share on other sites
                     

Литиевые батарейки Fanso в беспроводных датчиках пожарно-охранной сигнализации

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

Подробнее...

2 hours ago, ARV said:

Соответственно для массива с структур будет список списков

Спасибо большое!

2 hours ago, ARV said:

Точно так же, как всегда.

Соответственно, если это массив из двух экземпляров структур, то перечисляем сначала значения 0-го элемента массива, затем первого?

typedef struct  //структура для хранения всех свойств канала
{
	unsigned char Delay_TurnOn, //задержка включения
				  Delay_ShutDown, //задержка выключения
				  Bright_Day, //яркость канала днём (при выключенных габаритах)
				  Bright_Night, //яркость канала ночью (при включенных габаритах)
				  Bright_Current, //текущая яркость
				  Bright_Target; //целевая яркость
				  
	unsigned int  Speed_Rise, //скорость розжига канала
				  Speed_Fall, //скорость затухания канала
				  Speed_Gab, //скорость для габаритов
				  Speed_Temp, //временная скорость канала
				  Speed_Target, //целевая скорость канала
				  Speed_Change; //скорость настройки яркости
} ch;
// в структуре всего 12 полей, поэтому можно проинициализировать структуру так:
ch my_struct[2] = {1,2,3,4,5,6,7,8,9,10,11,12,
                   1,2,3,4,5,6,7,8,9,10,11,12};

 

Share this post


Link to post
Share on other sites
Posted (edited)

Каждая структура должна быть в своих скобках.

Массив = {}

Структура = {}

Массив структур = {{},{},{}...}

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

Edited by ARV

Share this post


Link to post
Share on other sites

@ARV а уже в самой программе оставляю вот такую строку для чтения из EEPROM-массива структур в RAM-массива структур?

eeprom_read_block (&chanel, &chanel_ee, sizeof(chanel));

 

@ARV Заработало!!! Огромное спасибо!!!

Share this post


Link to post
Share on other sites

Да массив и структура - это одно и тоже. Только структуру надо выравнивать (компиляторы разные бывают). А если создать массив структур, то по полям структур можно "скользить" с помощью указателя также, как и по элементам массива.

Share this post


Link to post
Share on other sites

Подскажите ещё пожалуйста, правильно ли я описал включение ножек PB1 и PB2 на выход?

//Пины выходов
#define PIN_CH0OUT _BV(PB1) //выход ШИМ 0-го канала
#define PIN_CH1OUT _BV(PB2) //выход ШИМ 1-го канала

#define OUT_PINS (PIN_CH0OUT|PIN_CH1OUT) //маскируем
  
void port_ini(void)
{
	PORTD|=OUT_PINS; //включаем подтягивающие резисторы на PB1 и PB2
}

 

Share this post


Link to post
Share on other sites

Направление вход-выход задается регистром DDRD

Share this post


Link to post
Share on other sites
Posted (edited)
1 hour ago, ARV said:

задается регистром DDRD

Опечатался немного

//Пины выходов
#define PIN_CH0OUT _BV(PB1) //выход ШИМ 0-го канала
#define PIN_CH1OUT _BV(PB2) //выход ШИМ 1-го канала

#define OUT_PINS (PIN_CH0OUT|PIN_CH1OUT) //маскируем
  
void port_ini(void)
{
	DDRD|=OUT_PINS; //включаем ножки PB1 и 2 на выход
}

Но в остальном верно?

Edited by -=FISHER=-

Share this post


Link to post
Share on other sites

а комментарий

//включаем подтягивающие резисторы на PB1 и PB2

это к  чему?

Share this post


Link to post
Share on other sites

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

1. Имеется две кнопки, одна для 1-го канала, другая для 2-го;

(Далее пример реакций на нажатие для одной кнопки, для второй всё аналогично, только номер канала меняется).

2. Нажимая на кнопку первый раз и удерживая, начинает расти яркость канала;

3. Отпустив кнопку и нажав её повторно и удерживая начинает уменьшаться яркость канала;

4. Если яркость упрется в 0 или 255, канал начинает моргать, показывая что достигнуто критическое значение;

5. Есть режим яркости для выключенных габаритов и для включенных, какой из них включен на данный момент, определяется по содержанию переменной button_state, которое может равняться 1 или 0.

@ARV Было бы интересно услышать Ваш подход с методами нисходящего программирования.

Share this post


Link to post
Share on other sites

Нисходящее программирование на данном этапе не при чём :) оно не для обдумывания, а для реализации обдуманного.

В чем, собственно, у вас проблема? Алгоритм редактирования яркости при помощи кнопок вы описали вполне понятно. Если проблема в реализации мигания для "упора", то оно делается элементарно путем накладывания "маски" на яркость по таймеру. Когда уперлись в край, активируете таймер при нажатой кнопке (а при отжатой - деактивируете). Таймер этот при срабатывании XOR-ит текущую яркость с 0xFF и с 0x00 поочередно каждый свой тик, что в итоге дает нужное вам мерцание.

Share this post


Link to post
Share on other sites
1 hour ago, ARV said:

В чем, собственно, у вас проблема?

У меня просто в голове крутится конструкция с множеством IF-ELSE, мне почему-то кажется это неправильным. Я вечером распишу как я это представляю и скину сюда.

 

Share this post


Link to post
Share on other sites

Я не спрашивал про то, что крутится в голове - это у вас крутится вариант РЕШЕНИЯ проблемы. Я спрашивал о самой проблеме - в чем она заключается? Что решать-то надо?

Share this post


Link to post
Share on other sites
4 hours ago, ARV said:

Что решать-то надо?

Нужно распутать клубок if-else...

Вот смотрите, прежде чем изменить яркость мне нужно проверить аж 4 параметра, это всё у меня получаются вложенные if-else. Допустим я отловил нажатие первой кнопки (пример для 0-го канала):

1. Разрешено ли изменение яркости? (То есть "протикал" ли таймер нужный отрезок времени чтобы яркость плавно изменялась, а не мгновенно);

2. Какое направление изменения яркости (наращивать или убавлять яркость?);

3. Включены габариты или нет? (Чтобы понимать дневной или ночной параметр мы регулируем) (input_state == GAB_ON) или (input_state == GAB_OFF);

4. Яркость уже достигла минимума или максимума? (Чтобы морганием сигнализировать о достижении предела).

И только потом будет ясно, какой из вариантов действий выбрать:

chanel[0].BrightDay++;

chanel[0].BrightDay--;

chanel[0].BrightNight++;

chanel[0].BrightNight--;

Share this post


Link to post
Share on other sites
Posted (edited)

Не знаю, что у вас за клубок...

Вопросы изменения яркости человеком и её фактическая "отработка" контроллером - две не связанные ветки. Человек меняет яркость не когда разрешено, а когда хочет, а уж МК отрабатывает это "плавно" или как-то иначе. Поэтому в обработке кнопок никаких проверок "можно или нет"не требуется - можно всегда.

Далее, направление изменения у вас всегда меняется на противоположное в момент отпускания кнопки - так? Ну так запоминайте его и не надо анализировать - оно всегда будет тем, какое надо.

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

Edited by ARV

Share this post


Link to post
Share on other sites
1 hour ago, ARV said:

Далее, направление изменения у вас всегда меняется на противоположное в момент отпускания кнопки - так?

Да, именно так и планировал, но вот дальше.

1 hour ago, ARV said:

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

А если я не буду его анализировать явно, типа: if(dir==0){прибавляем яркость;} if(dir==1){убавляем яркость}

То как же МК поймет когда прибавлять, а когда убавлять?...

1 hour ago, ARV said:

И только достижение "края" есть смысл отслеживать постоянно. Поскольку процесс изменения одинаков для всех 4-х яркостей, есть смысл делать это при помощи функции, получающей указатель на нужную яркость

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

1 hour ago, ARV said:

Вопросы изменения яркости человеком и её фактическая "отработка" контроллером - две не связанные ветки.

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

@ARV Спасибо что отвечаете:)

Share this post


Link to post
Share on other sites
4 minutes ago, -=FISHER=- said:

То как же МК поймет когда прибавлять, а когда убавлять?...

Слыхали про такое - число со знаком? ;) 

int direction;

bright += direction;

Если direction = 1, то яркость увеличится, если direction = -1, то уменьшится.

8 minutes ago, -=FISHER=- said:

нужно как бы разрешение (наверное это не самый рациональный подход, но концепция ведь верная?) на изменение яркости, которое будет выдаваться, предположим, каждые 100 мс.

Если информация о нажатии кнопки будет поступать каждые 100 мс, то никаких разрешений не потребуется.

Share this post


Link to post
Share on other sites
1 hour ago, ARV said:

Если direction = 1, то яркость увеличится, если direction = -1, то уменьшится.

Это гениально!))

1 hour ago, ARV said:

Если информация о нажатии кнопки будет поступать каждые 100 мс, то никаких разрешений не потребуется.

То есть достаточно просто опрашивать кнопку раз в 100 мс ?? Это проще чем я думал! Значит опрос кнопки нужно проводить в прерывании таймера, откалиброванным на 100 мс.

1 hour ago, ARV said:

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

А можете рассказать, хотя бы в общих чертах, что имеется ввиду под хитрым способом с Вашей колокольни?

Share this post


Link to post
Share on other sites
Posted (edited)

Моя колокольня в том, что я, не зная общей архитектуры вашей программы, все неизвестное сразу представляю, как будто я его сам сделал. Ну типа как в том анекдоте "я три дня не ел - ну, так нельзя, надо себя заставлять". И мои советы могут быть, мягко говоря, не в струю.

Edited by ARV

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Сообщения

    • И что теперь, в крестный ход? 
    • Так зависит звучание от типа конденсатора, или нет? Ты уж определись, если что...
    • Большой ток тут не нужен, ws2812 в среднем до 5 А кушать будут при такой длине ленты, если в карман то вообще без разницы какого формата акумы, но 5 Вольт сложнее на акумах собрать, WS2811 проще питать 3 литиевых сосиски 18650 и все... контроллер хоть готовый (но при съемке видео будут мерцать, там шим низкочастотный) хоть на ардуино (тут и частота шим сам какую поставишь и акселерометр можно прикрутить для динамической подсветки и управление с телефона по BT) по сути прикрепить ленту и разъем возле ботинка, провода выбрать гибкие, завить спиралькой, а управление и питание из кармана
    • А если попробовать поменять их местами, перекинув на другой канал? Если дело в них - симптомы появятся же на здоровом канале?
    • Да.   Ясно, мужчина. В смысле вектор ваших мыслей становится понятен.
    • Lexter, спасибо. А можно прям именно то реле, которое подойдет? извините за "непрофессиональные" вопросы, как я уже говорил, что далек от электроники. Но спаять и проверить смогу)
    • Едридмадрид, - как в воду глядел!    Макет неплохо работал и козу легко переносил, собирался  поддать побольше ПОС по напряжению для устойчивой работы на ХХ, и тут на тебе – отстрел транзистора. Причём выключалка надёжно функционировала, осциллограмму удалось сохранить. Пока считаю, произошло это из-за увеличения базового тока (ПОС по напряжению тока добавила), а значит и роста реверсивного базового тока при резком запирании. А вот это уже прямая дорожка ко вторичному пробою, - классика жанра, однако – торопиться надо с умом.  Так штаа - эмиттерная коммутация рулит.  Спасибо, буду много думать. На картинке ещё один финт улучшающий работу защёлки. Захлопывающий защёлку сигнал снимается с балластного дросселя (Ladd) в цепи первички силового транса. Всё равно он крайне желателен при использовании биполяров, а просунуть через него проводочек несложно. На картинке старт на козу. Принцип работы этого узла отражен в названии модели, модельку прикрепил. di по dt.rar
×
×
  • Create New...