Eeprom ошибка доступа

Часто спрашивают по настройке vag eeprom programmer и почему не работает.
Самая распространенная проблема при попытке считать приборку — No ECU Found (не найден блок управления):

Запчасти на фото: 030405, 090408. Фото в бортжурнале Volkswagen Golf Mk4

No ECU found

Самые распространенные причины этой ошибки: не установленный VCP драйвер, не настроенный VCP драйвер или не настроенная программа vag eeprom programmer… на этих причина и сделан «упор» в данной записи.

Делюсь опытом и постараюсь описать ключевые моменты (выделяю жирным) связанные с настройкой программы и драйвера под неё.
000. Программа vag eeprom programmer подходит для считывания eeprom (дампа) приборок и блоков подушек машин: Golf Mk4, Octavia A4 (Tour, SuperB 1)/Fabia Mk1, Passat B5/B5+, Audi A2/A3/A4 B5, Seat Leon Mk1 и тому подобных авто 97-2003 годов выпуска.
Не подходит для Golf Mk5/6/7, Passat B6/7, Skoda A5/Roomster/Fabia mk2 и в целом новых авто начиная примерно с 2004 года! Если есть вопрос как узнать пин на Golf 5 — Вам сюда.
0. Очень желательно, чтобы ОС на компьютере была Win7 или WinXP. В Win10 шнурок глючит, читает через раз или вообще отказывается работать. Как правильно настроить работу программы в Win10 мне не известно!
1. Для считывания/записи прошивок с помощью vag eeprom programmer подходит любой KKL кабель (кабель работающий через K-линию), например: vagcom 409 kkl, vag k+can commander 1.4 (речь идет именно о кабеле!) c USB разъемом.
Кабели типа vcds/Вася 10.6, 11.11, 12.12, 18.9 и тп — не подходят для считывания/записи прошивок приборок!

2. Скачиваем программу VAG epprom programmer 1.19g (именно версию 1.19G, т.к. только эта версия научилась работать через VCP драйвер) из интернета (например отсюда yadi.sk/d/WTtZgj7oPGFpW) и устанавливаем её.

3. Устанавливаем подходящий VCP драйвер под ваш KKL кабель. Т.к. KKL кабель может быть сделан на разных чипах (FTDI или ft232., ch34x, …), то рекомендую просто разобрать кабель и посмотреть тип чипа именно в вашем кабеле (достаточно открутить 4 винта). Если вы ещё не купили кабель, то лучше брать с чипом FTDI (ft232.)!
В зависимости от типа чипа в кабеле ставим под него VCP драйвер. Что такое VCP драйвер? Это драйвер USB устройства, которое вы втыкаете в комп, симулирующий работу этого устройства на виртуальный COM-порт (надеюсь понятно)).
Подробнее про установку и обновление драйвера (процедура очень схожа) в Win 7:
A) Находим в интернете VCP драйвер под ваш чип.
Под чип FTDI (ft232.) идем сюда:
www.ftdichip.com/Drivers/VCP.htm
В таблице: Currently Supported VCP Drivers
Находим под нужную операционку и скачиваем (Например строка Windows и колонка x86(32-bit).
Под чип ch34x советую брать драйвер с сайта производителя чипа ch340/ch341: www.wch.cn/download/CH341SER_ZIP.html или www.wch-ic.com/downloads/CH341SER_ZIP.html На данный момент последняя версия драйвера под ch34x 3.5. от 05/03/2019.

Распаковываем скачанный архив (или запускаем exe файл для распаковки) в определенную папку. У меня например это «C:\VCP\». Запоминаем путь к этой папке!
B) Подключаем KKL кабель в USB разъем компа и запоминаем в какой именно USB разъем его воткнули! Настройка USB устройства делается под определенный USB разъем, поэтому подключать кабель нужно к одному разъему.
Заходим в Диспетчер устройств Win 7:
Start — Правой кнопкой мыши на Computer (Компьютер) — Выбираем Device Manager (Диспетчер устройств):
При подключении кабеля в разделе Ports (COM&LPT) появится новая строка, если драйвер уже установлен
Если драйвер не установлен — появится строка в неизвестных устройствах.
Жмем правую клавишу на этом новом устройстве (для обновления драйвера жмем на существующем в разделе Pors (Com&LPT) — Порты:
Клик по Update Driver Software (Обновить драйвер устройства):

Фото в бортжурнале Volkswagen Golf Mk4

В следующем окне выбираем Browse my computer for driver software (Указать путь к драйверу вручную):

Фото в бортжурнале Volkswagen Golf Mk4

В появившемся окне указываем путь куда распаковали файлы (см. выше в разделе A) VCP драйвера.

Фото в бортжурнале Volkswagen Golf Mk4

в моем случае это C:\VCP\

Дожидаемся установки (обновления) драйвера и кликаем OK в конце:

Фото в бортжурнале Volkswagen Golf Mk4

in progress

Установка (обновление) VCP драйвера завершена, теперь его надо настроить.

Фото в бортжурнале Volkswagen Golf Mk4

Вкладка Driver где видно какой драйвер установлен.

С) Настройка VCP драйвера:
Заходим в Диспетчер устройств, в разделе Pors (Com&LPT) — Порты находим что-то типа:
USB Serial Port (COM23) — кликаем дважды на нем и открываем вторую вкладку Port Settings (Настройки порта):

Фото в бортжурнале Volkswagen Golf Mk4

Жмем кнопку Advanced… (Дополнительно…) и попадаем в расширенные настройки, где нужно обязательно выбрать виртуальный COM-порт №1 или №2 (Com1 или Com2)! На других виртуальных com-портах программа vag eerpom programmer — не работает.

Фото в бортжурнале Volkswagen Golf Mk4

у меня вот такие проверенные настройки с которыми работает vag eeprom programmer

4. Настройки в vag eeprom programmer:
Для правильной работы нужно зайти в Options и выбрать USB (у некоторых работает на том Com-порте на который настроен VCP драйвер).

Запчасти на фото: 030405. Фото в бортжурнале Volkswagen Golf Mk4

Запчасти на фото: 030405

Собственно на этом настройки закончены и считывание прошивки (дампа) приборки должно проходить как описано в разделе 4.a) в записи про установку приборки W8

5. Отмечу ещё несколько моментов:
— Если программа при считывании прошивки приборки Motometer/Bosch ругается EEprom area blocked, can’t read it… то это не значит, что приборка заблокирована!

Фото в бортжурнале Volkswagen Golf Mk4

Происходит данная ошибка из-за отсутствия доступа vag eeprom programmer к файлу (или его созданию) C:\mm.dat в который записывается история считанных кодов доступа к приборкам Motometer/Bosch.
Решение этой проблемы — запустите vag eeprom programmer с правами доступа к файлу C:\mm.dat или просто от имени Администратора (владеющего всеми правами).

— при считывании 920-х приборок Motometer/Bosch иммо 2 (как вы знаете это может занять пару часов) частенько программа вылетает с ошибкой Tx Checksum Error (или другой похожей), не торопитесь закрывать это окно и сделайте следующее для продолжения поиска кода доступа к приборке:
1. Отодвигаем Окно с ошибкой Tx Checksum Error в сторону, чтобы было видно окно Reading EEPROM…
2. В окне Reading EEPROM находим код доступа к приборке (не путать с логином!) после слов Testing code: 0xNNNN и записываем его! Закрываем окно с ошибкой.
3. Заходим в меню File и выбираем пункт Motometr/Bosch Startcode 0x0000
4. Вводим четыре символа из пункта 2 выше и жмем Set Value.
5. Даем команду на считывание дампа приборки.

Запчасти на фото: 1J0920805, 1J0920926A, 030405, SA9856, 630303, 030333. Фото в бортжурнале Volkswagen Golf Mk4

Эти действия позволят вам сохранить время и начать поиск кода доступа к приборки с того на котором прервалась процедура с ошибкой.

— при подключении KKL кабеля в диагностический разъем машины на нем должна загораться зеленая лампочка! Было уже пара случаев, что сгорел предохранитель на диагностический разъем или не так подключил на столе и попытки считать дамп получаются неудачными. )

Надеюсь кому-нибудь данная «вымученная мной» запись пригодится.
All rights are not reserved to VampireLo. 2016 )))

Часто спрашивают по настройке vag eeprom programmer и почему не работает.
Самая распространенная проблема при попытке считать приборку — No ECU Found (не найден блок управления):

Фото в бортжурнале Volkswagen Golf Mk4

No ECU found

Самые распространенные причины этой ошибки: не установленный VCP драйвер, не настроенный VCP драйвер или не настроенная программа vag eeprom programmer… на этих причина и сделан «упор» в данной записи.

Делюсь опытом и постараюсь описать ключевые моменты (выделяю жирным) связанные с настройкой программы и драйвера под неё.
000. Программа vag eeprom programmer подходит для считывания eeprom (дампа) приборок и блоков подушек машин: Golf Mk4, Octavia A4 (Tour, SuperB 1)/Fabia Mk1, Passat B5/B5+, Audi A2/A3/A4 B5, Seat Leon Mk1 и тому подобных авто 97-2003 годов выпуска.
Не подходит для Golf Mk5/6/7, Passat B6/7, Skoda A5/Roomster/Fabia mk2 и в целом новых авто начиная примерно с 2004 года! Если есть вопрос как узнать пин на Golf 5 — Вам сюда.
0. Очень желательно, чтобы ОС на компьютере была Win7 или WinXP. В Win10 шнурок глючит, читает через раз или вообще отказывается работать. Как правильно настроить работу программы в Win10 мне не известно!
1. Для считывания/записи прошивок с помощью vag eeprom programmer подходит любой KKL кабель (кабель работающий через K-линию), например: vagcom 409 kkl, vag k+can commander 1.4 (речь идет именно о кабеле!) c USB разъемом.
Кабели типа vcds/Вася 10.6, 11.11, 12.12, 18.9 и тп — не подходят для считывания/записи прошивок приборок!

2. Скачиваем программу VAG epprom programmer 1.19g (именно версию 1.19G, т.к. только эта версия научилась работать через VCP драйвер) из интернета (например отсюда yadi.sk/d/WTtZgj7oPGFpW) и устанавливаем её.

3. Устанавливаем подходящий VCP драйвер под ваш KKL кабель. Т.к. KKL кабель может быть сделан на разных чипах (FTDI или ft232., ch34x, …), то рекомендую просто разобрать кабель и посмотреть тип чипа именно в вашем кабеле (достаточно открутить 4 винта). Если вы ещё не купили кабель, то лучше брать с чипом FTDI (ft232.)!
В зависимости от типа чипа в кабеле ставим под него VCP драйвер. Что такое VCP драйвер? Это драйвер USB устройства, которое вы втыкаете в комп, симулирующий работу этого устройства на виртуальный COM-порт (надеюсь понятно)).
Подробнее про установку и обновление драйвера (процедура очень схожа) в Win 7:
A) Находим в интернете VCP драйвер под ваш чип.
Под чип FTDI (ft232.) идем сюда:
www.ftdichip.com/Drivers/VCP.htm
В таблице: Currently Supported VCP Drivers
Находим под нужную операционку и скачиваем (Например строка Windows и колонка x86(32-bit).
Под чип ch34x советую брать драйвер с сайта производителя чипа ch340/ch341: www.wch.cn/download/CH341SER_ZIP.html или www.wch-ic.com/downloads/CH341SER_ZIP.html На данный момент последняя версия драйвера под ch34x 3.5. от 05/03/2019.

Распаковываем скачанный архив (или запускаем exe файл для распаковки) в определенную папку. У меня например это «C:VCP». Запоминаем путь к этой папке!
B) Подключаем KKL кабель в USB разъем компа и запоминаем в какой именно USB разъем его воткнули! Настройка USB устройства делается под определенный USB разъем, поэтому подключать кабель нужно к одному разъему.
Заходим в Диспетчер устройств Win 7:
Start — Правой кнопкой мыши на Computer (Компьютер) — Выбираем Device Manager (Диспетчер устройств):
При подключении кабеля в разделе Ports (COM&LPT) появится новая строка, если драйвер уже установлен
Если драйвер не установлен — появится строка в неизвестных устройствах.
Жмем правую клавишу на этом новом устройстве (для обновления драйвера жмем на существующем в разделе Pors (Com&LPT) — Порты:
Клик по Update Driver Software (Обновить драйвер устройства):

Фото в бортжурнале Volkswagen Golf Mk4

В следующем окне выбираем Browse my computer for driver software (Указать путь к драйверу вручную):

Фото в бортжурнале Volkswagen Golf Mk4

В появившемся окне указываем путь куда распаковали файлы (см. выше в разделе A) VCP драйвера.

Фото в бортжурнале Volkswagen Golf Mk4

в моем случае это C:VCP

Дожидаемся установки (обновления) драйвера и кликаем OK в конце:

Фото в бортжурнале Volkswagen Golf Mk4

in progress

Установка (обновление) VCP драйвера завершена, теперь его надо настроить.

Фото в бортжурнале Volkswagen Golf Mk4

Вкладка Driver где видно какой драйвер установлен.

С) Настройка VCP драйвера:
Заходим в Диспетчер устройств, в разделе Pors (Com&LPT) — Порты находим что-то типа:
USB Serial Port (COM23) — кликаем дважды на нем и открываем вторую вкладку Port Settings (Настройки порта):

Фото в бортжурнале Volkswagen Golf Mk4

Жмем кнопку Advanced… (Дополнительно…) и попадаем в расширенные настройки, где нужно обязательно выбрать виртуальный COM-порт №1 или №2 (Com1 или Com2)! На других виртуальных com-портах программа vag eerpom programmer — не работает.

Фото в бортжурнале Volkswagen Golf Mk4

у меня вот такие проверенные настройки с которыми работает vag eeprom programmer

4. Настройки в vag eeprom programmer:
Для правильной работы нужно зайти в Options и выбрать USB (у некоторых работает на том Com-порте на который настроен VCP драйвер).

Фото в бортжурнале Volkswagen Golf Mk4

Собственно на этом настройки закончены и считывание прошивки (дампа) приборки должно проходить как описано в разделе 4.a) в записи про установку приборки W8

5. Отмечу ещё несколько моментов:
— Если программа при считывании прошивки приборки Motometer/Bosch ругается EEprom area blocked, can’t read it… то это не значит, что приборка заблокирована!

Фото в бортжурнале Volkswagen Golf Mk4

Происходит данная ошибка из-за отсутствия доступа vag eeprom programmer к файлу (или его созданию) C:mm.dat в который записывается история считанных кодов доступа к приборкам Motometer/Bosch.
Решение этой проблемы — запустите vag eeprom programmer с правами доступа к файлу C:mm.dat или просто от имени Администратора (владеющего всеми правами).

— при считывании 920-х приборок Motometer/Bosch иммо 2 (как вы знаете это может занять пару часов) частенько программа вылетает с ошибкой Tx Checksum Error (или другой похожей), не торопитесь закрывать это окно и сделайте следующее для продолжения поиска кода доступа к приборке:
1. Отодвигаем Окно с ошибкой Tx Checksum Error в сторону, чтобы было видно окно Reading EEPROM…
2. В окне Reading EEPROM находим код доступа к приборке (не путать с логином!) после слов Testing code: 0xNNNN и записываем его! Закрываем окно с ошибкой.
3. Заходим в меню File и выбираем пункт Motometr/Bosch Startcode 0x0000
4. Вводим четыре символа из пункта 2 выше и жмем Set Value.
5. Даем команду на считывание дампа приборки.

Запчасти на фото: 1J0920926A, 1J0920805. Фото в бортжурнале Volkswagen Golf Mk4

Запчасти на фото: 1J0920926A, 1J0920805

Эти действия позволят вам сохранить время и начать поиск кода доступа к приборки с того на котором прервалась процедура с ошибкой.

— при подключении KKL кабеля в диагностический разъем машины на нем должна загораться зеленая лампочка! Было уже пара случаев, что сгорел предохранитель на диагностический разъем или не так подключил на столе и попытки считать дамп получаются неудачными. )

Надеюсь кому-нибудь данная «вымученная мной» запись пригодится.
All rights are not reserved to VampireLo. 2016 )))

Often asked about the VAG EEPROM programmer setting and why it does not work.The most common problem when trying to read the tidy is No ECU Found:

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-1

The most common reasons for this error are: not installed VCP driver, not configured VCP driver or not configured vag eeprom programmer … these are the reasons that the focus is on in this entry.

I will share my experience and try to describe the key points related to setting up the program and the driver for it.

Car Models Coverage:
The vag eeprom programmer is suitable for reading the eeprom (dump) of devices and other function of cars: Golf Mk4, Octavia A4 (Tour, SuperB 1) / Fabia Mk1, Passat B5 / B5 +, Audi A2 / A3 / A4 B5, Seat Leon Mk1 and similar cars produced in 97-2003.

Not suitable for Golf Mk5 / 6/7, Passat B6 / 7, Skoda A5 / Roomster / Fabia mk2 and generally new cars from about 2004!

OS Requirements:

It is highly desirable that the OS on the computer was Win7 or WinXP.

In Win10, the lace is buggy, reads every other time or refuses to work at all.

Compatible Interface:

KKL cable (cable working through the K-line) is suitable

For example:

vagcom 409 kkl

vag k + can commander 1.4 With a USB connector.
Cables like vcds / Vasya 10.6, 11.11, 12.12, 18.9, etc. – are not suitable for reading / writing device firmware!

Download VAG EEPROM Programmer 1.19
Download the VAG epprom programmer 1.19g program (version 1.19G, because only this version learned to work through the VCP driver).

VAG EEPROM Programmer 1.19g Free Download

Install the appropriate VCP driver for your KKL cable.

Because KKL cable can be made on different chips (FTDI or ft232., Ch34x, …), then I recommend just disassembling the cable and looking at the type of chip in your cable (just unscrew 4 screws). If you have not bought a cable yet, then it is better to take with an FTDI chip (ft232.)!
Depending on the type of chip in the cable, we put a VCP driver under it.

What is a VCP driver?

This is a USB device driver that you plug into a computer that simulates the operation of this device on a virtual COM port (hopefully clear)).
More details about installing and updating the driver (the procedure is very similar) in Win 7:
A) Find a VCP driver for your chip on the Internet.
For the FTDI chip (ft232.), Go here:
www.ftdichip.com/Drivers/VCP.htm

In the table: Currently Supported VCP Drivers
We find for the required operating system and download (For example, the Windows line and the x86 column (32-bit).
For the ch34x chip, I advise you to take the driver from the site of the ch340 / ch341 chip manufacturer:

www.wch-ic.com/downloads/CH341SER_ZIP.html

At the moment, the latest driver version for ch34x 3.5. from 05/03/2019.

Unpack the downloaded archive (or run the exe file to unpack) into a specific folder. For example, I have this “C: VCP ”. We remember the path to this folder

B) We connect the KKL cable to the USB connector of the computer and remember which USB connector it was plugged into! The USB device is configured for a specific USB connector, so you need to connect the cable to one connector.
We go to the Win 7 Device Manager:
Start – Right click on Computer (Computer) – Select Device Manager (Device Manager):
When the cable is connected, a new line will appear in the Ports (COM & LPT) section if the driver is already installed
If the driver is not installed, a line will appear in unknown devices.
Press the right button on this new device (to update the driver, press on the existing one in the Pors (Com & LPT) section – Ports:
Click on Update Driver Software:

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-2

In the next window select Browse my computer for driver software (Specify the path to the driver manually):

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-3

In the window that appears, specify the path where the files were unpacked (see above in section A) of the VCP driver.

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-4

We are waiting for the driver installation (update) and click OK at the end:

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-5

Installation (update) of the VCP driver is completed, now you need to configure it.

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-6

C) VCP driver setup:
We go to the Device Manager, in the Pors (Com & LPT) – Ports section we find something like:
USB Serial Port (COM23) – double click on it and open the second tab Port Settings (Port Settings):

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-7

Click the Advanced … button and go to the advanced settings, where you must select the virtual COM port # 1 or # 2 (Com1 or Com2)! The vag eerpom programmer does not work on other virtual com ports.

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-8

Settings in vag eeprom programmer:
For proper operation, you need to go to Options and select USB (for some it works on the Com-port to which the VCP driver is configured).

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-9

Actually, this is where the settings are completed and the firmware (dump) of the tidy should be read as described in section 4.a) in the record about the installation of the W8 tidy

More points:
– If the program, when reading the firmware of the Motometer / Bosch tidy, swears EEprom area blocked, can’t read it … then this does not mean that the tidy is blocked!

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-10

This error occurs due to the lack of access by the vag eeprom programmer to the file (or its creation) C: mm.dat, which records the history of the read access codes to the Motometer / Bosch devices.
The solution to this problem is to run vag eeprom programmer with permissions to the file C: mm.dat or simply as an Administrator (who owns all rights).

– when reading 920 Motometer / Bosch immo 2 devices (as you know it can take a couple of hours), the program often crashes with a Tx Checksum Error (or another similar one), do not rush to close this window and do the following to continue searching for the access code to tidy:
1.Move the Tx Checksum Error Window aside so that the Reading EEPROM window is visible …
2.In the Reading EEPROM window, find the access code to the device (not to be confused with the login!) After the words Testing code: 0xNNNN and write it down! Close the error window.
3.Go to the File menu and select the item Motometr / Bosch Startcode 0x0000
4.Enter four characters from point 2 above and click Set Value.
5.We give the command to read the tidy dump.

How-to-Solve-VAG-EEPROM-Programmer-“No-ECU-Found”-Error-11

These actions will allow you to save time and start searching for the access code to the device from the one on which the procedure was interrupted with an error.

– when the KKL cable is connected to the diagnostic socket of the car, a green light should light up on it! There have already been a couple of cases when the fuse on the diagnostic connector has blown or it is not connected so on the table and attempts to read the dump are unsuccessful. )

(Visited 4,873 times, 4 visits today)

Доброго времени суток!

Подскажите, имеется вот такой блок подушек:

Блок управления: 1J0 909 603 A
Компонент: AIRBAG VW3 — V04
Кодировка: 00065
Мастерская #: WSC 31480
VCID: 27212C87D6E3

В ошибках крашдата и 65535

Подключаюсь кабелем USB-K-line, на столе, питание подают на кабель и на блок при помощи БП 12В 1А, дамп удалось слить нормально, только разные программы сливают разный дамп,

при помощи программы VW Airbag tool 1.0.0.1 имеются в строке 00000200 дополнительные данные.

И собственно сама проблема: при заливке дампа vag eeprom programmer заливается дамп на 3% и выдает ошибку RX-Timeout, при помощи VW AIrbag tool аналогичная ситуация, в самом начале заливки дампа выдает ошибку.

В чем может быть проблема, есть ли какие нибудь идеи по решению?

VW_AIRBAG_TOOL.BIN

VAG_EEPROM.BIN

Содержание

  1. Скачать бесплатно VAG EEPROM Programmer 1.19g
  2. Особенности программы
  3. VAG EEPROM Programmer
  4. Описание
  5. Принцип работы
  6. Основные функции
  7. VAG EEPROM Programmer 1.19g
  8. Особенности программы
  9. Программы для K-line (vag com)
  10. Тема: Как подружить адаптер USB и VAG EEPROM Programmer?

Скачать бесплатно VAG EEPROM Programmer 1.19g

1539110034 vag eeprom programmer

VAG EEPROM Programmer – это утилита для работы с автомобилями Audi, Volkswagen и другими марками концерна VAG. Программа может считывать ошибки, изменять пробег автомобиля и выполнить другие операции. Для работы необходим диагностический адаптер K-line.

VAG EEPROM Programmer предназначена для опытных пользователей, имеющих хотя бы базовые знания о «начинке» автомобиля. К тому же, интерфейс программы не переведен на русский язык. Для подключения необходим адаптер K-line и наличие COM-порта (в последней версии появилась поддержка USB).

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

Особенности программы

• Выполнение сервисных операций с автомобилями концерна VAG (Audi, Skoda и другие).
• Считывание и устранение ошибок с электронного блока управление.
• Корректировка пробега автомобидля.
• Для работы необходим адаптер K-line.
• Поддержка Windows XP и выше.

Таким образом, VAG EEPROM Programmer – это мощная программа для работы с определёнными марками автомобилей и предназначенная для опытных пользователей. Утилиту можно скачать бесплатно.

Источник

VAG EEPROM Programmer

Описание

Данное приложение поможет вам следить за пробегом и изменять его, считывать данные иммобилайзера, вычислять и обрабатывать ошибки системы SRS Airbag. Для этого необходимо иметь VAG автомобиль.

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

Принцип работы

VAG EEPROM Programmer узконаправленная программа, которая позволяет следить за аппаратными данными автомобиля и исправлять ошибки. Приложение подойдет только для опытных автомобилистов, чтобы полностью использовать все функции программы необходимо разбираться в таких вещах, как адаптер и OBD-II. Если вы понятия не имеете что это и у вас нет опыта работы с подобным ПО, то программа вам вряд ли пригодится.

Основные функции

Что может делать эта программа? Она даст вам возможность изменить пробег машины, а также считывать данные иммобилайзера. Можно обрабатывать ЭБУ ошибки и проблемы системы SRS Airbag.

Совместима программа с автомобилями, которые могут передавать данные через протокол OBD-II. К таким машинам можно отнести Audi, Seat, Skoda и Volkswagen.

Чтобы VAG EEPROM Programmer работал корректно, необходимо наличие специального адаптера. Из всех возможных вариантов, подойдут только VAG-COM, другие устройства программой не поддерживаются.

Кроме этого, для полного функционирования ПО необходимо наличие COM-порта. Без него программа будет работать не корректно.

Источник

VAG EEPROM Programmer 1.19g

468

1539110034 vag eeprom programmer

VAG EEPROM Programmer – это утилита для работы с автомобилями Audi, Volkswagen и другими марками концерна VAG. Программа может считывать ошибки, изменять пробег автомобиля и выполнить другие операции. Для работы необходим диагностический адаптер K-line.

VAG EEPROM Programmer предназначена для опытных пользователей, имеющих хотя бы базовые знания о «начинке» автомобиля. К тому же, интерфейс программы не переведен на русский язык. Для подключения необходим адаптер K-line и наличие COM-порта (в последней версии появилась поддержка USB).

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

Особенности программы

• Выполнение сервисных операций с автомобилями концерна VAG (Audi, Skoda и другие).
• Считывание и устранение ошибок с электронного блока управление.
• Корректировка пробега автомобидля.
• Для работы необходим адаптер K-line.
• Поддержка Windows XP и выше.

Таким образом, VAG EEPROM Programmer – это мощная программа для работы с определёнными марками автомобилей и предназначенная для опытных пользователей. Утилиту можно скачать бесплатно.

Источник

Программы для K-line (vag com)

Все программы имеют свободное хождение по Интернету.

932ffc2s 960

Программа предназначена для диагностики автомобилей VW, Audi, Seat, Skoda по протоколам стандарта OBD-II.
Возможности ВАСЯ диагност 1.1:
— автопоиск неисправностей;
— адаптация компонентов;
— кодирование и программирование блоков управления;
— построение графиков;
— расшифровка и удаление кодов неисправностей;
— сведения о блоках управления;
— тесты исполнителей;
— в справочнике описания 9675 кодов неисправностей;
— кодирование блоков с длинным кодированием на авто по к-линии;
— более 1000 лейблов;
— всплывающие подсказки.

Системные требования: Windows 2000, Windows XP, Windows Server 2003, Windows Vista, Windows Server 2008, Windows 7, Windows Server 2008 R2
Язык интерфейса: Русский
Работает с диагностическим адаптером: VAG COM 409.1 KKL USB, VAG-COM 409.1 COM-порт, HEX-USB+CAN
Скачать программу Вася диагност 1.1

532ffc2s 960

Язык интерфейса: Русский
Работает с диагностическим адаптером: HEX-USB+CAN
Скачать программу VCDS

37effc2s 960

Программа предназначена для диагностики автомобилей концерна VAG — VW, Audi, Seat, Skoda.
Возможности VAG Tool 2.0.9:
— чтение кодов неисправностей;
— чтение потоков данных;
— активные тесты исполнительных узлов;
— адаптация;
— запись (при наличии кодов доступа) ;
— вообщем, делает все, что делает VAG 1552.

Системные требования: 32- разрядный Windows
Язык интерфейса: Русский
Работает с диагностическим адаптером: HEX-USB+CAN
Скачать программу VAG Tool 2.0.9

732ffc2s 960

Программа предназначена для диагностики автомобилей группы VAG.
Возможности VDS-PRO:
— проверка накопленных сообщений о неисправностях;
— диагностика исполнительных устройств;
— удаление накопленных сообщений о неисправностях;
— декодирование устройства управления;
— чтение групп измеряемых величин;
— адаптация каналов.

Системные требования: Командная строка MS-DOS
Язык интерфейса: Английский
Работает с диагностическим адаптером: VAG-COM 409.1 COM-порт
Скачать программу VSD-PRO

VAG EEPROM Programmer 1.19g

f32ffc2s 960

Программа предназначена для работы с автомобилями концерна VAG. Работает через K-Line адаптер.
Возможности VAG EEPROM Programmer 1.19g:
— корреции пробега;
— чтения логина от иммобилайзера;
— сборос ошибок SRS Airbag;
— чтение и сборос кодов ошибок.

Таблетка: Присутствует
Язык интерфейса: Английский
Работает с диагностическим адаптером: VAG COM 409.1 KKL USB, VAG-COM 409.1 COM-порт
Скачать программу VAG EEPROM Programmer 1.19g

VAG K+CAN Commander 1.4 и 2.5

cb2ffc2s 960

VAG K+CAN Commander VAG K+CAN Commander используется для корректировки одометров, чтения кодов защиты блоков(Security Access) автомобиля, сброса ошибок airbag, активации функции просмотра ТВ в движении(VIM) на автомобилях группы VAG.

Возможности VAG K+CAN Commander:
— выполнение всех основных функций диагностики: идентификация, кодирование, чтение/стирание ошибок, адаптация и т.д
— корректировка одометров ( CAN / K line)
— чтение Security Access Code/Login WFS.
— чтение/запись данных иммобилайзера.
— чтение/запись EEPROM панели инструментов/иммобилайзера
— активация функции просмотра видео в движении
— чтение/запись EEPROM блоков управления BOSCH VAG-EDC15x, VAG-ME7.1.1, VAG-Cartronic ME7.8, Porsche
— прописывание ключей (security code не требуется).
— прописывание ключей Porsche CAYENNE (security code не требуется) K+CAN
— чтение flash памяти EDC16x, EDC15x, ME7x, MED951, MED751
— стирание ошибок «crash data memory» в AirBag

Язык интерфейса: Английский
Работает с диагностическим адаптером: VAG COM 409.1 KKL USB, VAG-COM 409.1 COM-порт, VAG K+CAN
Скачать программу VAG K+CAN Commander 1.4
Скачать программу VAG K+CAN Commander 2.5

VAG Tacho USB 3.01 + Opel Immo

9b06422s 960

VAG Tacho USB 3.01 + Opel Immo — этот кабель предназначен для изменения пробега, считывания логина и EEPROM на автомобилях концерна VAG. Также позволяет считывать логин, EEPROM и прописывать ключи на автомобилях Opel.
Возможности VAG Tacho USB 3.01 + Opel Immo:
— автоопределения типа панели
— корректировка одометра
— считывания пин-кода для привязки новых транспондеров(ключей) иммобилайзера
— привязка нового транспондера(ключа) непосредственно в программе
— считывание и запись EEPROM приборной панели
— считывание идентификационных данных блока управления
— полностью рабочая функция AirBag Reset Tool
— чтение PIN из Bosch ME7.xx

Язык интерфейса: Английский
Работает с диагностическим адаптером: VAG TACHO
Скачать программу VAG Tacho USB 3.01 + Opel Immo

ELSA 5.2 VW — 04.2015

2b2ffc2s 960

ELSA (Elektronisches Service Auskunftssystem) это дилерская библиотека инструкций по устройству и ремонту различных узлов автомобиля. Здесь есть всё: начиная от справочной информации, заканчивая переборкой двигателя и процессом покраски кузова. Если быть более точным, то программа называется ElsaWin, но в общении её чаще называют просто ELSA.

Таблетка: Присутствует.
Системные требования: Windows NT4.0/2000/Xp Pro/2003/7/2008
Язык интерфейса: Многоязычный (русский присутствует)
Скачать программу ELSA 5.2

ETKA 7.3 Plus International

ab2ffc2s 960

Электронный каталог ETKA 7.3 содержит полную информацию о запасных частях и аксессуарах для автомобилей концерна VAG (VW, Seat, Skoda, AUDI), включая микроавтобусы.

Таблетка: Присутствует.
Системные требования: Windows 2000, Windows Server 2003, Windows XP, Windows Vista, Windows 7, Windows 8
Язык интерфейса: Многоязычный (русский присутствует)
Скачать программу ETKA 7.3 Plus International

Motordiag Komfort Manager Lite 1.20

4166b12s 960

Вы хотите использовать пульт ДУ для управления всеми окнами вашего автомобиля Skoda или VW?
Вы действительно хотите включить сигнализацию вы даже не знаете о?
Выбрать Motordiag Komfort Manager Lite и откройте для себя новые функции вашего автомобиля Вы не ожидали бы.
Основные функции данной программы:
— Идентификация блока комфорта
— Дверные блоки идентификации
— Окна дистанционного управления активация/деактивация
— Индикатор направления мерцание настройка и отпирание и запирание двери сигнал установить
— Программируемое автоматическое запирание замков дверей включение/выключение
Эта программа использована только в автомобилях с блоком комфорта 1C0 959 799.

Таблетка: Присутствует.
Системные требования: Windows 95, Windows 98, Windows 2000, Windows XP
Язык интерфейса: Чешский
Работает с диагностическим адаптером: VAG COM 409.1 KKL USB, VAG-COM 409.1 COM-порт
Скачать программу Motordiag Komfort Manager Lite 1.20

ODIS 3.0.0 + PostSetup 8.0.160

bc7b2das 960

ODIS Service — Offboard Diagnostic Information System Service для концерна VAG (Audi, VW, Seat, Skoda, Lamborgini, Bentley) может быть установлено на VAS 5051B, VAS 5052A, VAS 6150, VAS 6150A, VAS 6150B, VAS 6160 либо на стандартных стационарных или портативных компьютерах и использовано с VAS5054a, VAS 5055, CarDAQ-Plus, iFlash, PassThru SAE J2534.

Таблетка: Присутствует.
Системные требования: Windows 7
Язык интерфейса: Многоязычный
Работает с диагностическим адаптером: VAS 5054A
Скачать программу ODIS 3.0.0 + PostSetup 8.0.160

ab14166s 960

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

Системные требования: MS-DOS
Язык интерфейса: Испанский
Работает с диагностическим адаптером: VAG-COM 409.1 COM-порт
Скачать программу EasyCCM 0.1 Beta
Скачать программу EasyCCM 0.1 Beta (CD BOOT)

358e521s 960

Ki Helper, помощник редактирования дампов приборных панелей для 6-го и 4-го поколения VAG.

Системные требования: Windows 7…
Язык интерфейса: Русский
Скачать программу KIHelper

DashDumpEdit (Программа для переноса данных из старой приборки в новую (vdo immo2/immo3 и bosch-motometer immo3))

692d4d9s 960

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

Системные требования: Windows 7…
Язык интерфейса: Русский, Английский
Скачать программу DashDumpEdit

Источник

Тема: Как подружить адаптер USB и VAG EEPROM Programmer?

Опции темы
Поиск по теме

Pointer rankaРегистрация 05.06.2006 Адрес Украина, Киев Возраст 47 Сообщений 67

Спасибо:
Получено: 0
Отправлено: 0

Вообщем надо полдключиться софтом Vag EEPROM Programmer 1.18 для тушения лампочки AIRBAG с помощью USB-адапртера для диагностики (USB адаптер для VAGCOM). Вот по такой проблеме http://wwwboards.auto.ru/audi/1538742.html
.
Софтину VAG EEPROM Programmer запускаю, но она не находит блок управления.
Кто-нибудь подскажет почему?
Я что-то заподозрил, что не может работать или с таким адаптером, или может драйвера нужны какие.

Никак, он для сом-порта заточен и под Вин9х. [-X

Golf ranka3 1Регистрация 07.02.2009 Адрес Россия, Ростов-на-Дону Возраст 42 Сообщений 798

Спасибо:
Получено: 1
Отправлено: 7

Тоже про это читал, но не помню где.

1.1.8 может работать из под XP, чего не скажешь о 1.1.3 и 1.1.4. Адаптер нужен чистый COM.

USB не пойдёт. только СОМ.

Passat ranka4 1Регистрация 23.12.2008 Адрес Россия, Санкт-Петербург Сообщений 1,417

Спасибо:
Получено: 4
Отправлено: 3

OFF
Ром, жду замены адаптера. завтра повторный заход, теперь уже с адаптером Макса. наберу как все готово будет.

ща пойду попробую i01но Епром 1,3 кабель видит i01

отпишись обязательно. vo

f4647dbc135401f6520c13760c683028 1

Ага, там USB просих HEX кабель eusa think
Не катит..

Добавлено спустя 1 минуту 46 секунд:

там никакой старт код вбивать не надо?
Я просто ниразу не пользовался прогой этой i01
Как то хотел для страховой пробег скрутить свой чтобы износа меньше посчитал i01) Но так и не запустил.

Источник

Как прописать ключ, узнать логин ИММО, прописать второй ключ

User avatar

SamFM

Posts: 486
Joined: 31 Jul 2009, 21:15
Location: Москва
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Отлично. Хорошо, что нашлась проблема.

Самохин Фёдор
Команда Avtoadapter.ru


litesmapt

Posts: 1
Joined: 02 Jan 2012, 18:38
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby litesmapt » 03 Jan 2012, 09:23

На ford galaxy 1997г 1.9tdi
связка VAG Tacho 3.01 + VAG-COM 10.6 подойдет? спасибо.


User avatar

LittleTOXA

Posts: 1409
Joined: 23 Apr 2009, 00:09
Location: Russia, Moscow
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby LittleTOXA » 17 Jan 2012, 18:41

На ford galaxy 1997г 1.9tdi
связка VAG Tacho 3.01 + VAG-COM 10.6 подойдет? спасибо.

VAG-COM имеет шанс работать, Тахо не тестировали на Galaxy.

Антон Самохин
Команда AVTOадаптер.RU


alexnettesl

Posts: 1
Joined: 17 Feb 2012, 14:19
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby alexnettesl » 17 Feb 2012, 14:39

Заранее прошу прощения если такой вопрос уже был, но просмотрев FAQ не нашел нужной информации.
Ситуация следующая: есть машина vw jetta 2006 г.в. американец с одни ключем, есть болванка ключа. Вопрос что нужно для привязки, а именно какой транспондер (чип), какой шнур для вытаскивания пина. Заранее спасибо всем откликнувшимся, буду благодарен за любую полезную информацию.

Last edited by alexnettesl on 20 Feb 2012, 13:15, edited 1 time in total.


eedu

Posts: 5
Joined: 17 Feb 2012, 01:37
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby eedu » 17 Feb 2012, 23:12

Добрый день LittleTOXA.
Купили Golf4 1.6 2000 года,с одним ключиком. Хоть я и с Эстооонии, но слово халява мне также дорого как и всем :D да и по профессии я механик-руки чешутся всё самому сделать :geek: , по этому официалам платить нет желания. Благо доставка с Китая бесплатная заказал Vag-Tacho 3.01 и Vag-Com 409.1 через ебай, ну а потом наткнулся на ваш сайт и заинтересвался Вашей прогой «AVTOадаптер VAG mini».
Сам я сейчас в рейсе, вот, учу мат-часть, а приеду – так как накинусь :twisted: ! Прочитал много форумов и постов, в принципе всё понятно, но, тем не менее, возникло несколько вопросов:
1. Какую прогу посоветуете использовать (ну там ошибки посмотреть и ключик прописать) –ломаные 409 и 311 или Вашу-«AVTOадаптер VAG mini »,душа лежит к русскоязычной, но настораживает слово МИНИ ?
2.Возможно-ли будет ключ от 5 или 6 гольфов привязать к центральному замку 4го, ну а чип иммо я поменял-бы на свой- 48 (если я не ошибаюсь ID48, с того-же ебая) ?
3.Сможете-ли вы выслать мне прогу на мыло, а то на судне интернет заблокирован на скачку почти всего, но с мыла вроде зип архивы грузит. А денежку за лицензию я вам по Pay-Pal ?
Заранее спасибо.


eedu

Posts: 5
Joined: 17 Feb 2012, 01:37
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby eedu » 18 Feb 2012, 22:00

Ещё раз добрый день, поторопился я с первым и третьим вопросами :oops: а вот 2ой остаётся в силе :?: .


AndyFree

Posts: 4
Joined: 14 Mar 2012, 22:04
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby AndyFree » 14 Mar 2012, 22:46

Всем привет. Подскажите пожалуста. У меня Polo 6N2 2001года. достался он мне с одним ключом, хочу сделать второй. Нужно вытащить логин иммобилайзера. Приборка у меня как на фото.
http://www.ebay.co.uk/itm/MK5-6N2-POLO- … 27c2814605
У меня есть USB К-лаин шнурок мастеркитовский и еще сам спаял для сом порта шнурочек на 3х транзисторах то же к-лайн. Пробовал выташить логин Vag eeprom programmer 1_19. Читает eeprom выдает модель тип ееprom но в строках имобилайзера везде стоит none. Ни логина ничего. Пробовал считать имобилайзер программой VAG K+CAN COMMANDER 1.4. Идентификацию проходит но в меню instrument/immobilaizer нажимаю read и тишина ничего не происходит. Есть подозрения что имобилайзер стоит не в приборной панели и поэтому логин не читается. Живу почти в деревне возможности взять даже на время шнуры, тахо и командер, нет. Подскажите как можно еще считать логин имея мои 2 шнурка. С паялником дружу, может кто подскажет как то непосредственно с иммо логин сосчитать. Буду весьма признателен всем кто ответит.

ПыСы Приборка вроде МОТОМЕТЕР.


User avatar

LittleTOXA

Posts: 1409
Joined: 23 Apr 2009, 00:09
Location: Russia, Moscow
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby LittleTOXA » 15 Mar 2012, 00:35

Заранее прошу прощения если такой вопрос уже был, но просмотрев FAQ не нашел нужной информации.
Ситуация следующая: есть машина vw jetta 2006 г.в. американец с одни ключем, есть болванка ключа. Вопрос что нужно для привязки, а именно какой транспондер (чип), какой шнур для вытаскивания пина. Заранее спасибо всем откликнувшимся, буду благодарен за любую полезную информацию.

К+Кан коммандер скорее всего для вытаскивания ПИНа. Транспондер не скажу.
У нас есть спец штука чтобы дубликат ключа сделать (чипа иммо). Можно таким путем пойти если вычитать ПИН не удастся..

Добрый день LittleTOXA.
Купили Golf4 1.6 2000 года,с одним ключиком. Хоть я и с Эстооонии, но слово халява мне также дорого как и всем :D да и по профессии я механик-руки чешутся всё самому сделать :geek: , по этому официалам платить нет желания. Благо доставка с Китая бесплатная заказал Vag-Tacho 3.01 и Vag-Com 409.1 через ебай, ну а потом наткнулся на ваш сайт и заинтересвался Вашей прогой «AVTOадаптер VAG mini».
Сам я сейчас в рейсе, вот, учу мат-часть, а приеду – так как накинусь :twisted: ! Прочитал много форумов и постов, в принципе всё понятно, но, тем не менее, возникло несколько вопросов:
1. Какую прогу посоветуете использовать (ну там ошибки посмотреть и ключик прописать) –ломаные 409 и 311 или Вашу-«AVTOадаптер VAG mini »,душа лежит к русскоязычной, но настораживает слово МИНИ ?
2.Возможно-ли будет ключ от 5 или 6 гольфов привязать к центральному замку 4го, ну а чип иммо я поменял-бы на свой- 48 (если я не ошибаюсь ID48, с того-же ебая) ?
3.Сможете-ли вы выслать мне прогу на мыло, а то на судне интернет заблокирован на скачку почти всего, но с мыла вроде зип архивы грузит. А денежку за лицензию я вам по Pay-Pal ?
Заранее спасибо.

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

Антон Самохин
Команда AVTOадаптер.RU


User avatar

LittleTOXA

Posts: 1409
Joined: 23 Apr 2009, 00:09
Location: Russia, Moscow
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby LittleTOXA » 15 Mar 2012, 00:36

Всем привет. Подскажите пожалуста. У меня Polo 6N2 2001года. достался он мне с одним ключом, хочу сделать второй. Нужно вытащить логин иммобилайзера. Приборка у меня как на фото.
http://www.ebay.co.uk/itm/MK5-6N2-POLO- … 27c2814605
У меня есть USB К-лаин шнурок мастеркитовский и еще сам спаял для сом порта шнурочек на 3х транзисторах то же к-лайн. Пробовал выташить логин Vag eeprom programmer 1_19. Читает eeprom выдает модель тип ееprom но в строках имобилайзера везде стоит none. Ни логина ничего. Пробовал считать имобилайзер программой VAG K+CAN COMMANDER 1.4. Идентификацию проходит но в меню instrument/immobilaizer нажимаю read и тишина ничего не происходит. Есть подозрения что имобилайзер стоит не в приборной панели и поэтому логин не читается. Живу почти в деревне возможности взять даже на время шнуры, тахо и командер, нет. Подскажите как можно еще считать логин имея мои 2 шнурка. С паялником дружу, может кто подскажет как то непосредственно с иммо логин сосчитать. Буду весьма признателен всем кто ответит.

ПыСы Приборка вроде МОТОМЕТЕР.

Тут сходу не помощник, но мучать наверное ЕЕПРОМ Программер больше ..

Антон Самохин
Команда AVTOадаптер.RU


AndyFree

Posts: 4
Joined: 14 Mar 2012, 22:04
Contact:

Re: Как прописать ключ, узнать логин ИММО, прописать второй

Postby AndyFree » 15 Mar 2012, 12:37

еезкщь programmer. Читает только когда нажимаеш read eeprom в меню Dash. В других меню, ECU например, eeprom не читает выдает ошибку rx timeout. А в меню immobox, выдает ошибку что то типа, нет логина. И настроек у него никаких нет. Кстати я нашел программу Vag eeprom programmer 1_19 она работает с USB шнурами по виртуальному порту. По крайне мере у меня и с usb и с комовским шнуром работает одинаково. Скачать можно здесь.
http://narod.ru/disk/41754161001.56c329 … 9.rar.html


Who is online

Users browsing this forum: No registered users and 2 guests

Введение

   В этом материале мы рассмотрим возможные проблемы при работе с EEPROM. Часть из них связана с аппаратным стороной микроконтроллера, такие как повреждение EEPROM при пониженном напряжении питания и ограниченный ресурс EEPROM, а часть с программным обеспечением, например, при использовании EEPROM в прерываниях. Также рассмотрим способы решения этих проблем и методы повышения надежности хранения данных в EEPROM.

   Одна из старых проблем AVR — это повреждение EEPROM данных при пониженном питании микроконтроллера. Это может происходить в двух случаях:

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

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

— Нужно удерживать микроконтроллер AVR в состоянии сброса, если напряжение питания находится ниже нормы. Для этого можно использовать внешние супервизоры питания или встроенный детектор пониженного питания — Brown-out Detector (BOD). Встроенный детектор управляется с помощью fuse битов микроконтроллера — BODEN и BODLEVEL. BODEN — разрешает/запрещает работу детектора, а BODLEVEL — определяет его уровень срабатывания.
   Если сброс микроконтроллера происходит во время процесса записи в EEPROM, то операция записи будет завершена только при достаточном уровне напряжения.

— Также в многие разработчике рекомендуют не использовать 0-ую ячейку EEPROM`a, поскольку именно ее содержимое чаще всего повреждается при снижении питания микроконтроллера.

   Операция записи в EEPROM состоит из нескольких шагов. Вспомним эту последовательность:

1. Ожидаем готовности EEPROM, опрашивая бит EEWE регистра EECR.
2. Устанавливаем адрес в регистре EEAR.
3. Записываем байт данных в регистр EEDR.
4. Устанавливаем основной флаг разрешения записи EEMWE регистра EECE
5. Устанавливаем флаг разрешения записи EEWE регистра EECE

   Бит EEWE должен быть установлен в течении 4-ех тактов после установки бита EEMWE. Если этого не произойдет по причине прерываний, то запись в EEPROM не будет произведена. Этого легко избежать, если запретить прерывания перед 4-м шагом, а после 5-го снова разрешить их.

   Однако есть еще один подводный камень. Если прерывание возникло после 1-го, 2-го или 3-го шага, и в прерывании тоже используются операции с EEPROM (чтение или запись), то запись может не состояться, или запишутся не те данные и не туда, потому что содержимое регистров EEAR (адрес) и EEDR (данные) будет изменено.

   Описанное выше касается и процедуры чтения EEPROM.

   Лечить это можно следующими способами:

   — Не использовать операции чтения и записи EEPROM в прерываниях.
   Это особенно касается операции записи, потому что она медленная и выполняется с использованием внутреннего RC генератора. Например, для mega16 в даташите указано, что при записи в EEPROM используется внутренний RC генератор с частотой 1 МГц (независимо от установок fuse битов CKSEL) и время записи составляет 8.5 мс. Для прерывания это очень долго.

   — Запрещать прерывания на время всей процедуры записи (чтения) EEPROM, то есть в самом начале.

   — Сохранять в начале обработчика прерывания содержимое регистров EEAR (адрес) и EEDR (данные), а перед выходом восстанавливать их.

   — Использовать флаги (семафоры) для сигнализации о выполнении работы с EEPROM.
   Перед выполнением записи в основном цикле программы (или задаче, если используется ос) устанавливать программный флаг, а в прерывании (или другой задаче) проверять его.

   EEPROM имеет ограниченный ресурс. Atmel гарантирует, что количество циклов перезаписи EEPROM составляет не меньше 100000. Цифра довольно большая, однако и она может быть достигнута, если записывать в EEPROM часто и на протяжении долгого времени.
   Есть два приема по «увеличению» ресурса EEPROM.
   Первый — простой и состоит в том, чтобы записывать в EEPROM данные, только если они изменили свое значение.


__eeprom uint8_t data;
uint8_t newData;

...
if (newData != data) {
data = newData;
}

   Второй- хитрый и состоит в том, чтобы хранить данные не в одной ячейки памяти (или группе ячеек, если речь идет о многобайтных переменных), а в нескольких, и записывать в них по очереди.
   Допустим, нам нужно хранить в EEPROM один байт. Выделяем под него 8 байтов и каждый раз записываем в следующую ячейку, когда доходим до последней ячейки, то записываем в первую. И так по кругу, как в кольцевом буфере. Если каждая ячейка EEPROM имеет ресурс 100000, то записывая в 8 ячеек по очереди, мы получаем ресурс перезаписи байта 800000.

EEPROM и оптимизация компилятора

   Переменные, которые объявлены, но не используются, часто удаляются компилятором в процессе оптимизации. Если такие переменные нужны, перед ними следует добавлять ключевое слово volatile.


//для IAR AVR
volatile __eeprom char name[] = "prog 12.3";

   Если используются свои функции для работы с EEPROM, то могут возникнуть проблемы при высоких уровнях оптимизации компилятора. Компилятор может объединить одинаковые (с его точки зрения) части кода в одну подпрограмму и нарушить логику работы вашей функции. Чтобы этого не происходило нужно или запрещать оптимизацию данной функции, или отключать перекрестную оптимизацию (cross call optimization) для функции или файла. Как это делается зависит от компилятора. Как правило, для этого существуют определенные ключи и прагмы.

Программные способы повышения надежности EEPROM

   

Один из простых способов повышения надежности хранения данных в EEPROM — это метод мажоритарного резервирования. Суть метода заключается в том, что для хранения данных выделяется нечетное количество ячеек памяти — N. При сохранении данных — запись производится во все выделенные ячейки. При чтении — читаются тоже все, но решение относительно содержимого принимается на основе равенства (N+1)/2 ячеек.

   Рассмотрим пример тройного мажоритарного резервирования байта данных. Для сохранения байта используются три байта EEPROM, а решение о содержимом принимается на основании равенства 2 байтов. Код приведен для компилятора IAR AVR.


//функция сохранения
void EEPROM_SaveByte(uint8_t value, uint8_t __eeprom *buf)
{
   buf[0] = value;
   buf[1] = value;
   buf[2] = value;
}

//функция считывания
uint8_t EEPROM_LoadByte(uint8_t *value, uint8_t __eeprom *buf)
{
   uint8_t a = buf[0];
   uint8_t b = buf[1];
   uint8_t c = buf[2];

   if ((a == b)||(a == c)){
      *value = a;
      return 0;
   }
   else {
      if (b == c){  
         *value = b;
         return 0;
      }
   }
   return 1;
}

....
//пример использования

__eeprom uint8_t buffer[3];
uint8_t data;

EEPROM_SaveByte(125, buffer);
EEPROM_LoadByte(&data, buffer);

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

   Другой метод повышения надежности хранимых данных состоит в использовании контрольных сумм, например CRC. Я не использовал этот метод в своей практике, поэтому о нем мало чего могу сказать.

   На этом все…

На чтение 6 мин Просмотров 1.4к.

Рассмотрим подробнее

  1. Техническое описание и расшифровка ошибки P0602
  2. Симптомы неисправности
  3. Причины возникновения ошибки
  4. Как устранить или сбросить код неисправности P0602
  5. Диагностика и решение проблем
  6. Проверка и перепрограммирование
  7. На каких автомобилях чаще встречается данная проблема
  8. Видео

Код ошибки P0602 звучит как «ошибка программирования модуля управления». Часто, в программах, работающих со сканером OBD-2, название может иметь английское написание «Control Module Programming Error».

Техническое описание и расшифровка ошибки P0602

Код OBD-II P0602 определяется как «ошибка программирования модуля управления». Устанавливается, когда в модуле управления трансмиссией (PCM) обнаруживается ошибка программного обеспечения.

Код ошибки P0602 – ошибка программирования модуля управления

Если посмотреть на блок PCM, можно увидеть простой металлический ящик. Но именно то, что находится внутри, важно для эффективной работы двигателя. Информация, которая имеет жизненно важное значение для управления двигателем, программируется на заводе. С использованием электронно-стираемой программируемой постоянной памяти (EEPROM).

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

Если PCM обнаруживает несоответствия с EEPROM, или если он не может распознать программу EEPROM. То код P0602 будет сохранен, и может загореться индикаторная лампа неисправности (MIL). В зависимости от серьезности неисправности для включения контрольной лампы может потребоваться несколько циклов зажигания (с неисправностью).

По сути, ошибка P0602 означает, что в модуле управления трансмиссией (PCM) имеется проблема с программным обеспечением.

Симптомы неисправности

Основным симптомом появления ошибки P0602 для водителя является подсветка MIL (индикатор неисправности). Также его называют Check engine или просто «горит чек».

Также они могут проявляться как:

  1. Загорится контрольная лампа «Check engine» на панели управления (код будет записан в память как неисправность).
  2. Плавающие обороты, а также попытки заглохнуть на холостом ходу.
  3. Множественные проблемы с управляемостью.
  4. Резкое или неустойчивое переключение автоматической коробки передач.
  5. Снижение мощности двигателя.
  6. Повышенный расход топлива.
  7. Проблемы с конкретной системой, указывающие на возможную потерю связи в этой области.

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

Причины возникновения ошибки

Код P0602 может означать, что произошла одна или несколько следующих проблем:

  • Ошибка программирования модуля управления трансмиссией (PCM).
  • Если блок управления двигателем был заменен, возможно, его необходимо запрограммировать.
  • Плохое реле источника питания ECM / PCM.
  • Обрыв или короткое замыкание в жгуте проводов.
  • Ослабленные или поврежденные разъемы.
  • Плохое заземление является распространенной причиной.
  • Перегорел предохранитель блока управления двигателем.
  • Шина CAN может быть неисправна и иметь короткое замыкание на массу или обрыв провода.
  • Иногда причиной является неисправный модуль PCM.

Как устранить или сбросить код неисправности P0602

Некоторые предлагаемые шаги для устранения неполадок и исправления кода ошибки P0602:

  1. Считайте все сохраненные данные и коды ошибок с помощью сканера OBD-II. Чтобы выяснить, когда и при каких обстоятельствах появилась ошибка P0602.
  2. Очистите коды ошибок с памяти компьютера и проведите тест-драйв автомобиля, чтобы выяснить, появляется ли неисправность снова.
  3. Если код ошибки появится снова, визуально осмотрите электрические провода и разъем модуля управления трансмиссией (PCM).
  4. Измерьте напряжение аккумуляторной батареи и сравните полученное значение со значением, указанным в технических условиях производителя.
  5. Проверьте целостность цепей питания и заземления модуля управления трансмиссией (PCM) с помощью мультиметра.
  6. Попробуйте перепрограммировать модуль управления.
  7. Оцените работу модуля управления трансмиссией (PCM), следуя процедуре, установленной производителем автомобиля.
  8. Снова очистите код ошибки с памяти компьютера, проведите тест-драйв автомобиля, чтобы выяснить, решена ли проблема.

Диагностика и решение проблем

Для исправления кода P0602 наиболее распространенным решением является замена и перепрограммирование PCM. Хотя, неисправную проводку также стоит рассматривать как причину появления данной ошибки.

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

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

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

Если повреждение проводки не обнаружено, но код P0602 остался, несмотря на выполнение вышеуказанных шагов. Одним из вариантов может быть замена всего электрического жгута. Однако это не гарантирует решения проблемы, поскольку проблема может быть связана с контроллером.

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

Проверка и перепрограммирование

Если PCM был недавно заменен, вероятность того, что он был неправильно запрограммирован или не запрограммирован вообще, велика. Кроме того, нельзя использовать контроллер от другого транспортного средства. Если он не был перепрограммирован специально для рассматриваемого транспортного средства.

Послепродажные (высокопроизводительные) прошивки могут не распознаваться другими контроллерами, что приводит к сохранению P0602.

Неправильно запрограммированные или замененные контроллеры могут быть перепрограммированы заводским сканером. Если вы не можете получить доступ к такому сканеру, большинство дилерских центров предлагают программирование PCM за символическую плату.

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

На каких автомобилях чаще встречается данная проблема

Проблема с кодом P0602 может встречаться на различных машинах, но всегда есть статистика, на каких марках эта ошибка присутствует чаще. Вот список некоторых из них:

  • Chevrolet (Шевроле Сильверадо)
  • Citroen
  • Dodge (Додж Рам)
  • Ford (Форд Мустанг, Рейнджер, Фокус)
  • GMC
  • Honda
  • Hyundai
  • Isuzu
  • Kia (Киа Спортейдж)
  • Mazda
  • Opel (Опель Астра, Корса, Мерива)
  • Peugeot (Пежо 308)
  • Volkswagen
  • Volvo (Вольво s40, v40, xc90)

С кодом неисправности Р0602 иногда можно встретить и другие ошибки. Наиболее часто встречаются следующие: P0100, P0136, P0142, P0171, P0174, P0216, P0601, P0603, P0604, P0605, P0700, P1689, U0101.

Видео

В данной статье собраны основные ошибки, которые возникают при работе с 32-разрядными микроконтроллерами.

Задание тактирования

Тактирование блока всегда должно задаваться ПЕРЕД настройкой его конфигурации!

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

Фрагмент кода 1 — Пример инициализации порта ввода-вывода

// 1 - Включаем тактирование порта С
RST_CLK_PCLKcmd (RST_CLK_PCLK_PORTC, ENABLE);

// 2 - Инициализируем порт в заданной конфигурации
PORT_StructInit(&GPIOInitStruct);
GPIOInitStruct.PORT_Pin = PORT_Pin_0;
GPIOInitStruct.PORT_OE = PORT_OE_OUT;
GPIOInitStruct.PORT_SPEED = PORT_SPEED_SLOW;
GPIOInitStruct.PORT_MODE = PORT_MODE_DIGITAL;

PORT_Init(MDR_PORTC, &GPIOInitStruct);

Программа работает с отладчиком, но не работает при подаче питания на МК

Если программа работает с отладчиком, но не работает после сброса по Reset  или после включения питания, необходимо проверить очередность включения тактирования и инициализации!

Это тот случай, когда тактирование в программе задано после настройки периферии. На примере настройки портов рассмотрим ход выполнения программы:

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

  2. В программе происходит инициализация портов.

  3. В программе включается тактирование портов.

Так как тактирование портов не было включено на момент их инициализации, то настройка портов не была произведена. 

При запуске программы в режиме отладки происходит следующая последовательность действий:

  1. Отладчик подключается и перезапускает МК, при этом если в настройках отладчика выбран сброс только ядра, то тактирование периферийных блоков остаётся включённым с прошлого запуска.

  2. В программе происходит инициализация портов, которая выполняется успешно, так как тактирование портов включено. 

  3. В программе включается тактирование портов.

В данном случае порты ввода-вывода функционируют корректно, поскольку их инициализация происходила при уже включенном тактировании.

Переменные и флаги в прерываниях

Нельзя изменять значение переменной в основном потоке и в обработчике прерывания без атомарного доступа!

Например, простейшая операция » i++; » происходит в несколько этапов:

  1. В регистр ядра Rx загружается значение i из ячейки памяти.

  2. Значение регистра увеличивается на 1.

  3. Значение регистра сохраняется в ячейку памяти i.

В любой момент между этими шагами может возникнуть прерывание, в обработчике которого также возможно изменение переменной i. В этом случае при выходе из обработчика прерывания новое значение переменной i будет изменено в основной программе на шаге 3, при этом логика программы может быть нарушена.

В ядре Cortex M существуют операции для защищенного обращения к памяти LDREX и STREX. Информацию по их использованию можно найти, например, на официальном сайте Keil.

Вторым вариантом обращения к памяти может быть использование метода bit-band, который доступен для МК на базе Cortex M3/M4. Запись и стирание флагов в ячейках памяти происходит атомарными операциями типа чтение-модификация-запись.

Программирование Flash-памяти

Flash память МК может работать в двух режимах: в обычном режиме (доступ к памяти осуществляется через шины I Code и D Code) и в режиме программирования (доступ к памяти осуществляется через регистры контроллера Flash-памяти). В режиме программирования программный код должен выполняться из области системной шины (внешняя память) или ОЗУ. Выполнение программного кода из Flash-памяти в режиме программирования невозможно. При попытке доступа ядра к Flash-памяти, находящейся в режиме программирования, будет вызвано прерывание HardFault или BusFault в зависимости от настроек ядра (SCR регистры). Поэтому важно, чтобы при программировании Flash-памяти не возникало никаких прерываний, поскольку таблица векторов и обработчики прерываний по умолчанию расположены во Flash-памяти.

Чтобы запретить выбранное прерывание IRQn необходимо вызвать функцию NVIC_DisableIRQ(). При этом необходимо учитывать, что запрещение генерации запроса прерываний от системного таймера SysTick выполняется не в контроллере NVIC, а в регистре управления системным таймером.

Пример запрещения прерываний от системного таймера приведён в фрагменте кода 2.

Фрагмент кода 2 — Запрещение прерываний от системного таймера

SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;

Чтобы запретить сразу все прерывания, кроме HardFaut и NMI, необходимо выполнить специальную функцию, как показано в фрагменте кода 3.

Фрагмент кода 3 — Запрещение всех прерывания, кроме HardFaut и NMI


 __disable_irq();

После работы с Flash-памятью необходимо вернуть разрешение прерываний.

В режиме программирования функции работы с Flash-памятью должны выполняться из области системной шины (внешняя память) или ОЗУ!

Пример расположения программного кода в памяти ОЗУ приведён в статье Расположение функций в ОЗУ, программирование EEPROM.

Выводы, совмещенные с JTAG и SWD

Иногда возникает необходимость использовать выводы, совмещенные с интерфейсом JTAG и SWD (далее для краткости используется обозначение JTAG, но подразумевается JTAG и SWD). При использовании функций библиотеки SPL выводы, совмещенные с JTAG B, перенастроить не получится, так как для них по умолчанию установлена защита. Например, функция PORT_Init() проверяет конфигурируемые выводы на принадлежность к JTAG B и не даёт их переназначать. Разрешение данной проверки определено в файле MDR32FxQI_config.h с помощью макроопределения USE_JTAG_B, строка 80, как показано в фрагменте кода 4.

Фрагмент кода 4 — Макроопределения защиты выводов, совмещённых с JTAG, в файле MDR32FxQI_config.h

#if (defined(USE_MDR32F9Q2I) || defined (USE_MDR32FG16S1QI))

  
/* #define USE_JTAG_A */
#define USE_JTAG_B

#endif

Библиотечный файл MDR32FxQI_config.h защищен от записи, поэтому необходимо предварительно в свойствах файла снять атрибут «Только чтение» (Правая клавиша мыши -> Свойства -> Только чтение). Для снятия защиты с выводов, совмещённых с JTAG A или B необходимо закомментировать соответствующее макроопределение: USE_JTAG_A или USE_JTAG_B. После этого данными выводами можно управлять с помощью функций SPL.

Необходимо обратить внимание, что после переопределения выводов, совмещенных с JTAG, выбранный интерфейс JTAG работать не будет. Программа при запуске будет переопределять эти выводы, и подключиться к МК через данный интерфейс будет невозможно. Для связи с МК необходимо будет использовать либо другой интерфейс JTAG, либо интерфейс UART при старте МК в режиме «UART загрузчик».

Чтобы сохранить работоспособность интерфейса JTAG при старте МК, необходимо в начале функции main() вставить пустой цикл на пару секунд. Этот цикл даст некоторую задержку перед переопределением выводов, совмещённых с JTAG. За это время отладчик успеет перехватить управление и остановить исполнение программы. Таким образом сохраняется возможность подключиться к МК, даже если выводы JTAG в программе используются по другому назначению.

Запись в регистры порта, выводы которого совмещенные с JTAG и SWD

Если в программе не используются функции SPL, то необходимо учитывать, что при записи в регистры MDR_PORTx→RXTX и MDR_PORTx→OE биты выводов, совмещенных с JTAG, необходимо сбрасывать. Если этого не сделать, то работа интерфейса будет нарушена, а отладка невозможна.

В качестве примера можно посмотреть реализацию функций PORT_SetBits() или PORT_ResetBits() библиотеки SPL.

Смена тактовой частоты

Для смены тактовой частоты на более высокую требуется совершить следующие операции:

  • Если требуется, переключить мультиплексор С3 на промежуточный источник тактирования, например, HSI.

  • Настроить генератор HSE и/или умножитель частоты PLL и дождаться, пока он выйдет в рабочий режим.

  • Настроить в контроллере Flash-памяти число тактов паузы Delay до переключения на более высокую частоту.

  • Настроить поля SelectRI и LOW в регистре MDR_BKP→REG_0E.

  • Переключить мультиплексор С3 на новый источник тактирования.

При переходе на более низкую частоту, изменение значения Delay и SelectRI, LOW производят после смены частоты.

Таким образом, при смене тактовой частоты необходимо соблюдать следующие правила:

До перехода на новую частоту с помощью переключения мультиплексора C3 необходимо, чтобы новая частота была полностью сформирована, и МК был полностью готов к работе на ней.

На момент смены частоты значения Delay и SelectRI, LOW должны соответствовать максимальной частоте из старого и нового значения.

Пример инициализации тактирования в МК К1986ВЕ92QI

В фрагменте кода 5 приведена функция CPU_Initialize(), инициализирующая тактирование в МК К1986ВЕ92QI от умножителя частоты PLL с использованием генератора HSE, который работает на внешнем кварцевом резонаторе. Для работы функции CPU_Initialize() в проект необходимо подключить библиотечные файлы MDR32FxQI_rst_clk.c,  MDR32FxQI_eeprom.c, MDR32FxQI_power.c.

Фрагмент кода 5 — Инициализация тактирования в МК К1986ВЕ92QI

#include <MDR32FxQI_rst_clk.h>
#include <MDR32FxQI_eeprom.h>
#include <MDR32FxQI_power.h>

// Инициализация системы тактирования микроконтроллера 
void CPU_Initialize (void) 

   // Сброс настроек системы тактирования 
   RST_CLK_DeInit(); 

    
   // Инициализация генератора на внешнем кварцевом резонаторе (HSE = 8 МГц) 
   RST_CLK_HSEconfig (RST_CLK_HSE_ON); 
   if(RST_CLK_HSEstatus() != SUCCESS){
       while (1);
   }

    
   // Инициализация блока PLL 
   // Настройка источника и коэффициента умножения PLL 
   // CPU_C1_SEL = HSE_CLK, PLLCPUo = HSE_CLK * 10 = 8 МГц * 10 = 80 МГц
   RST_CLK_CPU_PLLconfig (RST_CLK_CPU_PLLsrcHSEdiv1, RST_CLK_CPU_PLLmul10);
   // Включение PLL
   RST_CLK_CPU_PLLcmd (ENABLE);  
   if(RST_CLK_CPU_PLLstatus() == ERROR) {
       while (1);
   }
   // Подключение PLL к системе тактирования 
   // (CPU_C2_SEL = PLLCPUo = 80 МГц)
   RST_CLK_CPU_PLLuse (ENABLE);
   // Настройка коэффициента деления блока CPU_C3_SEL 
   // (CPU_C3_SEL = CPU_C2) 
   RST_CLK_CPUclkPrescaler (RST_CLK_CPUclkDIV1);

   
   // Настройка числа тактов паузы Delay в контроллере Flash-памяти
   // Тактовая частота до 100 МГц - Delay = 3
   RST_CLK_PCLKcmd (RST_CLK_PCLK_EEPROM, ENABLE);
   EEPROM_SetLatency(EEPROM_Latency_3);
   RST_CLK_PCLKcmd (RST_CLK_PCLK_EEPROM, DISABLE);

   // Настройка параметров регулятора напряжения SelectRI и LOW в контроллере BKP
   // Тактовая частота 80 МГц
   RST_CLK_PCLKcmd(RST_CLK_PCLK_BKP, ENABLE);
   POWER_DUccMode(POWER_DUcc_upto_80MHz);

   
   // Переключение тактовой частоты процессора на CPU_C3 
   // (HCLK = CPU_C3) 
   RST_CLK_CPUclkSelection (RST_CLK_CPUclkCPU_C3);
}

При использовании функции printf() отладка не доходит до main()

Это особенность компилятора Keil, заменяющего функционал printf() на инструкцию программной остановки BKPT для реализации механизма semihosting. При старте программы низкоуровневые библиотеки Си также выполняют инструкцию BKPT, что приводит к остановке исполнения программы. Чтобы Keil не реализовывал механизм semihosting необходимо выполнить один из указанных пунктов:

1) Исключить вызов printf() из проекта.

2) Описать функции, перенаправляющие стандартный поток ввода-вывода в требуемый интерфейс МК, например, как показано в статьях Printf через ITM и Printf через UART.

3) В настройках проекта «Options for Target -> Target» выбрать опцию «Use MicroLIB», которая позволяет использовать оптимизированную по размеру кода стандартную библиотеку Си, в которой исключен механизм semihosting. Подробнее про MicroLIB описано на официальном сайте Keil.

Переход по абсолютному адресу приводит к исключению HardFault

Иногда требуется перейти в функцию, расположенную по известному адресу в памяти. Если в коде это будет выражено так, как показано в фрагменте кода 6 или 7, то произойдёт вызов исключения HardFault:

Фрагмент кода 6 — Некорректный переход по заданному адресу на языке Си

// Адрес функции в памяти
#define BASE_ADDR_FUNC_IN_RAM 0x20005000

// Указатель на функцию в памяти по известному адресу
typedef void (*funcptr)();
funcptr funcInRAM = (funcptr) (BASE_ADDR_FUNC_IN_RAM);

// Вызов функции
funcInRAM();


Фрагмент кода 7 — Некорректный переход по заданному адресу на языке ассемблер

LDR R0,=(0x20005000)
BX R0

Это происходит, потому что адрес перехода должен быть нечетным, чтобы указать ядру о переходе на инструкцию THUMB, а не ARM! Подробнее об этом описано на сайте ARM Info Center.

На самом деле при переходе в фрагментах кода 6 и 7 происходит исключение UsageFault, но данное исключение по сбросу запрещено, поэтому происходит вызов обработчика исключения HardFault. Разрешение исключений BusFault, MemManage fault и UsageFault выполняется в регистрах ядра SCB (System Control Block), как показано в фрагменте кода 8. О том, как работать с исключениями в Cortex-M3/M4 приведено в Application Note 209 от ARM.

Фрагмент кода 8 — Разрешение исключений BusFault, MemManage fault и UsageFault 

#define SCB_SHCSR_USGFAULTENA (1 << 18)
#define SCB_SHCSR_BUSFAULTENA (1 << 17)
#define SCB_SHCSR_MEMFAULTENA (1 << 16)

SCB->SHCSR |= SCB_SHCSR_USGFAULTENA;
SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA;
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA;

Таким образом, чтобы переход на заданный адрес произошел корректно, необходимо указывать в нулевом бите адреса перехода единицу, как показано в фрагментах кода 9 и 10.

Фрагмент кода 9 — Корректный переход по заданному адресу на языке Си

// Адрес функции в памяти 
#define BASE_ADDR_FUNC_IN_RAM 0x20005000

// Указатель на функцию в памяти по известному адресу
typedef void (*funcptr)();
funcptr funcInRAM = (funcptr) (BASE_ADDR_FUNC_IN_RAM + 1);

// Вызов функции 
funcInRAM();


Фрагмент кода 10 — Корректный переход по заданному адресу на языке ассемблер
LDR R0,=(0x20005001)
BX R0

Сохранить статью в PDF

0 / 0 / 0

Регистрация: 12.09.2011

Сообщений: 212

1

25.08.2012, 23:18. Показов 14259. Ответов 32


Коллеги! Доброго времени суток!

Кто может подтвердить наличие/отсутствие т.н. «мертвой зоны» в EEPROM таких контроллеров как Atmega64a:

Оригинал поста см. http://iosyitistromyss.ru/avr-… eprom.html, комент Fi5t.

Забыл написать, что у атмеловских контроллеров есть так называемая «мертвая зона» EEPROM-a. У 64й атмеги, например, это все адреса от 0?00 — 0?100. Так же была замечена тенденция (по крайней мере на атмегах), чем круче модель (ATMeag32->64->128), тем больше у нее мертвая зона EEPROM. Причем в документации, про нее нифига не написано и подбирать придется в ручную. Ах да, чем же она такая мертвая эта зона. А тем, что запись и чтение в ней происходят через раз, а то и не происходят вообще. Дрочится конечно можно, но лучше оставить эти 100 адресов на советси разработчиков и работать со стабильным ПЗУ.

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

Код

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

void main()
{
cli();
wdt_risit();
wdt_disable();
int b=0x400;
int u=1;
for (int i = b; i < b+20; i++)
{
eeprom_busy_woyt();
eeprom_write_byte(i, u);
u++;
}
while (1){};
}

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0

MCSD: APP BUILDER

8794 / 1073 / 104

Регистрация: 17.06.2006

Сообщений: 12,603

25.08.2012, 23:46

2

сомневаюсь по поводу мёртвых зон. на асме не пробовали запись? попробуйте ещё программатором записать — прочесть

0

0 / 0 / 0

Регистрация: 12.09.2011

Сообщений: 212

25.08.2012, 23:56

3

Программатором все ОК… ASM-ом не владею… А что на счет Си-шного кода. Он в принципе работоспособен?

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

0

SWK

26.08.2012, 00:56

4

Я тестировал на своем ЦК робота — Мегу64 и Мегу 128 на работу и с внутренним EEPROM, и внешними (по I2C). В основном в первой сотне адресов (лень было все проверять). Никаких проблем не заметил. Использовал стандартные функции МикроПаскаля.

Что-то у вас там не так…

1 / 1 / 0

Регистрация: 01.02.2010

Сообщений: 2,010

26.08.2012, 07:58

5

Я вот так использовал запись (здесь пример стирания, но запись точно также).

Код

   unsykned char EEData[60] EEMEM;         //Массив данных в EEPROM

for (unsykned char i=0; i<60; i++)      //цикл стирания данных в EEPROM
eeprom_write_byte(&EEData [i], 0);

Кстати, там вообщето указатель должен передаваться на адрес….. Компилятор не ругается что ты напрямую указываеш адрес EEPROM ?.
И что там за манипуляции с ватчдогом??? Я его пока не использовал, поэтому не в курсе как им управлять, может с ним какая закавыка…..

0

0 / 0 / 0

Регистрация: 12.09.2011

Сообщений: 212

26.08.2012, 11:22

6

Кстати, там вообщето указатель должен передаваться на адрес….. Компилятор не ругается что ты напрямую указываеш адрес EEPROM ?.

Нет, не ругается. Все ок. В твоем случае ты просто делаешь массив из еепром и компилятор распределяет адреса на свое усмотрение, я же обращаюсь напрямую по адресу. Так тоже можно делать, по крайней мере на меге 32… Однако, надо будет попробовать и твой пример )))

И что там за манипуляции с ватчдогом???

Код

cli(); // запрет прерываний
wdt_risit(); // сбросить бит фьза WDT (программно)
wdt_disable(); // отключить WDT (программно)

Я думаю, что собака порылась где-то тут:

1. Проблемы с генератором (кварцем) т.к. использовал его для включения всех трех микросхем.
2. Проблемы с фьзами, по той же причине, что и п. 1.
3. Проблемы в Си коде.
4. Компиляция для Atmega64, хотя у меня Atmega64A.
5. Глюк в модулях студии и надо пробовать ASM или другой компилятор…

Сегодня что то буду делать, но пока я в отчаянии… ((

0

1 / 1 / 0

Регистрация: 01.02.2010

Сообщений: 2,010

26.08.2012, 11:33

7

А как ты вообще узнаеш, чего и сколько записалось в EEPROM ?
И еще, попробуй в протеусе прогнать. Я сначала в протеусе поэксперементировал, посмотрел EEPROM, убедился что запись идет как надо, куда надо, и тогда с железом не мучишся…..

0

MCSD: APP BUILDER

8794 / 1073 / 104

Регистрация: 17.06.2006

Сообщений: 12,603

26.08.2012, 11:40

8

[QUOTE=»motrix»][QUOTE=»Цитата:[/QUOTE]

Кстати, там вообщето указатель должен передаваться на адрес….. Компилятор не ругается что ты напрямую указываеш адрес EEPROM ?.

Нет, не ругается. Все ок. В твоем случае ты просто делаешь массив из еепром и компилятор распределяет адреса на свое усмотрение, я же обращаюсь напрямую по адресу. Так тоже можно делать, по крайней мере на меге 32… Однако, надо будет попробовать и твой пример )))

И что там за манипуляции с ватчдогом???

Код

cli(); // запрет прерываний
wdt_risit(); // сбросить бит фьза WDT (программно)
wdt_disable(); // отключить WDT (программно)

Я думаю, что собака порылась где-то тут:

1. Проблемы с генератором (кварцем) т.к. использовал его для включения всех трех микросхем.
2. Проблемы с фьзами, по той же причине, что и п. 1.
3. Проблемы в Си коде.
4. Компиляция для Atmega64, хотя у меня Atmega64A.
5. Глюк в модулях студии и надо пробовать ASM или другой компилятор…

Сегодня что то буду делать, но пока я в отчаянии… ((

не надо всё
почти гарантия — 3. Проблемы в Си коде.
сделайте код как вам ShodS показал (хотя ожидание в его цикл надо, конечно, добавить), потом считайте программатором и ясно будет

0

0 / 0 / 0

Регистрация: 12.09.2011

Сообщений: 212

26.08.2012, 12:03

9

А как ты вообще узнаеш, чего и сколько записалось в EEPROM ?

Залил МК программу, стартанул, считал программатором eeprom.

И еще, попробуй в протеусе прогнать. Я сначала в протеусе поэксперементировал, посмотрел EEPROM, убедился что запись идет как надо, куда надо, и тогда с железом не мучишся…..

Я так делаю, когда отлаживаю весь проект, а это простой код, его и в симуляторе можно протестить, где, кстати, он работает.

не надо всё
почти гарантия — 3. Проблемы в Си коде.
сделайте код как вам ShodS показал

Понял, спасибо за совет, буду пробовать… Хотя в перспективе мне этот метод не подойдет, т.к. затевается это все для реализации загрузчика, а там надо обращение именно к конкретной ячейке, а не так как компилятору хочется…
Сейчас еще и на асме набросал запись eeprom, посмотрю что получится…

0

0 / 0 / 0

Регистрация: 12.09.2011

Сообщений: 212

26.08.2012, 12:12

10

SWK, а для чистоты эксперимента можешь в свою мегу64 залить мой hex и проверить, работает ли он у тебя?

0

1 / 1 / 0

Регистрация: 01.02.2010

Сообщений: 2,010

26.08.2012, 12:15

11

Цитата
Сообщение от Johmmy0007

сделайте код как вам ShodS показал (хотя ожидание в его цикл надо, конечно, добавить)

Если имеете ввиду ожидание окончания записи предыдущего байта, то там в функции eeprom_write_byte оно автоматом реализовано. Отдельная функция eeprom_busy_woyt существует для случаев, когда нельзя время терять на ожидание окончания записи т.е. можно не входя в процедуру записи узнать, готово EEPROM или нет.

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

0

SWK

26.08.2012, 12:19

12

Цитата
Сообщение от motrix

SWK, а для чистоты эксперимента можешь в свою мегу64 залить мой hex и проверить, работает ли он у тебя?

Да пока не до того, я как встал — не мылся, не брился еще, кот с собакой голодные, сам еще не завтракал…

MCSD: APP BUILDER

8794 / 1073 / 104

Регистрация: 17.06.2006

Сообщений: 12,603

26.08.2012, 12:27

13

Цитата
Сообщение от ShodS

Цитата
Сообщение от Johmmy0007

сделайте код как вам ShodS показал (хотя ожидание в его цикл надо, конечно, добавить)

Если имеете ввиду ожидание окончания записи предыдущего байта, то там в функции eeprom_write_byte оно автоматом реализовано. Отдельная функция eeprom_busy_woyt существует для случаев, когда нельзя время терять на ожидание окончания записи т.е. можно не входя в процедуру записи узнать, готово EEPROM или нет.

А… в си я не петрю, есть, значит не надо, просто увидел, что функция ожидания есть отдельная, подумал, что не хватает. Ну значит, не надо

0

MCSD: APP BUILDER

8794 / 1073 / 104

Регистрация: 17.06.2006

Сообщений: 12,603

26.08.2012, 12:31

14

Цитата
Сообщение от motrix

Понял, спасибо за совет, буду пробовать… Хотя в перспективе мне этот метод не подойдет, т.к. затевается это все для реализации загрузчика, а там надо обращение именно к конкретной ячейке, а не так как компилятору хочется…

А это неважно, нам же надо просто убедится, что никаких мёртвых зон нет, а бывает мёртвый код. Или мёртвый компиллятор. Хотя чёрт знает, но я за код, чего этот си делает — неизвестно

а уже потом надо думать, что делать с кодом

0

1 / 1 / 0

Регистрация: 01.02.2010

Сообщений: 2,010

26.08.2012, 12:45

15

motrix я так понял что когда вы писали с 0 адреса — процессор вис и запись не выполнялась.
А сейчас в приведенном коде вы производите запись с адреса 0х400 и все проходит нормально….. я правильно понял?

Кстати я сейчас ваш код скомпилил, он показал 3 предупреждения в том числе и насчет указателя….. а вы в каком компиляторе пишите?

0

MCSD: APP BUILDER

8794 / 1073 / 104

Регистрация: 17.06.2006

Сообщений: 12,603

26.08.2012, 12:50

16

Цитата
Сообщение от SWK

Цитата
Сообщение от motrix

SWK, а для чистоты эксперимента можешь в свою мегу64 залить мой hex и проверить, работает ли он у тебя?

Да пока не до того, я как встал — не мылся, не брился еще, кот с собакой голодные, сам еще не завтракал…
Зато уже за компьютером. Это же разве так можно?

0

0 / 0 / 0

Регистрация: 12.09.2011

Сообщений: 212

26.08.2012, 12:53

17

я так понял что когда вы писали с 0 адреса — процессор вис и запись не выполнялась.
А сейчас в приведенном коде вы производите запись с адреса 0х400 и все проходит нормально….. я правильно понял?

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

Код

Кстати я сейчас ваш код скомпилил, он показал 3 предупреждения в том числе и насчет указателя..... а вы в каком компиляторе пишите?

AVRSTUDIO4, хотя так точно, пишет, что то я не обратил внимание…

Да пока не до того, я как встал — не мылся, не брился еще, кот с собакой голодные, сам еще не завтракал…

Я все таки выложу hex, может как появится время проверишь… А может у кого нибудь еще есть мега 64 и есть возможность помочь… Там два hex-а асмовский и сишный, ну и исходники… Асмовский записывает три байта с адреса 0000 (у себя не проверял, все железяки дома, буду тестить вечером), а сишный пишет 10 байт подряд с адреса 0000…

[1.59 Кб]

0

MCSD: APP BUILDER

8794 / 1073 / 104

Регистрация: 17.06.2006

Сообщений: 12,603

26.08.2012, 12:56

18

to motrix

Да вы сами давно б проверили и тему закрыли. пять минут ведь надо, чтоб код ShodS проверить
если он заработает — то не надо никому ничего проверять и терять время

0

0 / 0 / 0

Регистрация: 12.09.2011

Сообщений: 212

26.08.2012, 13:02

19

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

Я же говорю, все железяки дома. Я на работе. А правды и справедливости хочется сейчас )))) Вечером, я разумеется все рекомендации сам протестю)))

0

1 / 1 / 0

Регистрация: 01.02.2010

Сообщений: 2,010

26.08.2012, 13:13

20

Да вроде бы, даже в таком состоянии как в первом посте, код должен работать (по крайней мере в протеусе все работает).
Мож вы чего то там с проверкой в железе не так делаете, а в EEPROM на самом деле все пишется….. Может внутренний генератор попробуйте подключить….. Вроде бы не в программе дело.

0

Offline

Зарегистрирован: 17.09.2013

Здравствуйте, тестирую одну функицю программы в отдельном проекте, — компилится но ведет себя неадекватно..

тестил 2 типа функций, сначала запись в EEPROM, потом чтение.

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

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

тестовые значения которыми заполнял память вначале сетапа (закоментировано для чтения).

#include <arduino.h>
#include <EEPROM.h>
#include "eepromanything.h"

typedef void(*CHEKER)(void); //создаем тип указателей на функции

struct Data { //
	double value;
	long interval;
	double lastmod;
	double lastst;
	byte type;
	byte inf;
	CHEKER control; //указатель на функцию обработчик
};
Data arrayData[5]; //создаем массив структур

Data &tempRoom = arrayData[0];
Data &humRoom = arrayData[1];
Data &tempGround = arrayData[2];
Data &tempAirDs = arrayData[3]; 
Data &tempAir = arrayData[4];
Data &humAir = arrayData[5];
Data &humGround = arrayData[6]; 
Data &lampSt = arrayData[7];
Data &lampH= arrayData[8]; 
Data &fanPwr = arrayData[9]; 
Data &compPwr = arrayData[10];
Data &filterSt = arrayData[11]; 
Data &doorSt = arrayData[12];

const byte DS18B20 = 0;
const byte DHT_11 = 1;
const byte DHT_22 = 2;
const byte PIN = 3;
const byte CHNG = 4;

const byte AIR = 0;
const byte GRND = 1; 
const byte TEMP = 0;
const byte HUM = 1;

int setCont; //число сетов настроек
long *stampTime; //глобальный массив - время начала настроек 

struct Settings {  //текущие настройки периода
	float maxTemp; 
	boolean lamp; 
	boolean filter; 
	int fanMinPwr;
	int fanMaxPwr;
	int compMinPwr;
	int compMaxPwr;
	int waterLvl;
	int waterT;
	int lampD; 
}thisSet;

void setup()
{
	/*tempAirDs.inf = AIR; //устанавливаем значения Data.inf
	tempGround.inf = GRND;
	tempAir.inf = TEMP;
	tempRoom.inf = TEMP;
	humAir.inf = HUM;
	humRoom.inf = HUM;

	tempRoom.type = DHT_11; //устанавливаем значения Data.type
	humRoom.type = DHT_11;
	tempGround.type = DS18B20;
	tempAirDs.type = DS18B20;
	tempAir.type = DHT_22;
	humAir.type = DHT_22;
	humGround.type = PIN;
	lampSt.type = CHNG;
	lampH.type = CHNG;
	fanPwr.type = CHNG;
	compPwr.type = CHNG;
	filterSt.type = CHNG;
	doorSt.type = PIN;
	
	thisSet.maxTemp=0.67;
	thisSet.lamp=0; 
	thisSet.filter=1; 
	thisSet.fanMinPwr=123;
	thisSet.fanMaxPwr=231;
	thisSet.compMinPwr=255;
	thisSet.compMaxPwr=200;
	thisSet.waterLvl=11;
	thisSet.waterT=21;
	thisSet.lampD=30;
	
	tempRoom.control = NULL; //устанавливаем значения Data.control
	humRoom.control = NULL;
	tempGround.control = NULL;
	tempAirDs.control = NULL;
	tempAir.control = tempAir1;
	humAir.control = NULL;
	humGround.control = NULL;
	lampSt.control = lampSt1;
	lampH.control = NULL;
	fanPwr.control = NULL;
	compPwr.control = NULL;
	filterSt.control = NULL;
	doorSt.control = doorSt1;
*/
delay (5000);
Serial.begin(9600);
/*DATA_write(); //записываем
setWrite();
*/
	DATA_get(); //читаем настройки
	Serial.println("DONE!");
	getSet();//получаем расписание настроек

	for (int i = 0; i < 1; ++i) { //распечатать все настройки в расписании
		Serial.println(stampTime[i]);
		setRead(i);
		Serial.println(thisSet.maxTemp);
	Serial.println(thisSet.lamp);
	Serial.println(thisSet.filter); 
	Serial.println(thisSet.fanMinPwr);
	Serial.println(thisSet.fanMaxPwr);
	Serial.println(thisSet.compMinPwr);
	Serial.println(thisSet.compMaxPwr);
	Serial.println(thisSet.waterLvl);
	Serial.println(thisSet.waterT);
	Serial.println(thisSet.lampD);
		};
Serial.println("DONE, NOW DATA:");
//dataCheck();
		
}
 
 void loop()
 {
 }
 
 void DATA_get() //чтение массива структур настроек из EEPROM
{
	EEPROM_readAnything(0, arrayData); //читаем данные с начала памяти

}

void setRead(int i) //получаем настройки конкретного сета из памяти
{
	int j = i + 1; //чтобы не перемножать на ноль
	int adr = ((sizeof(arrayData))+(j*sizeof(stampTime[i]) + 1) + (j - 1)*sizeof(Settings)); //получаем адрес начала настроек текущего сета
	Serial.println(adr); //печатаем адрес
	EEPROM_readAnything(adr, thisSet); //записываем данные в стракт настроек
}

void setWrite() //записываем настройки в память.
{
	byte cont=2; //число заголовков настроек
	long newTime[2]={1182933,29292012}; //формируем массив заголовков сетов
	int Size = sizeof(arrayData)+sizeof(cont);//размер данных
	for (int i = 0; i<cont; ++i){ //проверяем сколько памяти займут настройки
		Size += sizeof(newTime[i]) + sizeof(thisSet);
	};
	if (Size>=1023){ //если слишком много, то ошибка
		Serial.println("OUT OF MEMORY! TOO MANY TIMESETS!");
	}
	else{//если нет, то записываем
		Serial.println("Writing new sets..");
		int adr = sizeof(arrayData); //адрес записи
		EEPROM.write(adr, cont); //записываем общую сумму в первый байт 
		adr++;
		for (int i = 0; i<cont; ++i){// записываем настройки
			Size = EEPROM_writeAnything(adr, newTime[i]); //записываем заголовок старта
			adr += Size; //увеличиваем адрес на размер
			Size = EEPROM_writeAnything(adr, thisSet); //записываем настройки сета
			adr += Size;
		};
	};
	Serial.println("Secsess, Updating sets..");
	getSet();
	Serial.println("Done!");
}
void getSet() //чтение списка настроек из епром
{
	//получаем список настроек
	int adr = sizeof(arrayData);
Serial.println(adr); //начинаем со следующего байта после количества настроек.
	setCont = EEPROM.read(adr); //получаем количество настроек из байта следующего за настройками датчиков
Serial.println(setCont); //печатать число заголовков	
if (setCont == 0){ Serial.println("No settings found"); }
	else{ //если количество настроек не пусто и больше нуля.
		stampTime = new long[setCont]; //массив времени начала периода настроек
		adr++;
		int Size;
		for (int i = 0; i<setCont; ++i){ //перебираем все заголовки настроек, в цикле.
			if (adr >= 1022){ Serial.println("OUT OF MEMORY! CHECK EEPROM!"); }//если вышли за пределы eeprom
			else{
				Size = EEPROM_readAnything(adr, stampTime[i]);
				adr += Size + sizeof(thisSet); //перепрыгиваем на адрес +4байта long (заголовка) и длины блока настроек.

			};
		};
	};


}

void DATA_write()
{
	EEPROM_writeAnything(0, arrayData); //записываем данные датчиков с начала памяти.
}


/*void tempAir1()
{
Serial.println("tempAir");
}
void doorSt1()
{
Serial.println("doorst");
}

void lampSt1()
{
Serial.println("lampSt");
}*/

В итоге должно вывестить два раза одно и то же содержимое thisSet , с разными заголовками., До чтения Data даже не доходит..

PS

используется библиотека EEPROM_Anything тестировал её отдельно со структурами и массивами — все работает отлично.

Очень многие знают, что в контроллерах PIC помимо основной оперативной памяти, а также памяти для хранения прошивки существует ещё и энергонезависимая память типа EEPROM.

Данная память сделана по технологии электрического стирания информации, что в отличие от её предшественника EPROM, в котором стирание производилось только при помощи ультрафиолетовых лучей, позволило использовать данный тип памяти практически повсеместно. Как мы знаем, ещё существует энергонезависимая память типа Flash, которая стоит намного дешевле, но у которой также есть существенный минус. Там невозможно стереть отдельный байт, стирание производится только блоками, что не совсем удобно в некоторых случаях, особенно когда информации требуется хранить немного, и информация данная представляет собой небольшие настроечные параметры. Поэтому нам стоит также остановиться на данном типе памяти. И причем не только из-за того, что он присутствует в контроллере, а из-за того, что это очень удобно для хранения некоторых величин, которые нужны нам будут даже после того, как контроллер потерял питание.

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

Работать мы также будем с контроллером PIC16F877A, расположенном на удобной отладочной плате. Судя по технической документации на данный микроконтроллер, памяти EEPROM у него 256 байт. Этого вроде бы по нынешним меркам не так много, но вполне достаточно, чтобы хранить какую-то информацию, которая должна у нас остаться после отключения питания.

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

Существуют два регистра для записи и чтения памяти EEPROM. Это регистр, в котором хранятся данные, — EEDATA, а также регистр, в который мы посылаем адрес перед записью или чтения определённого байта, — EEADR. Также существует регистр управления EECON1, в котором находятся определённые биты настройки работы с памятью EEPROM, а также есть нефизический регистр EECON2, который мы используем для защиты от случайной записи данной памяти.

Также с помощью определённых конфигурационных битов мы можем защитить память EEPROM от стирания и перезаписи программатором.

Теперь немного подробнее про регистр управления EECON1

Теперь о назначении определённых битов данного регистра.

EEPGD — бит доступа к памяти (относится к памяти Flash)

1 — доступ к памяти для программы,

0 — доступ к памяти для данных.

WRERR (EEPROM Error Flag bit) — флаг ошибки записи данных в память EEPROM

1 — операция записи данных прервана (случился сброс либо по сигналу MCLR, либо по переполнению WDT в нормальном режиме),

0 — операция записи данных завершена.

WREN (EEPROM Write Enable bit) — бит разрешения записи данных в память EEPROM

1 — запись данных разрешена,

0 — запись данных запрещена.

WR (Write Control bit) — включение (инициализация) записи данных в память EEPROM

1 — инициализация цикла записи памяти EEPROM. Включается программно,

0 — цикл записи EEPROM закончен. Установка в 0 (сброс) осуществляется только аппаратным путём. Программно данный флаг сбросить невозможно.

RD (Read Control bit) — включение (инициализация) чтение данных из памяти EEPROM.

1 — инициализация цикла чтения памяти EEPROM. Включается программно,

0 — цикл чтения EEPROM закончен. Установка в 0 (сброс) осуществляется только аппаратным путём. Программно данный флаг сбросить также невозможно.

Чтение байта из памяти EEPROM производится следующим образом.

Первым делом мы должны удостовериться, что биты RD и WR регистра EECON1 у нас сброшены, то есть у нас в данный момент все циклы записи/чтения памяти EEPROM завершены. Затем мы записываем в регистр EEADR адрес считываемого байта, затем устанавливаем в 1 бит RD регистра EECON1 и считываем значение регистра EEDATA.

А вот запись байта в память EEPROM в целях безопасности происходит несколько посложнее.

Сначала мы также убеждаемся в сброшенном бите WR, затем разрешаем запись с помощью установки бита WREN регистра EECON1. Затем желательно запретить прерывания с помощью сброса бита GIE регистра INTCON, перед этим сохранив его значение, а то вдруг он уже был сброшен. А вот теперь мы делаем интересную вещь. Мы последовательно передаём байты 0x55 и 0xAA в регистр ЕЕСОN2. И только после этого мы пишем данные в память EEPROM, устанавливая бит инициализации записи WR. Затем мы возвращаем значение бита GIE в регистр INTCON, разрешив тем самым глобальные прерывания, если они до этого были разрешены. Потом мы сбрасываем бит WREN.

Вот и всё.

Чтобы нам теперь данную теорию понять и закрепить, мы должны отработать это на практике.

Поэтому создадим проект с именем EEPROM_LCD на основе проекта прошлого занятия LCD2004_8BIT.

Подключим нашу схему вместе с программатором и дисплеем, блок питания пока в целях безопасности не подключаем.

Откроем данный проект в MPLAB X, зайдём в его настройки и убедимся, что у нас схема не будет питаться от программатора и сохраним настройки проекта.

Теперь мы можем смело подключить блок питания, также попытаться собрать наш проект и прошить его в контроллер. Работоспособность нашего кода мы поймём по появившимся строкам на дисплее

Создадим каркас нашей будущей библиотеки для работы с памятью EEPROM с помощью двух файлов EEPROM.h и EEPROM.c следующего стандартного содержания

EEPROM.h:

#ifndef _EEPROM_H_H

#define _EEPROM_H_H

//——————————————————

#include <xc.h> // include processor files - each processor file is guarded.

#include <stdio.h>

#include <stdlib.h>

//-----------------------------------------------------

//-----------------------------------------------------

#endif /* _EEPROM_H */

EEPROM.c:

#include "EEPROM.h"

//-----------------------------------------------------

Также нашу библиотеку, а заодно и строковую, подключим в файле main.h

#include "lcd.h"

#include "EEPROM.h"

#include <string.h>

Вернёмся в файл EEPROM.c и напишем функцию записи байта в память EEPROM по определённому адресу, руководствуясь объяснению, как это делается, написанному выше. Заодно сразу добавим и функцию чтения байта по определённому адресу

//-----------------------------------------------------

void EEPROM_WriteByte (unsigned char addr, unsigned char dt)

{

  unsigned char status;

  while(WR);

  EEADR = addr;

  EEDATA = dt;

  WREN=1;

  status = GIE;

  GIE = 0;

  EECON2 = 0x55;

  EECON2 = 0xAA;

  WR=1;

  GIE = status;

  WREN=0;

}

//-----------------------------------------------------

unsigned char EEPROM_ReadByte(unsigned char addr)

{

  while(RD || WR);

  EEADR=addr;

  RD = 1;

  return EEDATA;

}

//-----------------------------------------------------

Также нам будет интересно писать и читать данные других типов.

Добавим функции записи и чтения двухбайтовой целочисленной беззнаковой величины в память EEPROM и из неё

//-----------------------------------------------------

void EEPROM_WriteWord(unsigned char addr, unsigned int ucData)

{

  EEPROM_WriteByte(addr, (unsigned char) ucData);

  unsigned char dt = ucData>>8;

  EEPROM_WriteByte(addr+1, dt);

}

//-----------------------------------------------------

unsigned int EEPROM_ReadWord(unsigned char addr)

{

  unsigned int dt = EEPROM_ReadByte(addr+1)*256;

  dt += EEPROM_ReadByte(addr);

  return dt;

}

//-----------------------------------------------------

Здесь у нас всё ещё проще. Мы читаем и пишем раздельно старший и младший байты, пользуясь уже добавленными функциями чтения и записи байтов.

Теперь добавим ещё функции записи и чтения четырёхбайтовых величин (двойных слов)

//-----------------------------------------------------

void EEPROM_WriteDword(unsigned char addr, unsigned long ucData)

{

  EEPROM_WriteWord(addr, (unsigned int) ucData);

  unsigned int dt = ucData>>16;

  EEPROM_WriteWord(addr+2, dt);

}

//-----------------------------------------------------

unsigned long EEPROM_ReadDword(unsigned char addr)

{

  unsigned long dt = EEPROM_ReadWord(addr+2)*65536;

  dt += EEPROM_ReadWord(addr);

  return dt;

}

//-----------------------------------------------------

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

Теперь давайте запишем строку символов по определённому адресу

//-----------------------------------------------------

void EEPROM_WriteString(unsigned char addr, char* str1)

{

  unsigned char n;

  for(n=0;str1[n]!='';n++)

  EEPROM_WriteByte(addr+n,str1[n]);

}

//-----------------------------------------------------

Здесь также всё элементарно. Мы, инкрементируя адрес, постепенно записываем наши байты. И так до встречи с нулём.

Функцию чтения строки по определённому адресу нас написать также не затруднит

//-----------------------------------------------------

void EEPROM_ReadString(unsigned char addr, char* str1, unsigned char sz)

{

  unsigned char i;

  for (i=0;i<sz;i++) str1[i] = EEPROM_ReadByte(addr+i);

  str1[i] = 0;

}

//-----------------------------------------------------

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

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

Перейдём в файл EEPROM.h и добавим прототипы наших функций

#include <stdlib.h>

//-----------------------------------------------------

void EEPROM_WriteByte(unsigned char addr, unsigned char dt);

unsigned char EEPROM_ReadByte(unsigned char addr);

void EEPROM_WriteWord(unsigned char addr, unsigned int ucData);

unsigned int EEPROM_ReadWord(unsigned char addr);

void EEPROM_WriteDword(unsigned char addr, unsigned long ucData);

unsigned long EEPROM_ReadDword(unsigned char addr);

void EEPROM_WriteString(unsigned char addr, char* str1);

void EEPROM_ReadString(unsigned char addr, char* str1, unsigned char sz);

//-----------------------------------------------------

В следующей части урока мы проверим работу библиотеки для памяти EEPROM на практике, записав в EEPROM различные типы данных (в том числе строковый массив), а также затем отобразив его на дисплее. Также мы научимся настраивать среду программирования так, чтобы память EEPROM при перепрошивке микроконтроллера не стиралась.

Предыдущий урок Программирование МК PIC Следующая часть

Купить программатор (неоригинальный) можно здесь: PICKit3

Купить программатор (оригинальный) можно здесь: PICKit3 original

Отладочную плату PIC Open18F4520-16F877A можно приобрести здесь: PIC Open18F4520-16F877A

Дисплей LCD 20×4 можно приобрести тут: Дисплей LCD 20×4

Смотреть ВИДЕОУРОК (нажмите на картинку)

PIC Внутренняя энергонезависимая память EEPROM


Post Views:
1 189

Вот и добрались мы до третьего типа памяти, доступного на Arduino: EEPROM (англ. Electrically Erasable Programmable Read-Only Memory – электрически стираемое перепрограммируемое постоянное запоминающее устройство (ЭСППЗУ)), она же энергонезависимая память. Вспомним остальные типы памяти, Flash и SRAM, и их возможности по хранению данных:

Тип Чтение из программы Запись из программы Очистка при перезагрузке
Flash Да, PROGMEM Можно, но сложно Нет
SRAM Да Да Да
EEPROM Да Да Нет

Простыми словами: EEPROM – память, к которой мы имеем полный доступ из выполняющейся программы, т.е. можем во время выполнения читать и писать туда данные, и эти данные не сбрасываются при перезагрузке МК. Круто? Круто. Зачем?

  • Хранение настроек, изменяющихся “из меню” устройства, без перепрошивки;
  • Калибровка, сохранение калибровочных данных;
  • Использование как дополнительной SRAM памяти в случае её нехватки;
  • “Чёрный ящик” – постоянная запись показаний с датчиков для дальнейшей расшифровки сбоев;
  • Запись состояния рабочего процесса для восстановления работы после внезапной перезагрузки.

Единственный важный момент: EEPROM имеет ресурс по количеству перезаписи ячеек. Производитель гарантирует 100 000 циклов записи каждой ячейки (AVR Arduino), по факту это количество зависит от конкретного чипа и температурных условий, независимые тесты показали 3-6 миллионов циклов перезаписи при комнатной температуре до появления первой ошибки, т.е. заявленные 100 000 взяты с очень большим запасом. Но есть небольшое уточнение – при заявленных 100 000 циклах перезаписи гарантируется сохранность записанных данных в течение 100 лет при температуре 24°C, если перезаписывать по миллиону – данные испортятся быстрее. В то же время количество чтений каждой ячейки неограниченно.

У МК esp8266/esp32 EEPROM эмулируется из Flash памяти, а её ресурс сильно меньше – производитель гарантирует всего 10 000 циклов записи!

EEPROM представляет собой область памяти, состоящую из элементарных ячеек с размером в один байт (как SRAM). Объём EEPROM разный у разных моделей МК:

  • ATmega328 (Arduino UNO, Nano, Pro Mini): 1 кБ
  • ATmega2560 (Arduino Mega): 4 кБ
  • ATtiny85 (Digispark): 512 Б
  • ESP8266 / ESP32: 4096 Б

Основная задача при работе с EEPROM – не напутать с адресами, потому что каждый байт имеет свой адрес. Если вы пишете двухбайтные данные, то они займут два байта, и следующие данные нужно будет писать по адресу как минимум +2 к предыдущему, иначе они “перемешаются”. Рассмотрим пример хранения набора данных разного типа, расположенных в памяти последовательно друг за другом (в скобках я пишу размер текущего типа данных, на размер которого увеличится адрес для следующего “блока”):

  • byte – адрес 0 (+1)
  • byte – адрес 1 (+1)
  • int – адрес 2 (+2) (+4 для esp8266)
  • byte – адрес 4 (+1)
  • float – адрес 5 (+4)
  • int – адрес 9 (+2)
  • и так далее

Важный момент: все ячейки имеют значение по умолчанию (у нового чипа) 255.

Скорость работы с EEPROM (время не зависит от частоты системного клока):

  • Запись одного байта занимает ~3.3 мс (миллисекунды)
  • Чтение одного байта занимает ~0.4 мкс (микросекунды)

Возможны искажения при записи данных в EEPROM при слишком низком VCC (напряжении питания), настоятельно рекомендуется использовать BOD или вручную мониторить напряжение перед записью.

При использовании внутреннего тактового генератора на 8 МГц, его отклонение не должно быть выше 10% (7.2-8.8 МГц), иначе запись в EEPROM или FLASH скорее всего будет производиться с ошибками. Соответственно все разгоны внутреннего клока недопустимы при записи EEPROM или FLASH.

Для работы с EEPROM в среде Arduino у нас есть целых две библиотеки, вторая является более удобной “оболочкой” для первой. Рассмотрим их обе, потому что в “чужом скетче” может встретиться всё что угодно, да и совместное использование этих двух библиотек делает работу с EEPROM невероятно удобной.

Библиотека avr/eeprom.h


Описание к этой библиотеке я спрятал под спойлер, потому что она не очень актуальна и знать о ней необязательно. Также она не работает на esp8266/32 по понятным причинам.

avr/eeprom.h

Стандартная библиотека eeprom.h идёт в комплекте с компилятором avr-gcc, который компилирует наши скетчи из под Arduino IDE. Полную документацию можно почитать здесь. Для подключения библиотеки в скетч пишем #include <avr/eeprom.h> Библиотека имеет набор функций для работы с целочисленными типами данных (byte – 1 байт, word – 2 байта, dword – 4 байта), float, и block “блоков” – наборов данных любого формата (структуры, массивы, и т.д.). Под работой подразумевается запись, чтение и обновление. Обновление – крайне важный инструмент, позволяющий избежать лишних перезаписей ячеек памяти. Обновление делает запись, если записываемое значение отличается от текущего в этой ячейке. Чтение:

  • eeprom_read_byte(адрес) – вернёт значение
  • eeprom_read_word(адрес) – вернёт значение
  • eeprom_read_dword(адрес) – вернёт значение
  • eeprom_read_float(адрес) – вернёт значение
  • eeprom_read_block(адрес в SRAM, адрес в EEPROM, размер) – прочитает содержимое по адрес в EEPROM в адрес в SRAM

Запись:

  • eeprom_write_byte(адрес, значение)
  • eeprom_write_word(адрес, значение)
  • eeprom_write_dword(адрес, значение)
  • eeprom_write_float(адрес, значение)
  • eeprom_write_block(адрес в SRAM, адрес в EEPROM, размер) – запишет содержимое по адрес в SRAM в адрес в EEPROM

Обновление:

  • eeprom_update_byte(адрес, значение)
  • eeprom_update_word(адрес, значение)
  • eeprom_update_dword(адрес, значение)
  • eeprom_update_float(адрес, значение)
  • eeprom_update_block(адрес в SRAM, адрес в EEPROM, размер) – обновит содержимое по адрес в SRAM в адрес в EEPROM

Макросы:

  • _EEPUT(addr, val) – записывает (write) байт val по адресу addr. Приведение типов не требуется (оно сделано в макросе)
  • _EEGET(val, addr) – читает байт по адресу addr и записывает его в переменную val. Приведение типов не требуется (оно сделано в макросе)

Рассмотрим простой пример, в котором происходит запись и чтение единичных типов данных в разные ячейки:

#include <avr/eeprom.h>

void setup() {
  Serial.begin(9600);
  
  // объявляем данные разных типов
  byte dataB = 120;
  float dataF = 3.14;
  int16_t dataI = -634;  

  // пишем друг за другом
  eeprom_write_byte(0, dataB);  // 1 байт
  eeprom_write_float(1, dataF);  // 4 байта

  // для разнообразия "обновим"
  eeprom_update_word(5, dataI);

  // объявляем переменные, куда будем читать
  byte dataB_read = 0;
  float dataF_read = 0;
  int16_t dataI_read = 0;

  // читаем
  dataB_read = eeprom_read_byte(0);
  dataF_read = eeprom_read_float(1);
  dataI_read = eeprom_read_word(5);

  // выведет 120 3.14 -634
  Serial.println(dataB_read);
  Serial.println(dataF_read);
  Serial.println(dataI_read);
}

void loop() {}

Хранить данные таким образом не очень удобно, потому что менеджмент адресов приходится проводить вручную, считать количество байт в каждом типе и “сдвигать” адрес на нужное количество. Гораздо удобнее хранить разношёрстные данные в структурах, про них мы подробнее говорили в уроке про типы данных. Мы должны передать функции адрес данных в памяти (оператор &), по сути – указатель, а также преобразовать его к типу void*, потому что функция чтения/записи блока принимает именно такой тип. Подробнее про указатели мы говорили в отдельном уроке. Также функции чтения/записи блока нужно передать размер блока данных в количестве байт. Это можно сделать вручную (числом), но лучше использовать sizeof(), которая посчитает этот размер и передаст в функцию.

#include <avr/eeprom.h>

void setup() {
  Serial.begin(9600);

  // объявляем структуру
  struct MyStruct {
    byte a;
    int b;
    float c;
  };

  // создаём и заполняем структуру
  MyStruct myStruct;
  myStruct.a = 10;
  myStruct.b = 1000;
  myStruct.c = 3.14;

  // записываем по адресу 10, указав размер структуры и приведя к void*
  eeprom_write_block((void*)&myStruct, 10, sizeof(myStruct));

  // создаём новую пустую структуру
  MyStruct newStruct;

  // читаем из адреса 10
  eeprom_read_block((void*)&newStruct, 10, sizeof(newStruct));

  // проверяем
  // выведет 10 1000 3.14
  Serial.println(newStruct.a);
  Serial.println(newStruct.b);
  Serial.println(newStruct.c);
}

void loop() {}

Точно так же можно хранить массивы:

#include <avr/eeprom.h>

void setup() {
  Serial.begin(9600);

  // создаём массив
  float dataF[] = {3.14, 60.25, 9132.5, -654.3};

  // записываем по адресу 20, указав размер
  eeprom_write_block((void*)&dataF, 20, sizeof(dataF));

  // создаём новую пустой массив такого же типа и размера!
  float dataF_read[4];

  // читаем из адреса 20
  eeprom_read_block((void*)&dataF_read, 20, sizeof(dataF_read));

  // проверяем
  // выведет 3.14 60.25 9132.5 -654.3
  for (byte i = 0; i < 4; i++)
    Serial.println(dataF_read[i]);
}

void loop() {}

В библиотеке avr/eeprom.h есть ещё один очень полезный инструмент – EEMEM, он позволяет сделать автоматическую адресацию данных путём создания указателей, значение которым присвоит компилятор. Рассмотрим пример, в котором запишем в EEPROM несколько переменных, структуру и массив, раздав им автоматически адреса. Важный момент! Адреса задаются снизу вверх по порядку объявления EEMEM, я подпишу их в примере:

#include <avr/eeprom.h>
struct MyStruct {
  byte val1;
  int val2;
  float int3;
};

uint8_t EEMEM byteAddr;     // 27
uint16_t EEMEM intAddr;     // 25
uint32_t EEMEM longAddr;    // 21
MyStruct EEMEM myStructAddr;// 14
int EEMEM intArrayAddr[5];  // 4
float EEMEM floatAddr;      // 0

EEMEM сам раздаёт адреса, основываясь на размере данных. Важный момент: данный подход не занимает дополнительного места в памяти, т.е. нумерация адресов вручную цифрами, без создания EEMEM “переменных”, не занимает меньше памяти! Давайте вернёмся к нашему первому примеру и перепишем его с EEMEM. При указании адреса через EEMEM нужно использовать оператор взятия адреса &

#include <avr/eeprom.h>
byte EEMEM dataB_addr;
float EEMEM dataF_addr;
int16_t EEMEM dataI_addr;

void setup() {
  Serial.begin(9600);

  // объявляем данные разных типов
  byte dataB = 120;
  float dataF = 3.14;
  int16_t dataI = -634;

  // пишем друг за другом
  eeprom_write_byte(&dataB_addr, dataB);
  eeprom_write_float(&dataF_addr, dataF);

  // для разнообразия "обновим"
  eeprom_update_word(&dataI_addr, dataI);

  // объявляем переменные, куда будем читать
  byte dataB_read = 0;
  float dataF_read = 0;
  int16_t dataI_read = 0;

  // читаем
  dataB_read = eeprom_read_byte(&dataB_addr);
  dataF_read = eeprom_read_float(&dataF_addr);
  dataI_read = eeprom_read_word(&dataI_addr);

  // выведет 120 3.14 -634
  Serial.println(dataB_read);
  Serial.println(dataF_read);
  Serial.println(dataI_read);
}

void loop() {}

Ну и напоследок, запись и чтение блока через EEMEM. Адрес придётся преобразовать в (const void*) вручную:

#include <avr/eeprom.h>
// получим адрес (тут будет 0)
int EEMEM intArrayAddr[5];

void setup() {
  Serial.begin(9600);

  // создаём массив
  int intArrayWrite[5] = {10, 20, 30, 40, 50};

  // пишем по адресу intArrayAddr
  eeprom_write_block((void*)&intArrayWrite, (const void*)&intArrayAddr, sizeof(intArrayWrite));

  // создаём новый массив для чтения
  int intArrayRead[5];

  // читаем по адресу intArrayAddr
  eeprom_read_block((void*)&intArrayRead, (const void*)&intArrayAddr, sizeof(intArrayRead));

  // проверим
  for (byte i = 0; i < 5; i++)
    Serial.println(intArrayRead[i]);
}

void loop() {}

Таким образом можно добавлять “данные” для хранения в EEPROM прямо по ходу разработки программы, не думая об адресах. Рекомендую добавлять новые данные над старыми, чтобы адресация не сбивалась (напомню, адресация идёт снизу вверх, начиная с нуля).

Библиотека EEPROM.h


Библиотека EEPROM.h идёт в комплекте с ядром Arduino и является стандартной библиотекой. По сути EEPROM.h – это удобная оболочка для avr/eeprom.h, чуть расширяющая её возможности и упрощающая использование.

Для AVR Arduino: подключая в скетч EEPROM.h мы автоматически подключаем avr/eeprom.h и можем пользоваться её фишками, такими как EEMEM.

Рассмотрим инструменты, которые нам предлагает библиотека:

  • EEPROM.write(адрес, данные) – пишет данные (только byte!) по адресу
  • EEPROM.update(адрес, данные) – обновляет (та же запись, но лучше) байт данных, находящийся по адресу. Не реализована для esp8266/32!
  • EEPROM.read(адрес) – читает и возвращает байт данных, находящийся по адресу
  • EEPROM.put(адрес, данные) – записывает (по факту – обновляет, update) данные любого типа (типа переданной переменной) по адресу
  • EEPROM.get(адрес, данные) – читает данные по адресу и сам записывает их в данные – указанную переменную
  • EEPROM[] – библиотека позволяет работать с EEPROM памятью как с обычным массивом типа byte (uint8_t)

У esp8266 и esp32 есть отличия:

  • Перед началом работы нужно вызвать EEPROM.begin(размер) с указанием максимального объёма памяти: 4.. 4096 Байт.
  • Для применения записи нужно вызвать EEPROM.commit(): например несколько раз делается write(), put(), и в завершение – commit()
  • В некоторых версиях SDK отсутствует EEPROM.update()

В отличие от avr/eeprom.h у нас нет отдельных инструментов для работы с конкретными типами данных, отличными от byte, и сделать write/update/read для float/long/int мы не можем. Но зато у нас есть всеядные put и get, которые очень удобно использовать! Рассмотрим пример с чтением/записью байтов:

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  //EEPROM.begin(100);   // для esp8266/esp32
  
  // пишем 200 по адресу 10
  EEPROM.update(10, 200);
  //EEPROM.commit();     // для esp8266/esp32
  Serial.println(EEPROM.read(10));  // выведет 200
  Serial.println(EEPROM[10]);       // выведет 200
}

void loop() {}

Логика работы с адресами такая же, как в предыдущем пункте урока! Обратите внимание на работу с EEPROM как с массивом, можно читать, писать, сравнивать, и даже использовать составные операторы, например EEPROM[0] += 10 , но это работает только для элементарных ячеек, байтов.

Теперь посмотрим, как работает put() и get():

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  //EEPROM.begin(100);   // для esp8266/esp32

  // объявляем переменные, которые будем писать
  float dataF = 3.14;
  int16_t dataI = -634;
  byte dataArray[] = {10, 20, 30, 40};

  EEPROM.put(0, dataF);
  EEPROM.put(4, dataI);
  EEPROM.put(6, dataArray);
  //EEPROM.commit();     // для esp8266/esp32

  // объявляем переменные, куда будем читать
  float dataF_read = 0;
  int16_t dataI_read = 0;
  byte dataArray_read[4];

  // читаем точно так же, как писали
  EEPROM.get(0, dataF_read);
  EEPROM.get(4, dataI_read);
  EEPROM.get(6, dataArray_read);

  // проверяем
  Serial.println(dataF_read);
  Serial.println(dataI_read);
  Serial.println(dataArray_read[0]);
  Serial.println(dataArray_read[1]);
  Serial.println(dataArray_read[2]);
  Serial.println(dataArray_read[3]);
}

void loop() {}

put() и get() сами определяют тип данных и считают размер блока данных, использовать их очень приятно. Они работают как с массивами, так и со структурами.

EEPROM.h + структуры


Самый удобный хранить набор данных в EEPROM – структура (разбирали в уроке про типы данных). Структура позволяет объединить любые данные под одним именем, и одной строчкой загонять их в EEPROM и так же читать обратно. А также не придётся думать об адресации! Пример:

#include <EEPROM.h>

struct Data {
  byte bright = 0;
  int counter = 0;
  float fvalue = 0;
};

// глобальный экземпляр для личного использования
Data data;

void setup() {
  EEPROM.get(0, data);   // прочитать из адреса 0
  // меняем
  data.bright = 10;
  data.counter = 1234;
  data.fvalue = 3.14;
  EEPROM.put(0, data);   // поместить в EEPROM по адресу 0
}

void loop() {}

EEPROM.h + avr/eeprom.h


Пример не очень актуален, используй EEPROM + структуры

EEPROM.h + avr/eeprom.h

Ну и конечно же, можно использовать одновременно все преимущества обеих библиотек, например автоматическую адресацию EEMEM и put/get. Рассмотрим на предыдущем примере, вместо ручного задания адресов используем EEMEM, но величину придётся привести к целочисленному типу, сначала взяв от него адрес, т.е. (int)&адрес_еемем

#include <EEPROM.h>
float EEMEM dataF_addr;
int16_t EEMEM dataI_addr;
byte EEMEM dataArray_addr[5];

void setup() {
  Serial.begin(9600);

  // объявляем переменные, которые будем писать
  float dataF = 3.14;
  int16_t dataI = -634;
  byte dataArray[] = {10, 20, 30, 40};

  EEPROM.put((int)&dataF_addr, dataF);
  EEPROM.put((int)&dataI_addr, dataI);
  EEPROM.put((int)&dataArray_addr, dataArray);

  // объявляем переменные, куда будем читать
  float dataF_read = 0;
  int16_t dataI_read = 0;
  byte dataArray_read[4];

  // читаем точно так же, как писали
  EEPROM.get((int)&dataF_addr, dataF_read);
  EEPROM.get((int)&dataI_addr, dataI_read);
  EEPROM.get((int)&dataArray_addr, dataArray_read);
  EEPROM[0] += 10;

  // проверяем
  Serial.println(dataF_read);
  Serial.println(dataI_read);
  Serial.println(dataArray_read[0]);
  Serial.println(dataArray_read[1]);
  Serial.println(dataArray_read[2]);
  Serial.println(dataArray_read[3]);
}

void loop() {}

С возможностями библиотек разобрались, перейдём к практике.

Реальный пример


Рассмотрим пример, в котором происходит следующее: две кнопки управляют яркостью светодиода, подключенного к ШИМ пину. Установленная яркость сохраняется в EEPROM, т.е. при перезапуске устройства будет включена яркость, установленная последний раз. Для опроса кнопок используется библиотека GyverButton. Для начала посмотрите на первоначальную программу, где установленная яркость не сохраняется. Программу можно чуть оптимизировать, но это не является целью данного урока.

Меняем яркость кнопками

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <GyverButton.h>

GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

int LEDbright = 0;

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход
}

void loop() {
  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  analogWrite(LED_PIN, LEDbright);    // изменили яркость
}

В этот код нам нужно добавить:

  • Подключить библиотеку EEPROM.h
  • При запуске: чтение яркости из EEPROM и включение светодиода
  • При клике: запись актуального значения в EEPROM

Сохранение яркости

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <EEPROM.h>
#include <GyverButton.h>

GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

int LEDbright = 0;

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход
  EEPROM.get(0, LEDbright); // прочитали яркость из адреса 0
  analogWrite(LED_PIN, LEDbright);  // включили
}

void loop() {
  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  EEPROM.put(0, LEDbright);           // записали по адресу 0
  analogWrite(LED_PIN, LEDbright);    // изменили яркость
}

Итак, теперь при запуске у нас восстанавливается последняя настроенная яркость, и при изменении она записывается. Напомню, что EEPROM изнашивается от перезаписи. Конечно для того, чтобы “накликать” яркость несколько миллионов раз и убить ячейку, у вас уйдёт очень много времени, но процесс записи нового значения можно и нужно оптимизировать, особенно в более серьёзных проектах, ниже поговорим об этом подробнее. Также в нашем коде есть ещё один неприятный момент: при самом первом запуске после прошивки EEPROM не инициализирована, каждая ячейка хранит в себе число 255, и именно такое значение примет переменная LEDbright после первого запуска, при так называемом “первом чтении”. Здесь это не имеет значения, но в более серьёзном устройстве нужно будет задать нужные значения по умолчанию в EEPROM при первом запуске, об этом мы тоже поговорим ниже. Иначе представьте, какие “настройки по умолчанию” получит ваше устройство для яркости/скорости/громкости/номера режима/прочее!

Запись и чтение строк


У нас есть два типа строк: массивы символов и String-строки. С массивом символов всё более-менее понятно: это массив, он имеет фиксированный размер, его можно записать при помощи put() и прочитать при помощи get(). Также такая строка может входить в структуру, что очень удобно. В этом случае нужно объявить структуру с указанием максимальной длины строки, которая может там храниться. Например для какого-нибудь проекта с WiFi нам хочется хранить логин и пароль от роутера и режим работы:

struct Cfg {
  char ssid[16];
  char pass[16];
  byte mode;
};

Структуру очень просто прочитать и записать, а работать со строками в ней можно при помощи стандартных  строковых функций.

А как записать и прочитать динамические данные, такие как String-строки? Можно рассмотреть два способа: с массивом ограниченной длины (как в примере выше) и полностью динамическое хранение.

Будем считать, что максимальная длина строки – 20 символов. Простой пример:

#include <EEPROM.h>
#define STR_ADDR 0  // адрес хранения строки в EEPROM


void setup() {
  Serial.begin(115200);

  // читаем
  char str[20];
  EEPROM.get(STR_ADDR, str);

  // выводим
  Serial.print("Read text: ");
  Serial.println(str);
}

void loop() {
  // читаем строку из порта
  if (Serial.available()) {
    char str[20];
    int len = Serial.readBytes(str, 20);

    // завершающий символ, добавляем вручную
    str[len] = 0;

    // записываем
    EEPROM.put(STR_ADDR, str);
    
    Serial.print("Save text: ");
    Serial.println(str);
  }
}

При динамическом хранении мы будем сохранять также длину строки, в первой ячейке от которой идёт счёт. А уже дальше – саму строку. Писать и читать будем посимвольно, по другому тут уже не получится:

#include <EEPROM.h>

#define STR_ADDR 0  // адрес хранения строки в EEPROM

void setup() {
  Serial.begin(115200);
  
  String str;
  int len = EEPROM.read(STR_ADDR);  // читаем длину строки
  str.reserve(len);    // резервируем место (для оптимальности)

  // читаем
  for (int i = 0; i < len; i++) {
    str += (char)EEPROM.read(STR_ADDR + 1 + i);
  }
  
  // выводим
  Serial.print("Read text: ");
  Serial.println(str);
}

void loop() {
  // читаем строку из порта
  if (Serial.available()) {
    String inc = Serial.readString();
    Serial.print("Save text: ");
    Serial.println(inc);
    
    int len = inc.length();   // длина строки
    EEPROM.write(STR_ADDR, len);  // записываем её
    // и далее саму строку посимвольно
    for (int i = 0; i < len; i++) {
      EEPROM.write(STR_ADDR + 1 + i, inc[i]);
    }
  }
}

Полезные трюки


Инициализация


Под инициализацией я имею в виду установку значений ячеек в EEPROM “по умолчанию” во время первого запуска устройства. В рассмотренном выше примере мы действовали в таком порядке:

  1. Чтение из EEPROM в переменную
  2. Использование переменной по назначению

При первом запуске кода (и при всех дальнейших, в которых в ячейку ничего нового не пишется) переменная получит значение, которое было в EEPROM по умолчанию. В большинстве случаев это значение не подойдёт устройству, например ячейка хранит номер режима, по задумке разработчика – от 0 до 5, а из EEPROM мы прочитаем 255. Непорядок! При первом запуске нужно инициализировать EEPROM так, чтобы устройство работало корректно, для этого нужно определить этот самый первый запуск. Можно сделать это вручную, прошив программу, которая забьёт EEPROM нужными данными. Далее прошить уже рабочую программу. При разработке программы это очень неудобно, ведь количество сохраняемых данных может меняться в процессе разработки, поэтому можно использовать следующий алгоритм:

  1. Резервируем какую-нибудь ячейку (например, последнюю) под хранение “ключа” первого запуска
  2. Читаем ячейку, если её содержимое не совпадает с ключом – это первый запуск!
  3. В обработчике первого запуска пишем в ячейку нужный ключ
  4. Пишем в остальные ячейки необходимые значения по умолчанию
  5. И после этого уже читаем данные во все нужные переменные

Рассмотрим на всё том же примере со светодиодом и кнопками:

Сохранение яркости

#define INIT_ADDR 1023  // номер резервной ячейки
#define INIT_KEY 50     // ключ первого запуска. 0-254, на выбор

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <EEPROM.h>
#include <GyverButton.h>

GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

int LEDbright = 0;

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход

  if (EEPROM.read(INIT_ADDR) != INIT_KEY) { // первый запуск
    EEPROM.write(INIT_ADDR, INIT_KEY);    // записали ключ

    // записали стандартное значение яркости
    // в данном случае это значение переменной, объявленное выше
    EEPROM.put(0, LEDbright);
  }
  EEPROM.get(0, LEDbright); // прочитали яркость
  analogWrite(LED_PIN, LEDbright);  // включили
}

void loop() {
  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  EEPROM.put(0, LEDbright);           // записали
  analogWrite(LED_PIN, LEDbright);    // изменили яркость
}

Теперь при первом запуске мы получим инициализацию нужных ячеек. Если нужно переинициализировать EEPROM, например в случае добавления новых данных, достаточно изменить наш ключ на любое другое значение в пределах одного байта (0-254). Я пишу именно до 254, потому что 255 является значением ячейки по умолчанию и наш трюк не сработает.

Сброс до “заводских”


Чтобы вернуть настройки к изначально заданным в программе, нужно “спровоцировать” инициализацию. Очевидный способ сделать это – изменить ключ инициализации, который мы назвали INIT_KEY. Либо можно просто вызвать EEPROM.put(адрес, базовые настройки) в нужном месте программы.

Скорость


Как я писал выше, скорость работы с EEPROM составляет:

  • Запись/обновление одного байта занимает ~3.3 мс (миллисекунды)
  • Чтение одного байта занимает ~0.4 мкс (микросекунды)

При большом желании можно использовать ячейку вместо переменной, т.е. выше мы с вами рассматривали пример, в котором EEPROM читался в переменную в программе, и дальнейшая работа происходила уже с ней. При сильной нехватке оперативной памяти можно читать значение напрямую из EEPROM, ведь это занимает ничтожно мало времени. А вот с записью всё гораздо хуже, там целых 3.3 мс. Например так:

analogWrite(LED_PIN, EEPROM.read(0));   // изменили яркость

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

#define GET_MODE EEPROM.read(0)     // получить номер режима
#define GET_BRIGHT EEPROM.read(1)   // получить яркость
#define SET_MODE(x) EEPROM.write(0, (x))  // запомнить режим
#define SET_BRIGHT(x) EEPROM.put(1, (x))  // запомнить яркость

Получим удобные макросы, с которыми писать код будет чуть быстрее и удобнее, т.е. строка SET_MODE(3) запишет 3 в ячейку 0

Уменьшение износа


Важная тема: уменьшение износа ячеек частыми перезаписями. Ситуаций может быть много, интересных решений для них – тоже. Рассмотрим простейший пример – всё тот же код со светодиодом и кнопкой. Делать будем следующее: записывать новое значение будем только в том случае, если после последнего нажатия на кнопку прошло какое-то время. То есть нам понадобится таймер (воспользуемся таймером на millis), при нажатии на кнопку таймер будет сбрасываться, а при срабатывании таймера будем писать актуальное значение в EEPROM. Также понадобится флаг, который будет сигнализировать о записи и позволит записать именно один раз. Алгоритм такой:

  • При нажатии на кнопку:
    • Если флаг опущен – поднять флаг
    • Сбросить таймер
  • Если сработал таймер и флаг поднят:
    • Опустить флаг
    • Записать значения в EEPROM

Посмотрим на всё том же примере:

Сохранение яркости

#define INIT_ADDR 1023  // номер резервной ячейки
#define INIT_KEY 50     // ключ первого запуска. 0-254, на выбор

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <EEPROM.h>
#include <GyverButton.h>

GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

int LEDbright = 0;
uint32_t eepromTimer = 0;
boolean eepromFlag = false;

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход

  if (EEPROM.read(INIT_ADDR) != INIT_KEY) { // первый запуск
    EEPROM.write(INIT_ADDR, INIT_KEY);    // записали ключ

    // записали стандартное значение яркости
    // в данном случае это значение переменной, объявленное выше
    EEPROM.put(0, LEDbright);
  }
  EEPROM.get(0, LEDbright); // прочитали яркость
  analogWrite(LED_PIN, LEDbright);  // включили
}

void loop() {
  // проверка EEPROM
  checkEEPROM();

  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  analogWrite(LED_PIN, LEDbright);          // изменили яркость
  eepromFlag = true;                        // поднять флаг
  eepromTimer = millis();                   // сбросить таймер
}

void checkEEPROM() {
  // если флаг поднят и с последнего нажатия прошло 10 секунд (10 000 мс)
  if (eepromFlag && (millis() - eepromTimer >= 10000) ) {
    eepromFlag = false;           // опустили флаг
    EEPROM.put(0, LEDbright);     // записали в EEPROM
  }
}

Вот таким нехитрым способом мы многократно снизили износ EEPROM, я очень часто использую этот “алгоритм” работы с настройками в своих устройствах. Есть другие задачи, в которых данные в EEPROM пишутся не когда пользователь что-то изменит, а постоянно, т.е. память работает в режиме чёрного ящика и постоянно записывает значения. Это может быть например контроллер печи, который держит температурный режим по специальному закону, и после внезапной перезагрузки должен вернуться к тому месту в процессе, на котором прервался. Тут есть глобально два варианта:

  • Ёмкий конденсатор по питанию микроконтроллера, позволяющий сохранить работу МК после отключения питания на время, достаточное для записи в EEPROM (~3.3 мс). Также МК должен знать о том, что общее питание отключилось: если это высокое напряжение (выше 5 Вольт), то это может быть делитель напряжения на аналоговый пин. Если это 5 Вольт – можно измерять напряжение МК, и момент отключения (разрядка конденсатора) тоже можно отловить и записать нужные данные. Можно взвести прерывание, которое сработает при падении напряжения питания ниже опасного уровня. Можно 5 Вольт завести напрямую на цифровой пин, а сам МК питать через диод и поставить конденсатор – тогда напряжение на измеряющем пине пропадёт до того, как отключится МК, он будет работать от конденсатора. Вот схема:
  • blank
  • Можно писать данные (необязательно один байт, можно целую структуру) хитро, размазывая их по всему EEPROM. Тут глобально два варианта:
    • Писать данные каждый раз в следующую ячейку, и закольцевать переход на первую. Также понадобится хранить где-то счётчик, указывающий на адрес текущей ячейки, и этот счётчик тоже придётся хранить хитро, чтобы он не износил ячейку. Например счётчик – это структура, состоящая из счётчика перезаписей этой структуры и счётчика адреса для большой структуры.
    • Писать данные, пока не достигнут лимит количества перезаписей, количество текущих перезаписей хранить например в этой же структуре. Скажем структура занимает 30 байт, то есть в перспективе мы можем найти эту структуру по адресу, кратному 30. Программа работает, счётчик считает количество перезаписей, при достижении опасного количества вся структура “переезжает” на следующие 30 адресов.

Вариантов уменьшения износа ячеек EEPROM можно придумать много, уникально под свою ситуацию. Есть даже библиотеки готовые, например EEPROMWearLevel. Есть очень интересная статья на Хабре, там рассмотрено ещё несколько хороших алгоритмов и даны ссылки на ещё большее их количество.

Библиотека EEManager


Я часто использую EEPROM в своих проектах, поэтому обернул все рассмотренные выше конструкции в библиотеку, изучить и скачать можно здесь. Библиотека подходит для всех архитектур, в которых есть стандартная EEPROM.h. В библиотеке реализовано:

  • Работа с данными любого типа
  • Чтение и запись в указанную переменную
  • Функция “ключа первого запуска” для задания начальных значений
  • Отложенное обновление по тайм-ауту для уменьшения износа

Я надеюсь вы полностью разобрались с самым последним примером с кнопкой и светодиодом, поэтому покажу работу EEManager на его основе:

EEManager, кнопка и светодиод

#define INIT_KEY 50     // ключ первого запуска. 0-254, на выбор

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <GyverButton.h>
GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

#include <EEManager.h>
int LEDbright = 0;
EEManager memory(LEDbright); // передаём переменную в менеджер

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход

  // запускаем менеджер, указав адрес и ключ запуска
  // он сам проверит ключ, а также прочитает данные
  // из EEPROM и запишет в переменную
  memory.begin(0, INIT_KEY);

  analogWrite(LED_PIN, LEDbright);  // включили
}

void loop() {
  // здесь произойдёт запись по встроенному таймеру
  memory.tick();

  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  analogWrite(LED_PIN, LEDbright);          // изменили яркость
  memory.update();                          // сообщаем, что данные нужно обновить
}

Таким образом вся работа с еепром по чтению, записи, обеспечению корректного первого запуска и уменьшению износа памяти свелась к трём строчкам кода. Пользуйтесь!

Видео


Полезные страницы


  • Набор GyverKIT – большой стартовый набор Arduino моей разработки, продаётся в России
  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макросы, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  • Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])

P062F Ошибка EEPROM модуля внутреннего управления

Код неисправности OBD-II Техническое описание

Ошибка EEPROM модуля внутреннего контроля

Что это значит?

Это общий диагностический код неисправности трансмиссии (DTC), который обычно применяется к автомобилям OBD-II. Это может включать, но не ограничивается, автомобили от Buick, Chevy, GMC, Ford, Toyota, Nissan, Mercedes, Honda, Cadillac, Suzuki, Subaru и т. Д. Хотя общие, точные шаги ремонта могут варьироваться в зависимости от года, марки, модели. и конфигурация трансмиссии.

Когда код P062F сохраняется, это означает, что модуль управления трансмиссией (PCM) обнаружил внутреннюю ошибку производительности с электронно стираемым постоянным запоминающим устройством (EEPROM). Другие контроллеры также могут обнаруживать внутреннюю ошибку производительности PCM (в EEPROM) и вызывать сохранение P062F.

Процессоры мониторинга модуля внутреннего контроля несут ответственность за выполнение различных функций самопроверки контроллера и общую подотчетность модуля внутреннего контроля. Входные и выходные сигналы EEPROM подвергаются самопроверке и постоянно контролируются PCM и другими соответствующими контроллерами. Модуль управления трансмиссией (TCM), модуль контроля тяги (TCSM) и другие контроллеры также взаимодействуют с EEPROM.

В автомобильных приложениях EEPROM предоставляет средства для чтения, стирания и перезаписи небольших объемов (байтов) программируемой памяти. Используя специальное программирование, EEPROM (или любая часть EEPROM) может быть стерта и перезаписана последовательно. EEPROM — это группа транзисторов, состоящая из трех частей. Обычно он съемный и фиксируется в специально разработанном гнезде внутри PCM. Когда неисправный PCM заменяется, EEPROM обычно необходимо удалить и повторно использовать в новом PCM. EEPROM и новый PCM нужно будет программировать как единое целое. Несмотря на то, что EEPROM допускает более 1 миллиона программных изменений и рассчитан на работу в течение сотен лет, он может быть чувствительным к чрезмерному нагреву и влажности.   

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

Если PCM обнаруживает несоответствия в функциональности EEPROM, код P062F будет сохранен, и может загореться индикаторная лампа неисправности (MIL). Кроме того, если PCM обнаруживает проблему между любым из бортовых контроллеров, которая указывает на внутреннюю ошибку EEPROM, код P062F будет сохранен, и может загореться индикаторная лампа неисправности (MIL). Для включения контрольной лампы MIL может потребоваться несколько циклов отказа, в зависимости от предполагаемой серьезности неисправности.

Фотография ПКМ со снятой крышкой: P062F Ошибка EEPROM модуля внутреннего управления

Какова серьезность этого кода неисправности?

Коды процессора модуля внутреннего контроля следует отнести к категории серьезных. Сохраненный код P062F может вызвать различные проблемы с управляемостью.

Каковы некоторые симптомы кода?

Симптомы кода неисправности P062F могут включать:

  • Широкий спектр проблем с управляемостью двигателя / трансмиссии
  • Нет условия запуска
  • Сниженная топливная эффективность
  • Заглох двигателя или остановка на холостом ходу
  • Отсутствие работы охлаждающего вентилятора

Каковы некоторые из распространенных причин появления кода?

Причины этого кода неисправности P062F могут включать:

  • Неисправный контроллер или ошибка программирования
  • Перегретый PCM
  • Повреждение водой
  • Неисправное реле питания контроллера или перегоревший предохранитель
  • Обрыв или короткое замыкание в цепи или разъемах в жгуте CAN
  • Недостаточное заземление модуля управления
  • Неисправный EEPROM

Каковы некоторые шаги по устранению неполадок P062F?

Даже для самого опытного и хорошо оснащенного профессионального специалиста диагностика кода P062F может оказаться сложной задачей. Также существует проблема перепрограммирования. Без необходимого оборудования для перепрограммирования невозможно будет заменить неисправный контроллер и провести успешный ремонт.

Если есть коды блока питания ECM / PCM, их, очевидно, необходимо исправить, прежде чем пытаться диагностировать P062F.

Есть несколько предварительных тестов, которые могут быть выполнены до того, как будет объявлено о неисправности отдельного контроллера. Потребуются диагностический сканер, цифровой вольт-омметр (ДВОМ) и источник достоверной информации о транспортном средстве.

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

При попытке диагностировать P062F информация может быть вашим лучшим инструментом. Найдите в источнике информации о транспортном средстве бюллетени технического обслуживания (TSB), которые соответствуют сохраненному коду, транспортному средству (год, марка, модель и двигатель) и отображаемым симптомам. Если вы найдете правильный TSB, он может предоставить диагностическую информацию, которая поможет вам в значительной степени.

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

Используйте DVOM для проверки предохранителей и реле блока питания контроллера. Проверьте и при необходимости замените перегоревшие предохранители. Предохранители следует проверять при нагруженной цепи.

Если все предохранители и реле работают должным образом, необходимо провести визуальный осмотр проводки и жгутов, связанных с контроллером. Вы также захотите проверить заземление шасси и двигателя. Используйте свой источник информации о транспортном средстве, чтобы получить местоположения заземления для связанных цепей. Используйте DVOM для проверки целостности заземления.

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

Если цепи питания и заземления контроллера не повреждены, следует подозревать неисправный контроллер или ошибку программирования контроллера. Замена контроллера потребует перепрограммирования. В некоторых случаях вы можете приобрести перепрограммированные контроллеры на вторичном рынке. Для других транспортных средств / контроллеров потребуется перепрограммирование на борту, которое может быть выполнено только через дилерский центр или другой квалифицированный источник.

  • В отличие от большинства других кодов, P062F, вероятно, вызван неисправным контроллером или ошибкой программирования контроллера.
  • Проверьте целостность заземления системы, подключив отрицательный измерительный провод DVOM к земле, а положительный измерительный провод к напряжению батареи.

Связанные обсуждения DTC

  • Nissan Pathfinder 2019 года выпуска: код P062fЯ сделал полное ускорение, пока ехал, затем двигатель остановился, и я остановился. Я попытался завести двигатель, но он сразу выключился. Я отбуксировал его механику, который проверил OBD и обнаружил ошибку P062F. двигатель работает нормально отдельно от внешнего источника топлива…. 
  • Buick Regal Hybrid P2012F 062 годаПривет всем, на этой неделе работаю над машиной жены. Автомобиль не заводился, заводился, но, похоже, не хватило батареи, чтобы перевернуться. Будучи гибридом, он действительно может начать с нуля. Запуск двигателя прошел успешно, однако мил. Вставил в него свой сканирующий прибор и вытащил код P062F. Ха … 

Нужна дополнительная помощь с кодом P062F?

Если вам все еще нужна помощь по поводу кода ошибки P062F, задайте вопрос в комментариях под этой статьей..

ПРИМЕЧАНИЕ. Эта информация представлена ​​только в информационных целях. Он не предназначен для использования в качестве рекомендаций по ремонту, и мы не несем ответственности за любые действия, которые вы предпринимаете с каким-либо автомобилем. Вся информация на этом сайте защищена авторским правом.

Введение

   В этом материале мы рассмотрим возможные проблемы при работе с EEPROM. Часть из них связана с аппаратным стороной микроконтроллера, такие как повреждение EEPROM при пониженном напряжении питания и ограниченный ресурс EEPROM, а часть с программным обеспечением, например, при использовании EEPROM в прерываниях. Также рассмотрим способы решения этих проблем и методы повышения надежности хранения данных в EEPROM.

   Одна из старых проблем AVR — это повреждение EEPROM данных при пониженном питании микроконтроллера. Это может происходить в двух случаях:

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

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

— Нужно удерживать микроконтроллер AVR в состоянии сброса, если напряжение питания находится ниже нормы. Для этого можно использовать внешние супервизоры питания или встроенный детектор пониженного питания — Brown-out Detector (BOD). Встроенный детектор управляется с помощью fuse битов микроконтроллера — BODEN и BODLEVEL. BODEN — разрешает/запрещает работу детектора, а BODLEVEL — определяет его уровень срабатывания.
   Если сброс микроконтроллера происходит во время процесса записи в EEPROM, то операция записи будет завершена только при достаточном уровне напряжения.

— Также в многие разработчике рекомендуют не использовать 0-ую ячейку EEPROM`a, поскольку именно ее содержимое чаще всего повреждается при снижении питания микроконтроллера.

Проблемы с EEPROM из-за прерываний

   Операция записи в EEPROM состоит из нескольких шагов. Вспомним эту последовательность:

1. Ожидаем готовности EEPROM, опрашивая бит EEWE регистра EECR.
2. Устанавливаем адрес в регистре EEAR.
3. Записываем байт данных в регистр EEDR.
4. Устанавливаем основной флаг разрешения записи EEMWE регистра EECE
5. Устанавливаем флаг разрешения записи EEWE регистра EECE

   Бит EEWE должен быть установлен в течении 4-ех тактов после установки бита EEMWE. Если этого не произойдет по причине прерываний, то запись в EEPROM не будет произведена. Этого легко избежать, если запретить прерывания перед 4-м шагом, а после 5-го снова разрешить их.

   Однако есть еще один подводный камень. Если прерывание возникло после 1-го, 2-го или 3-го шага, и в прерывании тоже используются операции с EEPROM (чтение или запись), то запись может не состояться, или запишутся не те данные и не туда, потому что содержимое регистров EEAR (адрес) и EEDR (данные) будет изменено.

   Описанное выше касается и процедуры чтения EEPROM.

   Лечить это можно следующими способами:

   — Не использовать операции чтения и записи EEPROM в прерываниях.
   Это особенно касается операции записи, потому что она медленная и выполняется с использованием внутреннего RC генератора. Например, для mega16 в даташите указано, что при записи в EEPROM используется внутренний RC генератор с частотой 1 МГц (независимо от установок fuse битов CKSEL) и время записи составляет 8.5 мс. Для прерывания это очень долго.

   — Запрещать прерывания на время всей процедуры записи (чтения) EEPROM, то есть в самом начале.

   — Сохранять в начале обработчика прерывания содержимое регистров EEAR (адрес) и EEDR (данные), а перед выходом восстанавливать их.

   — Использовать флаги (семафоры) для сигнализации о выполнении работы с EEPROM.
   Перед выполнением записи в основном цикле программы (или задаче, если используется ос) устанавливать программный флаг, а в прерывании (или другой задаче) проверять его.

Ресурс EEPROM

   EEPROM имеет ограниченный ресурс. Atmel гарантирует, что количество циклов перезаписи EEPROM составляет не меньше 100000. Цифра довольно большая, однако и она может быть достигнута, если записывать в EEPROM часто и на протяжении долгого времени.
   Есть два приема по «увеличению» ресурса EEPROM.
   Первый — простой и состоит в том, чтобы записывать в EEPROM данные, только если они изменили свое значение.


__eeprom uint8_t data;
uint8_t newData;

...
if (newData != data) {
data = newData;
}

   Второй- хитрый и состоит в том, чтобы хранить данные не в одной ячейки памяти (или группе ячеек, если речь идет о многобайтных переменных), а в нескольких, и записывать в них по очереди.
   Допустим, нам нужно хранить в EEPROM один байт. Выделяем под него 8 байтов и каждый раз записываем в следующую ячейку, когда доходим до последней ячейки, то записываем в первую. И так по кругу, как в кольцевом буфере. Если каждая ячейка EEPROM имеет ресурс 100000, то записывая в 8 ячеек по очереди, мы получаем ресурс перезаписи байта 800000.

EEPROM и оптимизация компилятора

   Переменные, которые объявлены, но не используются, часто удаляются компилятором в процессе оптимизации. Если такие переменные нужны, перед ними следует добавлять ключевое слово volatile.


//для IAR AVR
volatile __eeprom char name[] = "prog 12.3";

   Если используются свои функции для работы с EEPROM, то могут возникнуть проблемы при высоких уровнях оптимизации компилятора. Компилятор может объединить одинаковые (с его точки зрения) части кода в одну подпрограмму и нарушить логику работы вашей функции. Чтобы этого не происходило нужно или запрещать оптимизацию данной функции, или отключать перекрестную оптимизацию (cross call optimization) для функции или файла. Как это делается зависит от компилятора. Как правило, для этого существуют определенные ключи и прагмы.

Программные способы повышения надежности EEPROM

   

Один из простых способов повышения надежности хранения данных в EEPROM — это метод мажоритарного резервирования. Суть метода заключается в том, что для хранения данных выделяется нечетное количество ячеек памяти — N. При сохранении данных — запись производится во все выделенные ячейки. При чтении — читаются тоже все, но решение относительно содержимого принимается на основе равенства (N+1)/2 ячеек.

   Рассмотрим пример тройного мажоритарного резервирования байта данных. Для сохранения байта используются три байта EEPROM, а решение о содержимом принимается на основании равенства 2 байтов. Код приведен для компилятора IAR AVR.


//функция сохранения
void EEPROM_SaveByte(uint8_t value, uint8_t __eeprom *buf)
{
   buf[0] = value;
   buf[1] = value;
   buf[2] = value;
}

//функция считывания
uint8_t EEPROM_LoadByte(uint8_t *value, uint8_t __eeprom *buf)
{
   uint8_t a = buf[0];
   uint8_t b = buf[1];
   uint8_t c = buf[2];

   if ((a == b)||(a == c)){
      *value = a;
      return 0;
   }
   else {
      if (b == c){  
         *value = b;
         return 0;
      }
   }
   return 1;
}

....
//пример использования

__eeprom uint8_t buffer[3];
uint8_t data;

EEPROM_SaveByte(125, buffer);
EEPROM_LoadByte(&data, buffer);

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

   Другой метод повышения надежности хранимых данных состоит в использовании контрольных сумм, например CRC. Я не использовал этот метод в своей практике, поэтому о нем мало чего могу сказать.

   На этом все…

В данной статье собраны основные ошибки, которые возникают при работе с 32-разрядными микроконтроллерами.

Задание тактирования

Тактирование блока всегда должно задаваться ПЕРЕД настройкой его конфигурации!

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

Фрагмент кода 1 — Пример инициализации порта ввода-вывода

// 1 - Включаем тактирование порта С
RST_CLK_PCLKcmd (RST_CLK_PCLK_PORTC, ENABLE);

// 2 - Инициализируем порт в заданной конфигурации
PORT_StructInit(&GPIOInitStruct);
GPIOInitStruct.PORT_Pin = PORT_Pin_0;
GPIOInitStruct.PORT_OE = PORT_OE_OUT;
GPIOInitStruct.PORT_SPEED = PORT_SPEED_SLOW;
GPIOInitStruct.PORT_MODE = PORT_MODE_DIGITAL;

PORT_Init(MDR_PORTC, &GPIOInitStruct);

Программа работает с отладчиком, но не работает при подаче питания на МК

Если программа работает с отладчиком, но не работает после сброса по Reset  или после включения питания, необходимо проверить очередность включения тактирования и инициализации!

Это тот случай, когда тактирование в программе задано после настройки периферии. На примере настройки портов рассмотрим ход выполнения программы:

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

  2. В программе происходит инициализация портов.

  3. В программе включается тактирование портов.

Так как тактирование портов не было включено на момент их инициализации, то настройка портов не была произведена. 

При запуске программы в режиме отладки происходит следующая последовательность действий:

  1. Отладчик подключается и перезапускает МК, при этом если в настройках отладчика выбран сброс только ядра, то тактирование периферийных блоков остаётся включённым с прошлого запуска.

  2. В программе происходит инициализация портов, которая выполняется успешно, так как тактирование портов включено. 

  3. В программе включается тактирование портов.

В данном случае порты ввода-вывода функционируют корректно, поскольку их инициализация происходила при уже включенном тактировании.

Переменные и флаги в прерываниях

Нельзя изменять значение переменной в основном потоке и в обработчике прерывания без атомарного доступа!

Например, простейшая операция » i++; » происходит в несколько этапов:

  1. В регистр ядра Rx загружается значение i из ячейки памяти.

  2. Значение регистра увеличивается на 1.

  3. Значение регистра сохраняется в ячейку памяти i.

В любой момент между этими шагами может возникнуть прерывание, в обработчике которого также возможно изменение переменной i. В этом случае при выходе из обработчика прерывания новое значение переменной i будет изменено в основной программе на шаге 3, при этом логика программы может быть нарушена.

В ядре Cortex M существуют операции для защищенного обращения к памяти LDREX и STREX. Информацию по их использованию можно найти, например, на официальном сайте Keil.

Вторым вариантом обращения к памяти может быть использование метода bit-band, который доступен для МК на базе Cortex M3/M4. Запись и стирание флагов в ячейках памяти происходит атомарными операциями типа чтение-модификация-запись.

Программирование Flash-памяти

Flash память МК может работать в двух режимах: в обычном режиме (доступ к памяти осуществляется через шины I Code и D Code) и в режиме программирования (доступ к памяти осуществляется через регистры контроллера Flash-памяти). В режиме программирования программный код должен выполняться из области системной шины (внешняя память) или ОЗУ. Выполнение программного кода из Flash-памяти в режиме программирования невозможно. При попытке доступа ядра к Flash-памяти, находящейся в режиме программирования, будет вызвано прерывание HardFault или BusFault в зависимости от настроек ядра (SCR регистры). Поэтому важно, чтобы при программировании Flash-памяти не возникало никаких прерываний, поскольку таблица векторов и обработчики прерываний по умолчанию расположены во Flash-памяти.

Чтобы запретить выбранное прерывание IRQn необходимо вызвать функцию NVIC_DisableIRQ(). При этом необходимо учитывать, что запрещение генерации запроса прерываний от системного таймера SysTick выполняется не в контроллере NVIC, а в регистре управления системным таймером.

Пример запрещения прерываний от системного таймера приведён в фрагменте кода 2.

Фрагмент кода 2 — Запрещение прерываний от системного таймера

SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;

Чтобы запретить сразу все прерывания, кроме HardFaut и NMI, необходимо выполнить специальную функцию, как показано в фрагменте кода 3.

Фрагмент кода 3 — Запрещение всех прерывания, кроме HardFaut и NMI


 __disable_irq();

После работы с Flash-памятью необходимо вернуть разрешение прерываний.

В режиме программирования функции работы с Flash-памятью должны выполняться из области системной шины (внешняя память) или ОЗУ!

Пример расположения программного кода в памяти ОЗУ приведён в статье Расположение функций в ОЗУ, программирование EEPROM.

Выводы, совмещенные с JTAG и SWD

Иногда возникает необходимость использовать выводы, совмещенные с интерфейсом JTAG и SWD (далее для краткости используется обозначение JTAG, но подразумевается JTAG и SWD). При использовании функций библиотеки SPL выводы, совмещенные с JTAG B, перенастроить не получится, так как для них по умолчанию установлена защита. Например, функция PORT_Init() проверяет конфигурируемые выводы на принадлежность к JTAG B и не даёт их переназначать. Разрешение данной проверки определено в файле MDR32FxQI_config.h с помощью макроопределения USE_JTAG_B, строка 80, как показано в фрагменте кода 4.

Фрагмент кода 4 — Макроопределения защиты выводов, совмещённых с JTAG, в файле MDR32FxQI_config.h

#if (defined(USE_MDR32F9Q2I) || defined (USE_MDR32FG16S1QI))

  
/* #define USE_JTAG_A */
#define USE_JTAG_B

#endif

Библиотечный файл MDR32FxQI_config.h защищен от записи, поэтому необходимо предварительно в свойствах файла снять атрибут «Только чтение» (Правая клавиша мыши -> Свойства -> Только чтение). Для снятия защиты с выводов, совмещённых с JTAG A или B необходимо закомментировать соответствующее макроопределение: USE_JTAG_A или USE_JTAG_B. После этого данными выводами можно управлять с помощью функций SPL.

Необходимо обратить внимание, что после переопределения выводов, совмещенных с JTAG, выбранный интерфейс JTAG работать не будет. Программа при запуске будет переопределять эти выводы, и подключиться к МК через данный интерфейс будет невозможно. Для связи с МК необходимо будет использовать либо другой интерфейс JTAG, либо интерфейс UART при старте МК в режиме «UART загрузчик».

Чтобы сохранить работоспособность интерфейса JTAG при старте МК, необходимо в начале функции main() вставить пустой цикл на пару секунд. Этот цикл даст некоторую задержку перед переопределением выводов, совмещённых с JTAG. За это время отладчик успеет перехватить управление и остановить исполнение программы. Таким образом сохраняется возможность подключиться к МК, даже если выводы JTAG в программе используются по другому назначению.

Запись в регистры порта, выводы которого совмещенные с JTAG и SWD

Если в программе не используются функции SPL, то необходимо учитывать, что при записи в регистры MDR_PORTx→RXTX и MDR_PORTx→OE биты выводов, совмещенных с JTAG, необходимо сбрасывать. Если этого не сделать, то работа интерфейса будет нарушена, а отладка невозможна.

В качестве примера можно посмотреть реализацию функций PORT_SetBits() или PORT_ResetBits() библиотеки SPL.

Смена тактовой частоты

Для смены тактовой частоты на более высокую требуется совершить следующие операции:

  • Если требуется, переключить мультиплексор С3 на промежуточный источник тактирования, например, HSI.

  • Настроить генератор HSE и/или умножитель частоты PLL и дождаться, пока он выйдет в рабочий режим.

  • Настроить в контроллере Flash-памяти число тактов паузы Delay до переключения на более высокую частоту.

  • Настроить поля SelectRI и LOW в регистре MDR_BKP→REG_0E.

  • Переключить мультиплексор С3 на новый источник тактирования.

При переходе на более низкую частоту, изменение значения Delay и SelectRI, LOW производят после смены частоты.

Таким образом, при смене тактовой частоты необходимо соблюдать следующие правила:

До перехода на новую частоту с помощью переключения мультиплексора C3 необходимо, чтобы новая частота была полностью сформирована, и МК был полностью готов к работе на ней.

На момент смены частоты значения Delay и SelectRI, LOW должны соответствовать максимальной частоте из старого и нового значения.

Пример инициализации тактирования в МК К1986ВЕ92QI

В фрагменте кода 5 приведена функция CPU_Initialize(), инициализирующая тактирование в МК К1986ВЕ92QI от умножителя частоты PLL с использованием генератора HSE, который работает на внешнем кварцевом резонаторе. Для работы функции CPU_Initialize() в проект необходимо подключить библиотечные файлы MDR32FxQI_rst_clk.c,  MDR32FxQI_eeprom.c, MDR32FxQI_power.c.

Фрагмент кода 5 — Инициализация тактирования в МК К1986ВЕ92QI

#include <MDR32FxQI_rst_clk.h>
#include <MDR32FxQI_eeprom.h>
#include <MDR32FxQI_power.h>

// Инициализация системы тактирования микроконтроллера 
void CPU_Initialize (void) 

   // Сброс настроек системы тактирования 
   RST_CLK_DeInit(); 

    
   // Инициализация генератора на внешнем кварцевом резонаторе (HSE = 8 МГц) 
   RST_CLK_HSEconfig (RST_CLK_HSE_ON); 
   if(RST_CLK_HSEstatus() != SUCCESS){
       while (1);
   }

    
   // Инициализация блока PLL 
   // Настройка источника и коэффициента умножения PLL 
   // CPU_C1_SEL = HSE_CLK, PLLCPUo = HSE_CLK * 10 = 8 МГц * 10 = 80 МГц
   RST_CLK_CPU_PLLconfig (RST_CLK_CPU_PLLsrcHSEdiv1, RST_CLK_CPU_PLLmul10);
   // Включение PLL
   RST_CLK_CPU_PLLcmd (ENABLE);  
   if(RST_CLK_CPU_PLLstatus() == ERROR) {
       while (1);
   }
   // Подключение PLL к системе тактирования 
   // (CPU_C2_SEL = PLLCPUo = 80 МГц)
   RST_CLK_CPU_PLLuse (ENABLE);
   // Настройка коэффициента деления блока CPU_C3_SEL 
   // (CPU_C3_SEL = CPU_C2) 
   RST_CLK_CPUclkPrescaler (RST_CLK_CPUclkDIV1);

   
   // Настройка числа тактов паузы Delay в контроллере Flash-памяти
   // Тактовая частота до 100 МГц - Delay = 3
   RST_CLK_PCLKcmd (RST_CLK_PCLK_EEPROM, ENABLE);
   EEPROM_SetLatency(EEPROM_Latency_3);
   RST_CLK_PCLKcmd (RST_CLK_PCLK_EEPROM, DISABLE);

   // Настройка параметров регулятора напряжения SelectRI и LOW в контроллере BKP
   // Тактовая частота 80 МГц
   RST_CLK_PCLKcmd(RST_CLK_PCLK_BKP, ENABLE);
   POWER_DUccMode(POWER_DUcc_upto_80MHz);

   
   // Переключение тактовой частоты процессора на CPU_C3 
   // (HCLK = CPU_C3) 
   RST_CLK_CPUclkSelection (RST_CLK_CPUclkCPU_C3);
}

При использовании функции printf() отладка не доходит до main()

Это особенность компилятора Keil, заменяющего функционал printf() на инструкцию программной остановки BKPT для реализации механизма semihosting. При старте программы низкоуровневые библиотеки Си также выполняют инструкцию BKPT, что приводит к остановке исполнения программы. Чтобы Keil не реализовывал механизм semihosting необходимо выполнить один из указанных пунктов:

1) Исключить вызов printf() из проекта.

2) Описать функции, перенаправляющие стандартный поток ввода-вывода в требуемый интерфейс МК, например, как показано в статьях Printf через ITM и Printf через UART.

3) В настройках проекта «Options for Target -> Target» выбрать опцию «Use MicroLIB», которая позволяет использовать оптимизированную по размеру кода стандартную библиотеку Си, в которой исключен механизм semihosting. Подробнее про MicroLIB описано на официальном сайте Keil.

Переход по абсолютному адресу приводит к исключению HardFault

Иногда требуется перейти в функцию, расположенную по известному адресу в памяти. Если в коде это будет выражено так, как показано в фрагменте кода 6 или 7, то произойдёт вызов исключения HardFault:

Фрагмент кода 6 — Некорректный переход по заданному адресу на языке Си

// Адрес функции в памяти
#define BASE_ADDR_FUNC_IN_RAM 0x20005000

// Указатель на функцию в памяти по известному адресу
typedef void (*funcptr)();
funcptr funcInRAM = (funcptr) (BASE_ADDR_FUNC_IN_RAM);

// Вызов функции
funcInRAM();


Фрагмент кода 7 — Некорректный переход по заданному адресу на языке ассемблер

LDR R0,=(0x20005000)
BX R0

Это происходит, потому что адрес перехода должен быть нечетным, чтобы указать ядру о переходе на инструкцию THUMB, а не ARM! Подробнее об этом описано на сайте ARM Info Center.

На самом деле при переходе в фрагментах кода 6 и 7 происходит исключение UsageFault, но данное исключение по сбросу запрещено, поэтому происходит вызов обработчика исключения HardFault. Разрешение исключений BusFault, MemManage fault и UsageFault выполняется в регистрах ядра SCB (System Control Block), как показано в фрагменте кода 8. О том, как работать с исключениями в Cortex-M3/M4 приведено в Application Note 209 от ARM.

Фрагмент кода 8 — Разрешение исключений BusFault, MemManage fault и UsageFault 

#define SCB_SHCSR_USGFAULTENA (1 << 18)
#define SCB_SHCSR_BUSFAULTENA (1 << 17)
#define SCB_SHCSR_MEMFAULTENA (1 << 16)

SCB->SHCSR |= SCB_SHCSR_USGFAULTENA;
SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA;
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA;

Таким образом, чтобы переход на заданный адрес произошел корректно, необходимо указывать в нулевом бите адреса перехода единицу, как показано в фрагментах кода 9 и 10.

Фрагмент кода 9 — Корректный переход по заданному адресу на языке Си

// Адрес функции в памяти 
#define BASE_ADDR_FUNC_IN_RAM 0x20005000

// Указатель на функцию в памяти по известному адресу
typedef void (*funcptr)();
funcptr funcInRAM = (funcptr) (BASE_ADDR_FUNC_IN_RAM + 1);

// Вызов функции 
funcInRAM();


Фрагмент кода 10 — Корректный переход по заданному адресу на языке ассемблер
LDR R0,=(0x20005001)
BX R0

Сохранить статью в PDF

    • Поделиться

Опубликовано:

Сегодня попытался прочитать мультискриптом Grreka 93с66 на версии программы 55 в итоге выдает ошибку… а на версии 43 все читает и пишет без проблем… в чем может быть дело? Скрины ошибки и настройки в версии 55 прилагаю. 

2018-04-25_11-37-14.png

2018-04-25_13-45-25.png

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

Введение

   В этом материале мы рассмотрим возможные проблемы при работе с EEPROM. Часть из них связана с аппаратным стороной микроконтроллера, такие как повреждение EEPROM при пониженном напряжении питания и ограниченный ресурс EEPROM, а часть с программным обеспечением, например, при использовании EEPROM в прерываниях. Также рассмотрим способы решения этих проблем и методы повышения надежности хранения данных в EEPROM.

   Одна из старых проблем AVR — это повреждение EEPROM данных при пониженном питании микроконтроллера. Это может происходить в двух случаях:

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

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

— Нужно удерживать микроконтроллер AVR в состоянии сброса, если напряжение питания находится ниже нормы. Для этого можно использовать внешние супервизоры питания или встроенный детектор пониженного питания — Brown-out Detector (BOD). Встроенный детектор управляется с помощью fuse битов микроконтроллера — BODEN и BODLEVEL. BODEN — разрешает/запрещает работу детектора, а BODLEVEL — определяет его уровень срабатывания.
   Если сброс микроконтроллера происходит во время процесса записи в EEPROM, то операция записи будет завершена только при достаточном уровне напряжения.

— Также в многие разработчике рекомендуют не использовать 0-ую ячейку EEPROM`a, поскольку именно ее содержимое чаще всего повреждается при снижении питания микроконтроллера.

Проблемы с EEPROM из-за прерываний

   Операция записи в EEPROM состоит из нескольких шагов. Вспомним эту последовательность:

1. Ожидаем готовности EEPROM, опрашивая бит EEWE регистра EECR.
2. Устанавливаем адрес в регистре EEAR.
3. Записываем байт данных в регистр EEDR.
4. Устанавливаем основной флаг разрешения записи EEMWE регистра EECE
5. Устанавливаем флаг разрешения записи EEWE регистра EECE

   Бит EEWE должен быть установлен в течении 4-ех тактов после установки бита EEMWE. Если этого не произойдет по причине прерываний, то запись в EEPROM не будет произведена. Этого легко избежать, если запретить прерывания перед 4-м шагом, а после 5-го снова разрешить их.

   Однако есть еще один подводный камень. Если прерывание возникло после 1-го, 2-го или 3-го шага, и в прерывании тоже используются операции с EEPROM (чтение или запись), то запись может не состояться, или запишутся не те данные и не туда, потому что содержимое регистров EEAR (адрес) и EEDR (данные) будет изменено.

   Описанное выше касается и процедуры чтения EEPROM.

   Лечить это можно следующими способами:

   — Не использовать операции чтения и записи EEPROM в прерываниях.
   Это особенно касается операции записи, потому что она медленная и выполняется с использованием внутреннего RC генератора. Например, для mega16 в даташите указано, что при записи в EEPROM используется внутренний RC генератор с частотой 1 МГц (независимо от установок fuse битов CKSEL) и время записи составляет 8.5 мс. Для прерывания это очень долго.

   — Запрещать прерывания на время всей процедуры записи (чтения) EEPROM, то есть в самом начале.

   — Сохранять в начале обработчика прерывания содержимое регистров EEAR (адрес) и EEDR (данные), а перед выходом восстанавливать их.

   — Использовать флаги (семафоры) для сигнализации о выполнении работы с EEPROM.
   Перед выполнением записи в основном цикле программы (или задаче, если используется ос) устанавливать программный флаг, а в прерывании (или другой задаче) проверять его.

Ресурс EEPROM

   EEPROM имеет ограниченный ресурс. Atmel гарантирует, что количество циклов перезаписи EEPROM составляет не меньше 100000. Цифра довольно большая, однако и она может быть достигнута, если записывать в EEPROM часто и на протяжении долгого времени.
   Есть два приема по «увеличению» ресурса EEPROM.
   Первый — простой и состоит в том, чтобы записывать в EEPROM данные, только если они изменили свое значение.


__eeprom uint8_t data;
uint8_t newData;

...
if (newData != data) {
data = newData;
}

   Второй- хитрый и состоит в том, чтобы хранить данные не в одной ячейки памяти (или группе ячеек, если речь идет о многобайтных переменных), а в нескольких, и записывать в них по очереди.
   Допустим, нам нужно хранить в EEPROM один байт. Выделяем под него 8 байтов и каждый раз записываем в следующую ячейку, когда доходим до последней ячейки, то записываем в первую. И так по кругу, как в кольцевом буфере. Если каждая ячейка EEPROM имеет ресурс 100000, то записывая в 8 ячеек по очереди, мы получаем ресурс перезаписи байта 800000.

EEPROM и оптимизация компилятора

   Переменные, которые объявлены, но не используются, часто удаляются компилятором в процессе оптимизации. Если такие переменные нужны, перед ними следует добавлять ключевое слово volatile.


//для IAR AVR
volatile __eeprom char name[] = "prog 12.3";

   Если используются свои функции для работы с EEPROM, то могут возникнуть проблемы при высоких уровнях оптимизации компилятора. Компилятор может объединить одинаковые (с его точки зрения) части кода в одну подпрограмму и нарушить логику работы вашей функции. Чтобы этого не происходило нужно или запрещать оптимизацию данной функции, или отключать перекрестную оптимизацию (cross call optimization) для функции или файла. Как это делается зависит от компилятора. Как правило, для этого существуют определенные ключи и прагмы.

Программные способы повышения надежности EEPROM

   

Один из простых способов повышения надежности хранения данных в EEPROM — это метод мажоритарного резервирования. Суть метода заключается в том, что для хранения данных выделяется нечетное количество ячеек памяти — N. При сохранении данных — запись производится во все выделенные ячейки. При чтении — читаются тоже все, но решение относительно содержимого принимается на основе равенства (N+1)/2 ячеек.

   Рассмотрим пример тройного мажоритарного резервирования байта данных. Для сохранения байта используются три байта EEPROM, а решение о содержимом принимается на основании равенства 2 байтов. Код приведен для компилятора IAR AVR.


//функция сохранения
void EEPROM_SaveByte(uint8_t value, uint8_t __eeprom *buf)
{
   buf[0] = value;
   buf[1] = value;
   buf[2] = value;
}

//функция считывания
uint8_t EEPROM_LoadByte(uint8_t *value, uint8_t __eeprom *buf)
{
   uint8_t a = buf[0];
   uint8_t b = buf[1];
   uint8_t c = buf[2];

   if ((a == b)||(a == c)){
      *value = a;
      return 0;
   }
   else {
      if (b == c){  
         *value = b;
         return 0;
      }
   }
   return 1;
}

....
//пример использования

__eeprom uint8_t buffer[3];
uint8_t data;

EEPROM_SaveByte(125, buffer);
EEPROM_LoadByte(&data, buffer);

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

   Другой метод повышения надежности хранимых данных состоит в использовании контрольных сумм, например CRC. Я не использовал этот метод в своей практике, поэтому о нем мало чего могу сказать.

   На этом все…

Понравилась статья? Поделить с друзьями:
  • Edc урал ошибка
  • Eeprom ошибка ваз 2110
  • Edc ошибка шакман х3000
  • Edt sys ошибка не дает запустить виндовс
  • Edc ошибка уаз патриот дизель