Оформлены комментарии в I2C

This commit is contained in:
Dmitry Shpak 2019-08-16 11:38:16 +03:00
parent 400caa0aa5
commit 7e38106ce2
3 changed files with 79 additions and 138 deletions

View File

@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="520753781973748679" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true"> <provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-411648972679954456" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/> <language-scope id="org.eclipse.cdt.core.g++"/>
</provider> </provider>
@ -16,7 +16,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="480357847621646132" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true"> <provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-311328360447573477" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/> <language-scope id="org.eclipse.cdt.core.g++"/>
</provider> </provider>

View File

@ -1,14 +1,31 @@
/* /*!
* V_i2cMem.h Copyright 2019 ÀÎ "ÍÈÈÝÒ" è ÎÎÎ "ÍÏÔ ÂÅÊÒÎÐ"
*
* Created on: 15 àâã. 2019 ã.
* Author: Dmitry
*/
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_i2cMem.h
\brief Äðàéâåð äëÿ ðàáîòû ñ ìèêðîñõåìîé ôëåø ïàìÿòè 24LC256 ïî
èíòåðôåéñó I2C
\author ÎÎÎ "ÍÏÔ Âåêòîð". http://motorcontrol.ru
\version v 1.0 10/08/2019
\addtogroup v_i2cMem
@{
*/
#ifndef INCLUDE_V_I2CMEM_H_ #ifndef INCLUDE_V_I2CMEM_H_
#define INCLUDE_V_I2CMEM_H_ #define INCLUDE_V_I2CMEM_H_
#define EEPROM_MEM_LENGTH 32768 //äëèíà ôëåøêè â áàéòàõ (256 êáèò) #define EEPROM_MEM_LENGTH 32768 // Ðàçìåð ïàìÿòè â áàéòàõ (256 êáèò)
struct SI2cMem; struct SI2cMem;
typedef volatile struct SI2cMem TI2cMem; typedef volatile struct SI2cMem TI2cMem;
@ -16,7 +33,7 @@ typedef volatile struct SI2cMem TI2cMem;
struct SI2cMem { struct SI2cMem {
Uint16 MEMstartaddr; //! Àäðåñ íà flash Uint16 MEMstartaddr; //! Àäðåñ íà flash
Uint16 data_length; //! Äëèíà äàííûõ â áàéòàõ Uint16 data_length; //! Äëèíà äàííûõ â áàéòàõ
Uint16 *DSPstartaddr; //! Àäðåñ íà ìàññèâ ñ äàííûìè Uint16 *DSPstartaddr; //! Àäðåñ íà ìàññèâ ñ äàííûìè â êîíòðîëëåðå
Uint16 LastErr; //! Êîä îøèáêè (åñëè âîçíèêëà) Uint16 LastErr; //! Êîä îøèáêè (åñëè âîçíèêëà)
void (*init)(TI2cMem*); void (*init)(TI2cMem*);
void (*write)(TI2cMem*); void (*write)(TI2cMem*);

View File

@ -1,10 +1,27 @@
/* /*!
* V_i2cMem.c Copyright 2019 АО "НИИЭТ" и ООО "НПФ ВЕКТОР"
*
* Created on: 15 àâã. 2019 ã.
* Author: Dmitry
*/
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\file v_i2cMem.c
\brief Драйвер для работы с микросхемой флеш памяти 24LC256 по
интерфейсу I2C
\author ООО "НПФ Вектор". http://motorcontrol.ru
\version v 1.0 10/08/2019
\addtogroup v_i2cMem
@{
*/
#include "main.h" #include "main.h"
#include "V_i2cmem.h" #include "V_i2cmem.h"
@ -15,11 +32,17 @@
TI2cMem i2cMem = I2CMEM_DEFAULTS; TI2cMem i2cMem = I2CMEM_DEFAULTS;
// Ôóíêöèÿ îæèäàíèÿ âûïîëíåíèÿ êîìàíäû // Желаемая частота шины I2C в килогерцах
#define I2CMEM_FREQUENCY_KHZ 400
// Функция ожидания выполнения команды модулем I2C
// Просто ждёт, пока модуль выйдет из состояния "IDLE"
Uint16 i2c_waitIdle() { Uint16 i2c_waitIdle() {
Uint32 idle = 0; Uint32 idle = 0;
while ((I2C->ST & I2C_ST_MODE_Msk) == I2C_ST_MODE_IDLE){ while ((I2C->ST & I2C_ST_MODE_Msk) == I2C_ST_MODE_IDLE){
idle++; idle++;
// Если ожидание слишком долгое - выдать ошибку
if (idle > 10000000) if (idle > 10000000)
return 1; return 1;
}; };
@ -27,7 +50,9 @@ Uint16 i2c_waitIdle() {
return 0; return 0;
} }
// Ôóíêöèÿ æä¸ò, ïîêà çàêîí÷èòñÿ âíóòðåííèé öèêë çàïèñè â ïàìÿòè
// Функция ждёт, пока закончится внутренний цикл записи в микросхеме памяти.
// Пока цикл идёт, микросхема не квитирует отправленный ей байт с собственным адресом и командой "Write"
// Åñëè äîëæàëèñü, ïîêà ìèêðîñõåìà îñâîáîäèòñÿ, òî íà âûõîäå èç ôóíêöèè îíà áóäåò â ñîñòîÿíèè // Åñëè äîëæàëèñü, ïîêà ìèêðîñõåìà îñâîáîäèòñÿ, òî íà âûõîäå èç ôóíêöèè îíà áóäåò â ñîñòîÿíèè
// îæèäàíèÿ ïðè¸ìà âíóòðåííåãî àäðåñà (òî åñòü å¸ ïîñëàí ñòàðò è àäðåñ óñòðîéñòâà ñ áèòîì "Write") // îæèäàíèÿ ïðè¸ìà âíóòðåííåãî àäðåñà (òî åñòü å¸ ïîñëàí ñòàðò è àäðåñ óñòðîéñòâà ñ áèòîì "Write")
Uint16 i2c_waitMemBusyAndSendAddWr () { Uint16 i2c_waitMemBusyAndSendAddWr () {
@ -66,11 +91,13 @@ Uint16 i2c_waitMemBusyAndSendAddWr () {
} }
} while ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTADPA); } while ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTADPA);
// Дошли до сюда - всё хорошо
return I2C_MEM_ERROR_OK; return I2C_MEM_ERROR_OK;
} }
// Вспомогательная функция для блочной записи данных в памяти.
// Èíèò/ïåðåèíèò çàïèñè ìàññèâà, êîòîðûé íàäî âûçûâàòü ïðè äîñòèæåíèè ãðàíèöû ñòðàíèöû (64 áàéòà) // Осуществляет инит/переинит записи массива, который надо вызывать
// при достижении границы страницы (64 байта) внутри памяти.
Uint16 i2c_initWriteArray (Uint16 address) { Uint16 i2c_initWriteArray (Uint16 address) {
Uint16 retVal; Uint16 retVal;
// Æä¸ì, ïîêà ïàìÿòü ïàìÿòü çàêîí÷èí âíóòðåííåå ñîõðàíåíèå // Æä¸ì, ïîêà ïàìÿòü ïàìÿòü çàêîí÷èí âíóòðåííåå ñîõðàíåíèå
@ -100,16 +127,16 @@ Uint16 i2c_initWriteArray (Uint16 address) {
return I2C_MEM_ERROR_OK; return I2C_MEM_ERROR_OK;
} }
// Çàïèñü ìàññèâà // Запись массива байт в память.
Uint16 i2c_writeArray(Uint16 address, Uint16 *dataPtr_u16, Uint16 length_u8) { Uint16 i2c_writeArray(Uint16 address, Uint16 *dataPtr_u16, Uint16 length_u8) {
// Òóò âíóòðè ïðîùå ðàáîòàòü ñ áàéòàìè // Òóò âíóòðè ïðîùå ðàáîòàòü ñ áàéòàìè
Uint8* dataPtr_u8 = (Uint8*)dataPtr_u16; Uint8* dataPtr_u8 = (Uint8*)dataPtr_u16;
// Отправляем адрес, с котрого начнём запись
i2c_initWriteArray(address); i2c_initWriteArray(address);
// Ïîåõàëè äàííûå // Отправляем данные
while (length_u8 > 0) { while (length_u8 > 0) {
// Äàííûå
I2C->SDA = *dataPtr_u8; I2C->SDA = *dataPtr_u8;
I2C->CTL0 = I2C_CTL0_CLRST_Msk; I2C->CTL0 = I2C_CTL0_CLRST_Msk;
if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT; if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
@ -118,11 +145,12 @@ Uint16 i2c_writeArray(Uint16 address, Uint16 *dataPtr_u16, Uint16 length_u8) {
if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTDAPA) if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTDAPA)
return I2C_MEM_ERROR_WRITE_HW_ERR; return I2C_MEM_ERROR_WRITE_HW_ERR;
// Ñìîòðèì, íå äîøëè ëè äî êîíöà ñòðàíèöû âíóòðè ïàìÿòè/
// Åñëè äîøëè - íàäî ñäåëàòü ñòîï è ïîäîæäàòü, ïîêà äàííûå ïðîïèøóòñÿ
length_u8--; length_u8--;
dataPtr_u8++; dataPtr_u8++;
address++; address++;
// Смотрим, не дошли ли до конца страницы внутри памяти/
// Если дошли - надо отправить стоп и подождать, пока данные пропишутся
if ((address & 0x3F) == 0) { if ((address & 0x3F) == 0) {
// Ôîðìèðóåì ñòîï è ïåðåçàïóñêàåì çàïèñûâàëêó íà íîâûé àäðåñ // Ôîðìèðóåì ñòîï è ïåðåçàïóñêàåì çàïèñûâàëêó íà íîâûé àäðåñ
I2C->CTL0 = I2C_CTL0_STOP_Msk; I2C->CTL0 = I2C_CTL0_STOP_Msk;
@ -144,7 +172,7 @@ Uint16 i2c_readArray(Uint16 address, Uint16* readDataPtr_u16, Uint16 length_u8){
Uint16 retVal; Uint16 retVal;
// Æä¸ì, ïîêà ïàìÿòü ïàìÿòü çàêîí÷èí âíóòðåííåå ñîõðàíåíèå // Ждём, пока память память закончит внутреннее сохранение
retVal = i2c_waitMemBusyAndSendAddWr(); retVal = i2c_waitMemBusyAndSendAddWr();
if (retVal != I2C_MEM_ERROR_OK) if (retVal != I2C_MEM_ERROR_OK)
return retVal; return retVal;
@ -185,8 +213,8 @@ Uint16 i2c_readArray(Uint16 address, Uint16* readDataPtr_u16, Uint16 length_u8){
if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MRADPA) if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MRADPA)
return I2C_MEM_ERROR_READ_HW_ERR; return I2C_MEM_ERROR_READ_HW_ERR;
// До последнего байта принимаем и квитируем
while (length_u8 > 1) { while (length_u8 > 1) {
// Ïðèíèìàåì áàéò, è êâèòèðóåì
I2C->CTL0 = I2C_CTL0_CLRST_Msk; I2C->CTL0 = I2C_CTL0_CLRST_Msk;
if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT; if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
@ -216,9 +244,8 @@ Uint16 i2c_readArray(Uint16 address, Uint16* readDataPtr_u16, Uint16 length_u8){
} }
// Æåëàåìàÿ ÷àñòîòà øèíû I2C â êèëîãåðöàõ
#define I2CMEM_FREQUENCY_KHZ 400
// Инит модуля I2C и GPIO, к которым подключена память
void I2CMEM_Init(TI2cMem*p){ void I2CMEM_Init(TI2cMem*p){
// Ðàçðåøàåì ðàáîòó 0 è 1 íîæåê ïîðòà À è ïåðåâîäèì èõ â ïåðèôåðèéíûé ðåæèì // Ðàçðåøàåì ðàáîòó 0 è 1 íîæåê ïîðòà À è ïåðåâîäèì èõ â ïåðèôåðèéíûé ðåæèì
GPIOA->DENSET |= 0x3; GPIOA->DENSET |= 0x3;
@ -230,23 +257,25 @@ void I2CMEM_Init(TI2cMem*p){
I2C->CTL1 |= (25000 / I2CMEM_FREQUENCY_KHZ) << I2C_CTL1_SCLFRQ_Pos; I2C->CTL1 |= (25000 / I2CMEM_FREQUENCY_KHZ) << I2C_CTL1_SCLFRQ_Pos;
} }
// Запись массива байтов
void I2CMEM_Write(TI2cMem*p){ void I2CMEM_Write(TI2cMem*p){
// Çàïèñü
p->LastErr = i2c_writeArray(p->MEMstartaddr, p->DSPstartaddr, p->data_length); p->LastErr = i2c_writeArray(p->MEMstartaddr, p->DSPstartaddr, p->data_length);
} }
// Чтение массива байтов
void I2CMEM_Read(TI2cMem*p){ void I2CMEM_Read(TI2cMem*p){
// ×òåíèå
p->LastErr = i2c_readArray(p->MEMstartaddr, p->DSPstartaddr, p->data_length); p->LastErr = i2c_readArray(p->MEMstartaddr, p->DSPstartaddr, p->data_length);
} }
// Полная очистка памяти
void I2CMEM_Clear(TI2cMem*p){ void I2CMEM_Clear(TI2cMem*p){
// Ñòèðàíèå
Uint32 i = 0; Uint32 i = 0;
Uint16 ffArr[32]; Uint16 ffArr[32];
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
ffArr[i] = 0xFFFF; ffArr[i] = 0xFFFF;
} }
// Забиваем каждую страницу 0xFF
for (i = 0; i < EEPROM_MEM_LENGTH; i += 0x40){ for (i = 0; i < EEPROM_MEM_LENGTH; i += 0x40){
p->MEMstartaddr = i; p->MEMstartaddr = i;
p->DSPstartaddr = ffArr; p->DSPstartaddr = ffArr;
@ -257,109 +286,4 @@ void I2CMEM_Clear(TI2cMem*p){
return; return;
} }
} }
/*@}*/
/****** Äåïðåêåéòåä, êàê ãîâîðèòñÿ *******/
//// Çàïèñü â ïàìÿòü îäíîãî áàéòà è "ñòîï"
//Uint16 i2c_writeSingleByteAndStop(Uint16 address, Uint8 data)
//{
// Uint16 retVal;
// // Æä¸ì, ïîêà ïàìÿòü ïàìÿòü çàêîí÷èí âíóòðåííåå ñîõðàíåíèå
// retVal = i2c_waitMemBusyAndSendAddWr();
// if (retVal != I2C_MEM_ERROR_OK)
// return retVal;
//
// // Ñòðàøèé áàéò àäðåñà 0x0000____
// I2C->SDA = (address >> 8) & 0xFF;
// I2C->CTL0 = I2C_CTL0_CLRST_Msk;
// if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
//
// // Åñëè íå êâèòèðîâàí - îøèáêà
// if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTDAPA)
// return I2C_MEM_ERROR_WRITE_HW_ERR;
//
// // Ìëàäøèé áàéò àäðåñà 0x____0000
// I2C->SDA = (address >> 0) & 0xFF;
// I2C->CTL0 = I2C_CTL0_CLRST_Msk;
// if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
//
// // Åñëè íå êâèòèðîâàí - îøèáêà
// if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTDAPA)
// return I2C_MEM_ERROR_WRITE_HW_ERR;
//
// // Äàííûå
// I2C->SDA = data;
// I2C->CTL0 = I2C_CTL0_CLRST_Msk;
// if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
//
// // Åñëè íå êâèòèðîâàí - îøèáêà
// if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTDAPA)
// return I2C_MEM_ERROR_WRITE_HW_ERR;
//
// // Ôîðìèðóåì ñòîï
// I2C->CTL0 = I2C_CTL0_STOP_Msk;
// I2C->CTL0 |= I2C_CTL0_CLRST_Msk;
// return I2C_MEM_ERROR_OK;
//}
//
//
//// ×òåíèå îäíîãî áàéòà è ñòîï
//Uint8 i2c_readSingleByteAndStop(Uint16 address, Uint16* readData)
//{
// Uint16 retVal;
//
// // Æä¸ì, ïîêà ïàìÿòü ïàìÿòü çàêîí÷èí âíóòðåííåå ñîõðàíåíèå
// retVal = i2c_waitMemBusyAndSendAddWr();
// if (retVal != I2C_MEM_ERROR_OK)
// return retVal;
//
// // Ñòðàøèé áàéò àäðåñà 0x0000____
// I2C->SDA = (address >> 8) & 0xFF;
// I2C->CTL0 = I2C_CTL0_CLRST_Msk;
// if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
//
// // Åñëè íå êâèòèðîâàí - îøèáêà
// if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTDAPA)
// return I2C_MEM_ERROR_READ_HW_ERR;
//
// // Ìëàäøèé áàéò àäðåñà 0x____0000
// I2C->SDA = (address >> 0) & 0xFF;
// I2C->CTL0 = I2C_CTL0_CLRST_Msk;
// if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
//
// // Åñëè íå êâèòèðîâàí - îøèáêà
// if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MTDAPA)
// return I2C_MEM_ERROR_READ_HW_ERR;
//
// // Ïîâòîðíûé ñòàðò, ÷òîáû ïåðåéòè â ðåæèì ìàñòåðà-ïðè¸ìíèêà
// I2C->CTL0 = I2C_CTL0_START_Msk;
// I2C->CTL0 |= I2C_CTL0_CLRST_Msk;
// if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
//
// // Åñëè ðåæèì íåïðàâèëüíûé - îøèáêà
// if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_RSDONE)
// return I2C_MEM_ERROR_READ_HW_ERR;
//
// // Àäðåñ óñòðîéñòâà + Read
// I2C->SDA = 0b10100001;
// I2C->CTL0 = I2C_CTL0_CLRST_Msk;
// if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
//
// // Åñëè ïåðåäà÷à àäðåñà óñòðîéñòâà íå êâèòèðîâàíà - îøèáêà
// if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MRADPA)
// return I2C_MEM_ERROR_READ_HW_ERR;
//
// // Ïðèíèìàåì áàéò, íî íå êâèòèðóåì
// I2C->CTL0 = I2C_CTL0_ACK_Msk; // Reset + NACK
// I2C->CTL0 |= I2C_CTL0_CLRST_Msk;
// if (i2c_waitIdle() != 0) return I2C_MEM_ERROR_TIMEOUT;
//
// // Åñëè ðåæèì íå ñòàë ïðàâèëüíûì - îøèáêà
// if ((I2C->ST & I2C_ST_MODE_Msk) != I2C_ST_MODE_MRDANA)
// return I2C_MEM_ERROR_READ_HW_ERR;
//
// *readData = I2C->SDA;
// // Ôîðìèðóåì ñòîï
// I2C->CTL0 = I2C_CTL0_STOP_Msk | I2C_CTL0_CLRST_Msk;
//
// return I2C_MEM_ERROR_OK;
//}