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
                     

Построение оптимального преобразователя мощности

Управляющие контроллеры, драйверы и МОП-транзисторы являются важнейшими элементами для инверторов и импульсных источников питания. Проектирование современных импульсных преобразователей, таких как импульсные источники питания (SMPS), DC/DC-преобразователи, приводы промышленных двигателей и инверторы солнечных батарей, необходимо выполнять с учетом целого ряда факторов. Существуют коммерческие, законодательные и экологические требования, направленные на повышение эффективности, снижение потерь, уменьшение эксплуатационных расходов, минимизацию потребления энергии. Кроме того, пользователи хотят видеть постоянное повышение эффективности без какого-либо увеличения габаритов и необходимости принятия дополнительных мер для защиты как элементов схемы, так и самих пользователей.

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

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  

  • Сообщения

    • возможно - у меня мало опыта - но как понял они слабое звено в цепи - может ошибаюсь - с учетом не большого опыта - чем лучше сделать условия работы ключей - меньше проблем - в схеме на ир2153 - я применил - с подсказки Сергея диоды на разряд - резисторы между затвором -истоком - результат - практически не греются и даже радиатор на них не ставил - здесь ес все в конечном итоге выйдет с основной схемой шим и зашитой- норм - что предложил - почему-бы не сделать работу ключей более комфортной.имхо
    • Много раз видел такие сообщения от других, про доп диоды, но не разу не встречал пробитые диоды у собственных транзисторов и никогда доп диоды не ставил и в сварочниках да же не видел такого, так что это миф о доп диодах)
    • Клиенту безграмотному я начну с 10-20 у.е. за страницу текста А4 .... и никак иначе ... А пока тебе ответят КНИГИ и ГУГЛЬ, которые ты даже не открывал, но возомнил себя супер-пупер программером, который безотказен для друзей .... Я таких всегда спрашиваю - А если друг уже без девочки пол-года и попросит тебя .... Тоже "возмешь" - ся
    • Делать линейный блок питания с такими характеристиками на микросхемах затруднительно. Слишком уж большие напряжения. Поэтому проще нарисовать схему на дискретных элементах. Расчетные параметры следующие. Выходное напряжение от 13в до 34в и выше. Устанавливается R17R18. Номинальное сопротивление нагрузки 14,45ом. Выходной ток номинальный 2,35А. Выходной ток в режиме ограничения не менее 3,0А. Задается R8. Выходной ток короткого замыкания около 0,2А. Порог распознавания напряжения короткого замыкания не менее 2 вольт. Задается резистором R9. Порог распознавания сопротивления короткого замыкания не менее 1,5ом. Задается резистором R9. Размах пульсаций выходного напряжения от пика до пика около 95мкв. Просадка напряжения при изменении выходного тока от 0А до 2,35А около 1,8мв. Выходное сопротивление около 0,00077ом или 0,77мОм. При изменении входного напряжения от 41в до 91в выходное напряжение изменяется примерно на 6мв (коэффициент стабилизации по напряжению около 4396). Температурный дрейф выходного напряжения около минус 2мв/°C. Минимальное статическое падение напряжения между входом и выходом 3,1в. Минимальное динамическое падение напряжения между входом и выходом 2,14в. 00_Bp_30v_80w_Расчетная_модель.pdf BP_34V_80W_Оригиналы_рисунков.zip    
    • @rocker60 , где и кто тут говорил про деление уровня сигнала с генератора?
    • спасибо, но ведь у вас источник 12 вольт, будет эта схема работать на 5 вольтах?
    • Я не знаю, как кто, я подаю на вход сигнал без всяких делителей! Зачем сигнал 250 mV делить на 10. На универсальный вход поступит 25 mV.  Во всех инструкциях и Service Manual как на отечественные, так и на импортные УНЧ и ресиверы вход AUX -250 mV. При таком уровне сигнала и надо проверять УНЧ. Грамотная проверка сигналом прямоугольной формы описана выше
×
×
  • Create New...