Compare commits

..

5 Commits

Author SHA1 Message Date
Razvalyaev
d03d26cef1 Добавлен i2c и распиновка МК 2026-03-13 15:47:13 +03:00
12922152bb Обновить README.md 2025-12-28 23:41:12 +03:00
16f46c87c4 Добавить README.md 2025-12-28 23:35:56 +03:00
Razvalyaev
c82bbdc1ca Убрано лишнее из main.c 2025-12-28 15:40:33 +03:00
Razvalyaev
c63d98f431 Проект перенесен в папку MDK-ARM 2025-12-28 15:38:30 +03:00
78 changed files with 1240 additions and 38 deletions

2
.gitignore vendored
View File

@@ -46,4 +46,4 @@ JLinkSettings.ini
# Other Files
/Objects/
MDK-ARM/Objects/

6
.gitmodules vendored
View File

@@ -1,4 +1,4 @@
[submodule "Core/ExtendedLibs"]
path = Core/ExtendedLibs
[submodule "MDK-ARM/Core/ExtendedLibs"]
path = MDK-ARM/Core/ExtendedLibs
url = https://git.arktika.cyou/Razvalyaev/STM32_ExtendedLibs.git
branch = release
branch = develop

971
MDK-ARM/Core/App/i2c.c Normal file
View File

@@ -0,0 +1,971 @@
/**
******************************************************************************
* @file i2c.c
* @author Разваляев Алексей
* @brief Драйвер I2C на основе PLIB035.
* Этот файл содержит:
* + Инициализацию I2C
* + Функции для работы в режиме мастера (блокирующие):
* - Блокирующая передача/прием
* - Функции чтения/записи регистров устройств
* - Проверка наличия устройства
*
******************************************************************************
* @attention
*
* Использование этого драйвера предполагает наличие корректных настроек:
* - Определена конфигурационная структура i2c_config в periph_config.h
* - Определены пины SDA/SCL для I2C
*
******************************************************************************
* @verbatim
==============================================================================
##### Как использовать этот драйвер #####
==============================================================================
1. Настройка в periph_config.h:
(+) Определите i2c_config для I2C
(+) Настройте частоту SCL (FSFreq для стандартного режима, HSFreq для высокоскоростного)
(+) Используйте enum для настройки:
• I2C_Mode_Master - режим мастера
• I2C_Mode_Slave - режим ведомого
2. Инициализация:
(+) i2c_init_first() - настройка GPIO, тактирования
(+) i2c_init(&hi2c, &config) - инициализация I2C
3. Запуск I2C:
(+) I2C_Start(&hi2c) - включение I2C
4. Работа в режиме мастера (блокирующие функции):
- Основные функции:
(+) I2C_Master_Transmit(&hi2c, addr, buf, size, timeout) - передача данных
(+) I2C_Master_Receive(&hi2c, addr, buf, size, timeout) - прием данных
(+) I2C_Master_WriteReg(&hi2c, addr, reg, val, timeout) - запись регистра
(+) I2C_Master_ReadReg(&hi2c, addr, reg, buf, size, timeout) - чтение регистра
(+) I2C_Master_WriteRegs(&hi2c, addr, reg, buf, size, timeout) - запись нескольких регистров
(+) I2C_Master_ReadRegs(&hi2c, addr, reg, buf, size, timeout) - чтение нескольких регистров
(+) I2C_Master_IsDeviceReady(&hi2c, addr, timeout) - проверка наличия устройства
5. Обработка ошибок:
(+) I2C_GetLastError(&hi2c) - получение кода последней ошибки
(+) Callback-функция ошибки вызывается автоматически при ошибках
6. GPIO для I2C:
(+) Пины настраиваются автоматически при вызове i2c_init_first()
(+) При необходимости можно вызвать i2c_gpio_deinit() для восстановления
==============================================================================
##### Особенности работы #####
==============================================================================
- Режимы работы:
- Master: инициирует передачу данных, управляет шиной
- Slave: реагирует на запросы мастера
- Скорости работы:
- Standard Mode (до 100 кГц)
- Fast Mode (до 400 кГц)
- Fast Mode Plus (до 1 МГц)
- High Speed Mode (до 3.4 МГц)
- Адресация:
- 7-битная адресация (стандартная)
- 10-битная адресация (поддерживается)
- Обработка ошибок:
- Обрабатываются ошибки шины, арбитража, таймаута
- При ошибке вызывается ErrCallback и сохраняется код ошибки
- После ошибки требуется переинициализация I2C
- Функции работы с регистрами:
- Упрощают чтение/запись регистров устройств на шине I2C
- Поддерживают различные размеры регистров (8/16 бит)
- Проверка устройства:
- Функция проверяет ответ устройства на свой адрес
- Полезна для проверки подключения устройств
@endverbatim
******************************************************************************
*/
//-- Includes ------------------------------------------------------------------
#include "periph_config.h"
I2C_HandleTypeDef hi2c; /*!< Хендл I2C */
//-- Private function prototypes -----------------------------------------------
static OperationStatus __i2c_master_wait_bus_free(I2C_HandleTypeDef *hi2c, uint32_t timeout);
static OperationStatus __i2c_master_send_start(I2C_HandleTypeDef *hi2c, uint32_t timeout);
static OperationStatus __i2c_master_send_address(I2C_HandleTypeDef *hi2c, uint16_t addr, uint8_t direction, uint32_t timeout);
static OperationStatus __i2c_master_send_stop(I2C_HandleTypeDef *hi2c, uint32_t timeout);
static OperationStatus __i2c_master_transmit_blocking(I2C_HandleTypeDef *hi2c, uint8_t *buf, uint16_t size, uint32_t timeout);
static OperationStatus __i2c_master_receive_blocking(I2C_HandleTypeDef *hi2c, uint8_t *buf, uint16_t size, uint32_t timeout);
static void __i2c_set_error(I2C_HandleTypeDef *hi2c, uint8_t error);
//-- I2C Init functions -------------------------------------------------------
/**
* @brief Первичная инициализация I2C
* @details Настройка I2C и хендла: GPIO, тактирование
*/
void i2c_init_first(void)
{
#if (USE_I2C==1)
// Настройка пинов для I2C
i2c_gpio_init();
// Включение тактирования и сброс I2C
RCU_APBClkCmd(RCU_APBClk_I2C, ENABLE);
RCU_APBRstCmd(RCU_APBRst_I2C, ENABLE);
// Инициализируем I2C
hi2c.Instance = I2C;
hi2c.LastError = I2C_ERROR_NONE;
i2c_init(&hi2c, &i2c_config);
#endif
}
/**
* @brief Инициализация I2C
* @param hi2c указатель на хендл I2C
* @param NewConfig указатель на новую конфигурацию I2C, иначе используется та, что в структуре
* @retval OperationStatus OK - если всё хорошо, ERROR - если ошибка
*/
OperationStatus i2c_init(I2C_HandleTypeDef *hi2c, I2C_ExtInit_TypeDef *NewConfig)
{
if(!hi2c || !hi2c->Instance)
return ERROR;
if(NewConfig != NULL)
{
hi2c->Config = NewConfig;
}
if(hi2c->Config == NULL)
{
return ERROR;
}
// Сбрасываем ошибку
hi2c->LastError = I2C_ERROR_NONE;
// Настраиваем частоту SCL
if(hi2c->Config->I2C_Init.HSMode == ENABLE)
{
// Высокоскоростной режим
I2C_HSFreqConfig(hi2c->Config->HSFreq, hi2c->Config->I2CFreq);
}
else
{
// Стандартный/быстрый режим
I2C_FSFreqConfig(hi2c->Config->FSFreq, hi2c->Config->I2CFreq);
}
// Настраиваем таймаут
if(hi2c->Config->I2C_Init.Timeout != DISABLE)
{
I2C_TimeoutClkDivConfig(hi2c->Config->I2C_Init.TimeoutClkDiv);
I2C_SetTimeoutCounterLoad(hi2c->Config->I2C_Init.TimeoutLoad);
}
// Настраиваем дополнительные функции
I2C_AlertResponseMatchCmd(hi2c->Config->I2C_Init.AlertResponse);
I2C_GlobalCallMatchCmd(hi2c->Config->I2C_Init.GlobalCall);
return OK;
}
/**
* @brief Установка коллбека I2C
* @param hi2c указатель на хендл I2C
* @param CallbackType Тип коллбека
* @param Callback Функция коллбека
* @retval OperationStatus OK - если успешно, ERROR - при ошибке
*/
OperationStatus I2C_Set_Callback(I2C_HandleTypeDef* hi2c, I2C_CallbackTypeDef CallbackType, void (*Callback)())
{
if (!hi2c || !hi2c->Instance || !hi2c->Config)
return ERROR;
switch(CallbackType)
{
case I2C_Callback_Tx:
hi2c->Config->TxCallback = Callback;
break;
case I2C_Callback_Rx:
hi2c->Config->RxCallback = Callback;
break;
case I2C_Callback_Addr:
hi2c->Config->AddrCallback = Callback;
break;
case I2C_Callback_Error:
hi2c->Config->ErrCallback = Callback;
break;
default:
return ERROR;
}
return OK;
}
//-- I2C API functions --------------------------------------------------------
/**
* @brief Запуск I2C
* @param hi2c указатель на хендл I2C
* @retval OperationStatus OK - если успешно, ERROR - при ошибке
*/
OperationStatus I2C_Start(I2C_HandleTypeDef *hi2c)
{
if (!hi2c)
return ERROR;
// Сбрасываем ошибку
hi2c->LastError = I2C_ERROR_NONE;
// Включаем I2C
I2C_Cmd(ENABLE);
// Если режим ведомого, настраиваем адрес и включаем распознавание
if(hi2c->Config->I2C_Init.Mode == I2C_Mode_Slave)
{
if(hi2c->Config->I2C_Init.Addr10Bit == ENABLE)
{
I2C_Slave10AddrCmd(ENABLE);
I2C_SetSlave10Addr(hi2c->Config->I2C_Init.SlaveAddr >> 8);
I2C_SetSlaveAddr(hi2c->Config->I2C_Init.SlaveAddr & 0xFF);
}
else
{
I2C_Slave10AddrCmd(DISABLE);
I2C_SetSlaveAddr(hi2c->Config->I2C_Init.SlaveAddr);
}
I2C_SlaveCmd(ENABLE);
}
return OK;
}
/**
* @brief Остановка I2C
* @param hi2c указатель на хендл I2C
* @retval OperationStatus OK - если успешно, ERROR - при ошибке
*/
OperationStatus I2C_Stop(I2C_HandleTypeDef *hi2c)
{
if (!hi2c)
return ERROR;
// Выключаем I2C
I2C_Cmd(DISABLE);
// Если режим ведомого, выключаем распознавание адреса
if(hi2c->Config->I2C_Init.Mode == I2C_Mode_Slave)
{
I2C_SlaveCmd(DISABLE);
}
return OK;
}
/**
* @brief Получение кода последней ошибки
* @param hi2c указатель на хендл I2C
* @retval Код последней ошибки I2C
*/
uint8_t I2C_GetLastError(I2C_HandleTypeDef *hi2c)
{
if (!hi2c)
return I2C_ERROR_NONE;
return hi2c->LastError;
}
//-- I2C Master functions -----------------------------------------------------
/**
* @brief Передача данных в режиме мастера (блокирующий режим)
* @param hi2c указатель на хендл I2C
* @param addr адрес устройства на шине I2C
* @param buf указатель на буфер данных
* @param size размер данных в байтах
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если успешно, ERROR - при ошибке или таймауте
*/
OperationStatus I2C_Master_Transmit(I2C_HandleTypeDef *hi2c,
uint16_t addr,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
{
OperationStatus status;
if (!hi2c || !buf || size == 0)
{
__i2c_set_error(hi2c, I2C_ERROR_NONE);
return ERROR;
}
// Проверяем, свободна ли шина
status = __i2c_master_wait_bus_free(hi2c, timeout);
if (status != OK)
return status;
// Отправляем START
status = __i2c_master_send_start(hi2c, timeout);
if (status != OK)
return status;
// Отправляем адрес с направлением "запись"
status = __i2c_master_send_address(hi2c, addr, I2C_Direction_Transmitter, timeout);
if (status != OK)
{
// При NACK отправляем STOP и выходим
if (hi2c->LastError == I2C_ERROR_NACK)
{
__i2c_master_send_stop(hi2c, timeout);
}
return status;
}
// Передаем данные
status = __i2c_master_transmit_blocking(hi2c, buf, size, timeout);
// Отправляем STOP (даже при ошибке в данных)
__i2c_master_send_stop(hi2c, timeout);
// Если была ошибка передачи данных, возвращаем ошибку
if (status != OK)
return status;
// Вызываем callback успешной передачи
if (hi2c->Config->TxCallback)
hi2c->Config->TxCallback();
return OK;
}
/**
* @brief Прием данных в режиме мастера (блокирующий режим)
* @param hi2c указатель на хендл I2C
* @param addr адрес устройства на шине I2C
* @param buf указатель на буфер приема
* @param size количество принимаемых байт
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если успешно, ERROR - при ошибке или таймауте
*/
OperationStatus I2C_Master_Receive(I2C_HandleTypeDef *hi2c,
uint16_t addr,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
{
OperationStatus status;
if (!hi2c || !buf || size == 0)
{
__i2c_set_error(hi2c, I2C_ERROR_NONE);
return ERROR;
}
// Проверяем, свободна ли шина
status = __i2c_master_wait_bus_free(hi2c, timeout);
if (status != OK)
return status;
// Отправляем START
status = __i2c_master_send_start(hi2c, timeout);
if (status != OK)
return status;
// Отправляем адрес с направлением "чтение"
status = __i2c_master_send_address(hi2c, addr, I2C_Direction_Receiver, timeout);
if (status != OK)
{
// При NACK отправляем STOP и выходим
if (hi2c->LastError == I2C_ERROR_NACK)
{
__i2c_master_send_stop(hi2c, timeout);
}
return status;
}
// Принимаем данные
status = __i2c_master_receive_blocking(hi2c, buf, size, timeout);
// Отправляем STOP (даже при ошибке приема)
__i2c_master_send_stop(hi2c, timeout);
// Если была ошибка приема данных, возвращаем ошибку
if (status != OK)
return status;
// Вызываем callback успешного приема
if (hi2c->Config->RxCallback)
hi2c->Config->RxCallback();
return OK;
}
/**
* @brief Запись регистра устройства (блокирующий режим)
* @param hi2c указатель на хендл I2C
* @param addr адрес устройства на шине I2C
* @param reg адрес регистра
* @param value значение для записи
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если успешно, ERROR - при ошибке или таймауте
*/
OperationStatus I2C_Master_WriteReg(I2C_HandleTypeDef *hi2c,
uint16_t addr,
uint16_t reg,
uint8_t value,
uint32_t timeout)
{
uint8_t data[3];
uint16_t reg_size = (hi2c->Config->I2C_Init.RegSize == I2C_RegSize_8bit) ? 1 : 2;
if (reg_size == 1)
{
data[0] = (uint8_t)reg;
data[1] = value;
return I2C_Master_Transmit(hi2c, addr, data, 2, timeout);
}
else
{
data[0] = (uint8_t)(reg >> 8);
data[1] = (uint8_t)reg;
data[2] = value;
return I2C_Master_Transmit(hi2c, addr, data, 3, timeout);
}
}
/**
* @brief Чтение регистра устройства (блокирующий режим)
* @param hi2c указатель на хендл I2C
* @param addr адрес устройства на шине I2C
* @param reg адрес регистра
* @param buf указатель на буфер для данных
* @param size размер данных для чтения
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если успешно, ERROR - при ошибке или таймауте
*/
OperationStatus I2C_Master_ReadReg(I2C_HandleTypeDef *hi2c,
uint16_t addr,
uint16_t reg,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
{
OperationStatus status;
uint8_t reg_data[2];
uint16_t reg_size = (hi2c->Config->I2C_Init.RegSize == I2C_RegSize_8bit) ? 1 : 2;
// Сначала отправляем адрес регистра
if (reg_size == 1)
{
reg_data[0] = (uint8_t)reg;
status = I2C_Master_Transmit(hi2c, addr, reg_data, 1, timeout);
}
else
{
reg_data[0] = (uint8_t)(reg >> 8);
reg_data[1] = (uint8_t)reg;
status = I2C_Master_Transmit(hi2c, addr, reg_data, 2, timeout);
}
if (status != OK)
return status;
// Затем читаем данные
return I2C_Master_Receive(hi2c, addr, buf, size, timeout);
}
/**
* @brief Запись нескольких регистров (блокирующий режим)
* @param hi2c указатель на хендл I2C
* @param addr адрес устройства на шине I2C
* @param reg начальный адрес регистра
* @param buf указатель на буфер данных
* @param size количество регистров для записи
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если успешно, ERROR - при ошибке или таймауте
*/
OperationStatus I2C_Master_WriteRegs(I2C_HandleTypeDef *hi2c,
uint16_t addr,
uint16_t reg,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
{
OperationStatus status;
uint16_t reg_size = (hi2c->Config->I2C_Init.RegSize == I2C_RegSize_8bit) ? 1 : 2;
// Проверяем, свободна ли шина
status = __i2c_master_wait_bus_free(hi2c, timeout);
if (status != OK)
return status;
// Отправляем START
status = __i2c_master_send_start(hi2c, timeout);
if (status != OK)
return status;
// Отправляем адрес с направлением "запись"
status = __i2c_master_send_address(hi2c, addr, I2C_Direction_Transmitter, timeout);
if (status != OK)
{
// При NACK отправляем STOP и выходим
if (hi2c->LastError == I2C_ERROR_NACK)
{
__i2c_master_send_stop(hi2c, timeout);
}
return status;
}
// Отправляем адрес регистра (первый байт)
if (reg_size == 1)
{
status = __i2c_master_transmit_blocking(hi2c, (uint8_t*)&reg, 1, timeout);
}
else
{
// Для 16-битного адреса отправляем старший, затем младший байт
uint8_t reg_bytes[2] = {(uint8_t)(reg >> 8), (uint8_t)reg};
status = __i2c_master_transmit_blocking(hi2c, reg_bytes, 2, timeout);
}
if (status != OK)
{
__i2c_master_send_stop(hi2c, timeout);
return status;
}
// Отправляем данные
status = __i2c_master_transmit_blocking(hi2c, buf, size, timeout);
// Отправляем STOP
__i2c_master_send_stop(hi2c, timeout);
// Если была ошибка передачи данных, возвращаем ошибку
if (status != OK)
return status;
// Вызываем callback успешной передачи
if (hi2c->Config->TxCallback)
hi2c->Config->TxCallback();
return OK;
}
/**
* @brief Чтение нескольких регистров (блокирующий режим)
* @param hi2c указатель на хендл I2C
* @param addr адрес устройства на шине I2C
* @param reg начальный адрес регистра
* @param buf указатель на буфер для данных
* @param size количество регистров для чтения
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если успешно, ERROR - при ошибке или таймауте
*/
OperationStatus I2C_Master_ReadRegs(I2C_HandleTypeDef *hi2c,
uint16_t addr,
uint16_t reg,
uint8_t *buf,
uint16_t size,
uint32_t timeout)
{
// Для чтения нескольких регистров используется та же функция, что и для одного
// т.к. после отправки адреса регистра можно читать любое количество байт
return I2C_Master_ReadReg(hi2c, addr, reg, buf, size, timeout);
}
/**
* @brief Проверка наличия устройства на шине
* @param hi2c указатель на хендл I2C
* @param addr адрес устройства на шине I2C
* @param timeout таймаут ожидания (мс)
* @retval OperationStatus OK - если устройство отвечает, ERROR - если нет ответа
*/
OperationStatus I2C_Master_IsDeviceReady(I2C_HandleTypeDef *hi2c,
uint16_t addr,
uint32_t timeout)
{
OperationStatus status;
if (!hi2c)
return ERROR;
// Проверяем, свободна ли шина
status = __i2c_master_wait_bus_free(hi2c, timeout);
if (status != OK)
return status;
// Отправляем START
status = __i2c_master_send_start(hi2c, timeout);
if (status != OK)
return status;
// Отправляем адрес с направлением "запись" (любое направление подойдет для проверки)
status = __i2c_master_send_address(hi2c, addr, I2C_Direction_Transmitter, timeout);
// Отправляем STOP независимо от результата
__i2c_master_send_stop(hi2c, timeout);
// Если устройство ответило ACK, значит оно готово
if (status == OK && hi2c->LastError == I2C_ERROR_NONE)
return OK;
return ERROR;
}
//-- I2C GPIO functions -------------------------------------------------------
/**
* @brief Инициализация GPIO для I2C
*/
void i2c_gpio_init(void)
{
#if USE_I2C==1
// Получаем структуры
GPIO_Init_TypeDef *sda_config = gpio_get_init(I2C_GPIO_Port, I2C_SDA_Pin);
GPIO_Init_TypeDef *scl_config = gpio_get_init(I2C_GPIO_Port, I2C_SCL_Pin);
// SDA пин
if (sda_config != NULL)
{
GPIO_StructInit(sda_config);
sda_config->Pin = I2C_SDA_Pin;
sda_config->AltFunc = ENABLE;
sda_config->Digital = ENABLE;
sda_config->OutMode = GPIO_OutMode_OD; // Открытый сток для I2C
sda_config->PullMode = GPIO_PullMode_PU; // Подтяжка к питанию для I2C
GPIO_Init(I2C_GPIO_Port, sda_config);
}
// SCL пин
if (scl_config != NULL)
{
GPIO_StructInit(scl_config);
scl_config->Pin = I2C_SCL_Pin;
scl_config->AltFunc = ENABLE;
scl_config->Digital = ENABLE;
scl_config->OutMode = GPIO_OutMode_OD; // Открытый сток для I2C
scl_config->PullMode = GPIO_PullMode_PU; // Подтяжка к питанию для I2C
GPIO_Init(I2C_GPIO_Port, scl_config);
}
#endif
}
/**
* @brief Деинициализация GPIO для I2C
*/
void i2c_gpio_deinit(void)
{
#if USE_I2C==1
// Получаем структуры
GPIO_Init_TypeDef *sda_config = gpio_get_init(I2C_GPIO_Port, I2C_SDA_Pin);
GPIO_Init_TypeDef *scl_config = gpio_get_init(I2C_GPIO_Port, I2C_SCL_Pin);
// Восстанавливаем оригинальные настройки из таблицы
if (sda_config != NULL)
{
GPIO_StructInit(sda_config);
sda_config->Pin = I2C_SDA_Pin;
GPIO_Init(I2C_GPIO_Port, sda_config);
}
if (scl_config != NULL)
{
GPIO_StructInit(scl_config);
scl_config->Pin = I2C_SCL_Pin;
GPIO_Init(I2C_GPIO_Port, scl_config);
}
#endif
}
//-- I2C private functions ----------------------------------------------------
/**
* @brief Установка ошибки I2C
*/
static void __i2c_set_error(I2C_HandleTypeDef *hi2c, uint8_t error)
{
if (!hi2c)
return;
hi2c->LastError = error;
// Вызываем callback ошибки, если он установлен
if (hi2c->Config->ErrCallback)
hi2c->Config->ErrCallback(error);
}
/**
* @brief Ожидание освобождения шины I2C
*/
static OperationStatus __i2c_master_wait_bus_free(I2C_HandleTypeDef *hi2c, uint32_t timeout)
{
uint32_t starttick = millis();
while(I2C_BusBusyStatus() == SET)
{
if(millis() - starttick > timeout)
{
__i2c_set_error(hi2c, I2C_ERROR_BUS_BUSY);
return ERROR;
}
}
return OK;
}
/**
* @brief Отправка условия START
*/
static OperationStatus __i2c_master_send_start(I2C_HandleTypeDef *hi2c, uint32_t timeout)
{
uint32_t starttick = millis();
I2C_State_TypeDef state;
// Формируем START
I2C_StartCmd();
// Ожидаем подтверждения формирования START
while(1)
{
state = I2C_GetState();
if (state == I2C_State_STDONE || state == I2C_State_HMTMCOK)
{
// START успешно сформирован
return OK;
}
else if (state == I2C_State_BERROR)
{
__i2c_set_error(hi2c, I2C_ERROR_BUS_ERROR);
return ERROR;
}
else if (state == I2C_State_IDLARL || state == I2C_State_HIDLARL)
{
__i2c_set_error(hi2c, I2C_ERROR_ARBITRATION_LOST);
return ERROR;
}
if(millis() - starttick > timeout)
{
__i2c_set_error(hi2c, I2C_ERROR_TIMEOUT);
return ERROR;
}
}
}
/**
* @brief Отправка адреса устройства
*/
static OperationStatus __i2c_master_send_address(I2C_HandleTypeDef *hi2c, uint16_t addr, uint8_t direction, uint32_t timeout)
{
uint8_t address;
uint32_t starttick = millis();
I2C_State_TypeDef state;
// Формируем адрес
if (addr > 0x7F)
{
// 10-битный адрес - первая часть всегда на запись
address = 0xF0 | ((addr >> 7) & 0x06);
I2C_SetData(address | I2C_Direction_Transmitter);
}
else
{
// 7-битный адрес
address = (addr << 1);
I2C_SetData(address | direction);
}
// Сбрасываем флаг прерывания
I2C_ITStatusClear();
// Ожидаем подтверждения адреса
while(1)
{
state = I2C_GetState();
// ACK получен для 7-битного адреса
if ((direction == I2C_Direction_Transmitter &&
(state == I2C_State_MTADPA || state == I2C_State_HMTADPA)) ||
(direction == I2C_Direction_Receiver &&
(state == I2C_State_MRADPA || state == I2C_State_HMRADPA)))
{
return OK;
}
// NACK получен
else if ((direction == I2C_Direction_Transmitter &&
(state == I2C_State_MTADNA || state == I2C_State_HMTADNA)) ||
(direction == I2C_Direction_Receiver &&
(state == I2C_State_MRADNA || state == I2C_State_HMRADNA)))
{
__i2c_set_error(hi2c, I2C_ERROR_NACK);
return ERROR;
}
// Ошибка шины
else if (state == I2C_State_BERROR)
{
__i2c_set_error(hi2c, I2C_ERROR_BUS_ERROR);
return ERROR;
}
// Потеря арбитража
else if (state == I2C_State_IDLARL || state == I2C_State_HIDLARL)
{
__i2c_set_error(hi2c, I2C_ERROR_ARBITRATION_LOST);
return ERROR;
}
if(millis() - starttick > timeout)
{
__i2c_set_error(hi2c, I2C_ERROR_TIMEOUT);
return ERROR;
}
}
}
/**
* @brief Отправка условия STOP
*/
static OperationStatus __i2c_master_send_stop(I2C_HandleTypeDef *hi2c, uint32_t timeout)
{
uint32_t starttick = millis();
// Формируем STOP
I2C_StopCmd();
// Сбрасываем флаг прерывания
I2C_ITStatusClear();
// Ожидаем освобождения шины (опционально, не обязательно)
// while(I2C_BusBusyStatus() == SET)
// {
// if(millis() - starttick > timeout)
// {
// __i2c_set_error(hi2c, I2C_ERROR_TIMEOUT);
// return ERROR;
// }
// }
return OK;
}
/**
* @brief Блокирующая передача данных
*/
static OperationStatus __i2c_master_transmit_blocking(I2C_HandleTypeDef *hi2c, uint8_t *buf, uint16_t size, uint32_t timeout)
{
uint32_t starttick;
I2C_State_TypeDef state;
for(uint16_t i = 0; i < size; i++)
{
// Отправляем байт данных
I2C_SetData(buf[i]);
// Сбрасываем флаг прерывания
I2C_ITStatusClear();
starttick = millis();
// Ожидаем подтверждения байта
while(1)
{
state = I2C_GetState();
// ACK получен
if (state == I2C_State_MTDAPA || state == I2C_State_HMTDAPA)
{
break;
}
// NACK получен
else if (state == I2C_State_MTDANA || state == I2C_State_HMTDANA)
{
__i2c_set_error(hi2c, I2C_ERROR_NACK);
return ERROR;
}
// Ошибка шины
else if (state == I2C_State_BERROR)
{
__i2c_set_error(hi2c, I2C_ERROR_BUS_ERROR);
return ERROR;
}
// Потеря арбитража
else if (state == I2C_State_IDLARL || state == I2C_State_HIDLARL)
{
__i2c_set_error(hi2c, I2C_ERROR_ARBITRATION_LOST);
return ERROR;
}
if(millis() - starttick > timeout)
{
__i2c_set_error(hi2c, I2C_ERROR_TIMEOUT);
return ERROR;
}
}
}
return OK;
}
/**
* @brief Блокирующий прием данных
*/
static OperationStatus __i2c_master_receive_blocking(I2C_HandleTypeDef *hi2c, uint8_t *buf, uint16_t size, uint32_t timeout)
{
uint32_t starttick;
I2C_State_TypeDef state;
for(uint16_t i = 0; i < size; i++)
{
starttick = millis();
// Ожидаем приема байта
while(1)
{
state = I2C_GetState();
// Байт получен с ACK или NACK
if (state == I2C_State_MRDAPA || state == I2C_State_MRDANA ||
state == I2C_State_HMRDAPA || state == I2C_State_HMRDANA)
{
// Читаем данные
buf[i] = I2C_GetData();
// Для последнего байта отправляем NACK
if (i == size - 1)
{
I2C_NACKCmd();
}
break;
}
// Ошибка шины
else if (state == I2C_State_BERROR)
{
__i2c_set_error(hi2c, I2C_ERROR_BUS_ERROR);
return ERROR;
}
// Потеря арбитража
else if (state == I2C_State_IDLARL || state == I2C_State_HIDLARL)
{
__i2c_set_error(hi2c, I2C_ERROR_ARBITRATION_LOST);
return ERROR;
}
if(millis() - starttick > timeout)
{
__i2c_set_error(hi2c, I2C_ERROR_TIMEOUT);
return ERROR;
}
}
}
return OK;
}

183
MDK-ARM/Core/App/i2c.h Normal file
View File

@@ -0,0 +1,183 @@
/**
******************************************************************************
* @file i2c.h
* @author Разваляев Алексей
* @brief Драйвер I2C на основе PLIB035.
* Данный файл содержит определения типов, структур и прототипы функций
* для работы с I2C, включая:
* + Структуры и typedef для I2C
* + Прототипы функций для инициализации и API драйвера
*
******************************************************************************
*/
#ifndef __I2C_H
#define __I2C_H
//-- Includes ------------------------------------------------------------------
#include "plib035.h"
#include "plib035_i2c.h"
#include "retarget_conf.h"
//-- Defines -------------------------------------------------------------------
// Дефайны для пинов I2C
#define I2C_SCL_Pin GPIO_Pin_0 /**< PA0 — I2C SCL */
#define I2C_SDA_Pin GPIO_Pin_1 /**< PA1 — I2C SDA */
#define I2C_GPIO_Port GPIOA /**< GPIO порт I2C */
// Стандартные частоты I2C
#define I2C_STANDARD_MODE 100000 /**< 100 kHz */
#define I2C_FAST_MODE 400000 /**< 400 kHz */
#define I2C_FAST_MODE_PLUS 1000000 /**< 1 MHz */
#define I2C_HIGH_SPEED_MODE 3400000 /**< 3.4 MHz */
// Максимальное время ожидания по умолчанию (мс)
#define I2C_DEFAULT_TIMEOUT 1000
// Коды ошибок I2C
#define I2C_ERROR_NONE 0x00
#define I2C_ERROR_BUS_BUSY 0x01
#define I2C_ERROR_TIMEOUT 0x02
#define I2C_ERROR_NACK 0x03
#define I2C_ERROR_ARBITRATION_LOST 0x04
#define I2C_ERROR_BUS_ERROR 0x05
#define I2C_ERROR_PEC_FAIL 0x06
//-- Types ---------------------------------------------------------------------
/**
* @brief Типы callback-функций I2C
*/
typedef enum
{
I2C_Callback_Tx, /*!< Передача данных завершена */
I2C_Callback_Rx, /*!< Приём данных завершён */
I2C_Callback_Addr, /*!< Ведомый получил свой адрес */
I2C_Callback_Error, /*!< Ошибка I2C */
} I2C_CallbackTypeDef;
/**
* @brief Режимы работы I2C
*/
typedef enum
{
I2C_Mode_Master, /*!< Режим мастера */
I2C_Mode_Slave, /*!< Режим ведомого */
} I2C_ModeTypeDef;
/**
* @brief Направление передачи I2C
*/
typedef enum
{
I2C_Direction_Transmitter, /*!< Направление: передатчик */
I2C_Direction_Receiver, /*!< Направление: приемник */
} I2C_DirectionTypeDef;
/**
* @brief Размер регистра устройства
*/
typedef enum
{
I2C_RegSize_8bit, /*!< Размер регистра: 8 бит */
I2C_RegSize_16bit, /*!< Размер регистра: 16 бит */
} I2C_RegSizeTypeDef;
/**
* @brief Структура инициализации I2C
*/
typedef struct
{
I2C_ModeTypeDef Mode; /*!< Режим работы: I2C_Mode_Master или I2C_Mode_Slave */
FunctionalState HSMode; /*!< Высокоскоростной режим */
FunctionalState Addr10Bit; /*!< 10-битная адресация */
I2C_RegSizeTypeDef RegSize; /*!< Размер регистра: I2C_RegSize_8bit или I2C_RegSize_16bit */
uint16_t SlaveAddr; /*!< Адрес ведомого (для режима Slave) */
FunctionalState Timeout; /*!< Таймаут: */
I2C_TimeoutClkDiv_TypeDef TimeoutClkDiv; /*!< Делитель тактирования таймаута */
uint8_t TimeoutLoad; /*!< Значение загрузки счетчика таймаута */
FunctionalState AlertResponse; /*!< Ответ на тревогу */
FunctionalState GlobalCall; /*!< Общий вызов */
} I2C_Init_TypeDef;
/**
* @brief Расширенная конфигурация I2C
*/
typedef struct
{
I2C_Init_TypeDef I2C_Init; /*!< Базовая конфигурация I2C */
uint32_t I2CFreq; /*!< Частота тактирования I2C в Гц */
uint32_t FSFreq; /*!< Частота SCL в стандартном режиме в Гц */
uint32_t HSFreq; /*!< Частота SCL в высокоскоростном режиме в Гц */
/* Callback функции */
void (*TxCallback)(void); /*!< Вызывается при завершении передачи */
void (*RxCallback)(void); /*!< Вызывается при завершении приема */
void (*AddrCallback)(void); /*!< Вызывается когда ведомый получает свой адрес */
void (*ErrCallback)(uint8_t error); /*!< Вызывается при ошибке I2C с кодом ошибки */
} I2C_ExtInit_TypeDef;
/**
* @brief Хендл I2C
*/
typedef struct
{
I2C_TypeDef *Instance; /*!< Регистры I2C */
I2C_ExtInit_TypeDef *Config; /*!< Конфигурация I2C */
uint8_t LastError; /*!< Код последней ошибки */
} I2C_HandleTypeDef;
//-- External handles ----------------------------------------------------------
extern I2C_HandleTypeDef hi2c;
//-- Exported functions prototypes ---------------------------------------------
/* Init functions */
/* Первичная инициализация I2C */
void i2c_init_first(void);
/* Инициализация I2C */
OperationStatus i2c_init(I2C_HandleTypeDef *hi2c, I2C_ExtInit_TypeDef *NewConfig);
/* Инициализация GPIO для I2C */
void i2c_gpio_init(void);
/* Деинициализация GPIO для I2C */
void i2c_gpio_deinit(void);
/* API functions*/
/* Установка callback-функции I2C */
OperationStatus I2C_Set_Callback(I2C_HandleTypeDef *hi2c, I2C_CallbackTypeDef CallbackType, void (*Callback)());
/* Запуск I2C */
OperationStatus I2C_Start(I2C_HandleTypeDef *hi2c);
/* Остановка I2C */
OperationStatus I2C_Stop(I2C_HandleTypeDef *hi2c);
/* Получение кода последней ошибки */
uint8_t I2C_GetLastError(I2C_HandleTypeDef *hi2c);
/* Передача данных в режиме мастера (блокирующий режим) */
OperationStatus I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t addr, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Прием данных в режиме мастера (блокирующий режим) */
OperationStatus I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t addr, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Запись регистра устройства (блокирующий режим) */
OperationStatus I2C_Master_WriteReg(I2C_HandleTypeDef *hi2c, uint16_t addr, uint16_t reg, uint8_t value, uint32_t timeout);
/* Чтение регистра устройства (блокирующий режим) */
OperationStatus I2C_Master_ReadReg(I2C_HandleTypeDef *hi2c, uint16_t addr, uint16_t reg, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Запись нескольких регистров (блокирующий режим) */
OperationStatus I2C_Master_WriteRegs(I2C_HandleTypeDef *hi2c, uint16_t addr, uint16_t reg, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Чтение нескольких регистров (блокирующий режим) */
OperationStatus I2C_Master_ReadRegs(I2C_HandleTypeDef *hi2c, uint16_t addr, uint16_t reg, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Проверка наличия устройства на шине */
OperationStatus I2C_Master_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t addr, uint32_t timeout);
#endif /*__I2C_H*/

View File

@@ -17,8 +17,9 @@ void periph_init()
{
sysclk_init();
uart_init_first();
adc_init_first();
tmr_init_first();
adc_init_first();
i2c_init_first();
gpio_init();
#ifdef RETARGET
retarget_init();

View File

@@ -33,6 +33,7 @@
#include "uart.h"
#include "tmr.h"
#include "adc.h"
#include "i2c.h"
/* Обработчик ошибок */
void Error_Handler(void);
@@ -59,6 +60,10 @@ void Error_Handler(void);
#define USE_ADC_DC2 0 /*!< Использовать Компаратор 2 */
#define USE_ADC_DC3 0 /*!< Использовать Компаратор 3 */
/* I2C */
#define USE_I2C 0 /*!< Использовать I2C */
/** @note Для RETARGET надо объявить этот дефайн в проекте
Options for Target -> C/C++ -> Defines
*/
@@ -306,6 +311,23 @@ static ADC_DC_ExtInit_TypeDef adc_dc3_config = {
};
#endif
//-- I2C Конфигурации ---------------------------------------------------------
#if USE_I2C==1
static I2C_ExtInit_TypeDef i2c_config = {
//Mode, HSMode, Addr10Bit, RegSize, SlaveAddr
I2C_Mode_Master, DISABLE, DISABLE, I2C_RegSize_8bit, 0x00,
//Timeout, TimeoutClkDiv, TimeoutLoad
DISABLE, I2C_TimeoutClkDiv_Div4, 0x00,
//AlertResponse, GlobalCall
DISABLE, DISABLE,
//I2CFreq, FSFreq, HSFreq
SYSCLK_CORE_CLOCK_MHZ * __MHZ, I2C_STANDARD_MODE, I2C_HIGH_SPEED_MODE,
//TxCallback, RxCallback, AddrCallback, ErrCallback
NULL, NULL, NULL, NULL
};
#endif
//-- NVIC Конфигурации --------------------------------------------------------
/** @brief Приоритеты прерываний, 0 - самый высокий приоритет*/
static uint8_t NCIV_Priorities[] =

View File

@@ -77,7 +77,7 @@
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>1</IsCurrentTarget>
</OPTFL>
<CpuCode>0</CpuCode>
<CpuCode>255</CpuCode>
<DebugOpt>
<uSim>0</uSim>
<uTrg>1</uTrg>
@@ -380,6 +380,18 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\Core\App\i2c.c</PathWithFileName>
<FilenameWithoutPath>i2c.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>11</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\Core\App\sysclk.c</PathWithFileName>
<FilenameWithoutPath>sysclk.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
@@ -387,7 +399,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>11</FileNumber>
<FileNumber>12</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -407,7 +419,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>12</FileNumber>
<FileNumber>13</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -419,7 +431,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>13</FileNumber>
<FileNumber>14</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -431,7 +443,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>14</FileNumber>
<FileNumber>15</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -443,7 +455,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>15</FileNumber>
<FileNumber>16</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -455,7 +467,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>16</FileNumber>
<FileNumber>17</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -467,7 +479,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>17</FileNumber>
<FileNumber>18</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -479,7 +491,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>18</FileNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -491,7 +503,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>19</FileNumber>
<FileNumber>20</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -503,7 +515,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>20</FileNumber>
<FileNumber>21</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -515,7 +527,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>21</FileNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -535,7 +547,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>22</FileNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -547,7 +559,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>23</FileNumber>
<FileNumber>24</FileNumber>
<FileType>2</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -567,7 +579,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>24</FileNumber>
<FileNumber>25</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -579,7 +591,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>25</FileNumber>
<FileNumber>26</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -591,7 +603,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>26</FileNumber>
<FileNumber>27</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -603,7 +615,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>27</FileNumber>
<FileNumber>28</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -615,7 +627,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>28</FileNumber>
<FileNumber>29</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -627,7 +639,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>29</FileNumber>
<FileNumber>30</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -639,7 +651,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>30</FileNumber>
<FileNumber>31</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -651,7 +663,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>31</FileNumber>
<FileNumber>32</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -663,7 +675,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>32</FileNumber>
<FileNumber>33</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -675,7 +687,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>33</FileNumber>
<FileNumber>34</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -687,7 +699,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>34</FileNumber>
<FileNumber>35</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -699,7 +711,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>35</FileNumber>
<FileNumber>36</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -711,7 +723,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>36</FileNumber>
<FileNumber>37</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -723,7 +735,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>37</FileNumber>
<FileNumber>38</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -735,7 +747,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>38</FileNumber>
<FileNumber>39</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -755,7 +767,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>39</FileNumber>
<FileNumber>40</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -767,7 +779,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>40</FileNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@@ -779,7 +791,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>41</FileNumber>
<FileNumber>42</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>

View File

@@ -434,6 +434,11 @@
<FileType>1</FileType>
<FilePath>.\Core\App\adc.c</FilePath>
</File>
<File>
<FileName>i2c.c</FileName>
<FileType>1</FileType>
<FilePath>.\Core\App\i2c.c</FilePath>
</File>
<File>
<FileName>sysclk.c</FileName>
<FileType>1</FileType>

Some files were not shown because too many files have changed in this diff Show More