Данная реализация функции осуществляется на основе данных из rm0008 и es096.
Тайминги заданные в примере рассчитаны для режима стандартной скорости (100кГц) при частоте тактирования шины 8МГц.
void I2C1_Init (void) {
//1 - Отключите периферийное устройство I2C, очистив бит PE в регистре I2Cx_CR1.
I2C1->CR1 &= ~I2C_CR1_PE; //Отключение модуля
//2 - Настройте входы/выходы SCL и SDA как выходы общего назначения с открытым стоком, высокий уровень (запишите 1 в GPIOx_ODR).
GPIOB->CRL |= GPIO_CRL_MODE6_1 | GPIO_CRL_MODE7_1 | GPIO_CRL_CNF6_0 | GPIO_CRL_CNF7_0; //SCL and SDA - Open-Drain выходы общего назначения, макс.скорость 2МГц
GPIOB->BSRR = GPIO_BSRR_BS6 | GPIO_BSRR_BS7; //Высокий уровень на выходах SCL и SDA
//3 - Check SCL and SDA High level in GPIOx_IDR. Проверьте высокий уровень SCL и SDA в GPIOx_IDR.
while (!(GPIOB->IDR &(GPIO_IDR_IDR6 | GPIO_IDR_IDR7)));
//4 - Настройте ввод-вывод SDA как выход общего назначения с открытым стоком, низкий уровень (запишите 0 в GPIOx_ODR).
GPIOB->CRL |= GPIO_CRL_MODE7_1 | GPIO_CRL_CNF7_0; //SDA - Open-Drain выходы общего назначения, макс.скорость 2МГц
GPIOB->BSRR = GPIO_BSRR_BR7; //Низкий уровень на выходе SDA
//5 - Check SDA Low level in GPIOx_IDR. Проверьте низкий уровень SDA в GPIOx_IDR.
while (GPIOB->IDR & GPIO_IDR_IDR7);
//6 - Настройте ввод/вывод SCL как выход общего назначения с открытым стоком, низкий уровень (запишите 0 в GPIOx_ODR).
GPIOB->CRL |= GPIO_CRL_MODE6_1 | GPIO_CRL_CNF6_0; //SCL - Open-Drain выходы общего назначения, макс.скорость 2МГц
GPIOB->BSRR = GPIO_BSRR_BR6; //Низкий уровень на выходе SCL
//7 - Check SCL Low level in GPIOx_IDR. Проверьте низкий уровень SCL в GPIOx_IDR.
while (GPIOB->IDR & GPIO_IDR_IDR6);
//8 - Настройте ввод-вывод SCL как выход общего назначения с открытым стоком, высокий уровень (запишите 1 в GPIOx_ODR).
GPIOB->CRL |= GPIO_CRL_MODE6_1 | GPIO_CRL_CNF6_0;
GPIOB->BSRR = GPIO_BSRR_BS6;
//9 - Check SCL High level in GPIOx_IDR. Проверьте высокий уровень SCL в GPIOx_IDR.
while (!(GPIOB->IDR & GPIO_IDR_IDR6));
//10 - Настройте ввод-вывод SDA как выход общего назначения с открытым стоком, высокий уровень (запишите 1 в GPIOx_ODR).
GPIOB->CRL |= GPIO_CRL_MODE7_1 | GPIO_CRL_CNF7_0;
GPIOB->BSRR = GPIO_BSRR_BS7;
//11 - Check SDA High level in GPIOx_IDR. Проверьте высокий уровень SDA в GPIOx_IDR.
while (!(GPIOB->IDR & GPIO_IDR_IDR7));
//12 - Настройте входы/выходы SCL и SDA как альтернативную функцию с открытым стоком.
GPIOB->CRL |= GPIO_CRL_MODE6_1 | GPIO_CRL_MODE7_1 | GPIO_CRL_CNF6_0 | GPIO_CRL_CNF6_1 | GPIO_CRL_CNF7_0 | GPIO_CRL_CNF7_1;
//13 - Установите бит SWRST в регистре I2Cx_CR1.
I2C1->CR1 |= I2C_CR1_SWRST;
//14 - Очистить бит SWRST в регистре I2Cx_CR1.
I2C1->CR1 &= ~I2C_CR1_SWRST;
//----------------------------------------------
//15
//На 100кГц при частоте шины 8МГц
//I2C1->OAR1 &= ~I2C_OAR1_ADDMODE; //7-ми битный режим адресации (по умолчанию)
I2C1->OAR1 |= (1<<14); //Программно необходимо всегда поддерживать значение "1"
I2C1->OAR1 |= 0x00FE; //Собственный адрес устройства 0xFE
//I2C1->OAR2 &= ~I2C_OAR2_ENDUAL; //Отключить режим двойной адресации (по умолчанию)
//I2C1->CR1 &= ~I2C_CR1_ENGC; //Отключить отклик на широковещательный запрос (по умолчанию)
//I2C1->CR1 &= ~I2C_CR1_NOSTRETCH; //Включить растягивание тактового сигнала (по умолчанию)
I2C1->CR1 |= I2C_CR1_ACK; //разрешение отправки ACK/NACK после приема байта адреса или данных.
I2C1->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITERREN | I2C_CR2_ITBUFEN; //Разрешить прерывания по событию, при ошибке и буферное
I2C1->CR2 |= 0x0010; //Записываем значение частоты тактирования шина (8МГц) в битовое поле FREQ[5:0]
I2C1->CCR |= 0x0028; //Настройка частоты CCR[11:0]=40
I2C1->TRISE = 0x0009; //Задание времени нарастания фронта TRISE=9
NVIC_EnableIRQ (I2C1_EV_IRQn); //Разрешения прерывания по событию I2C в контроллере прерываний
NVIC_EnableIRQ (I2C1_ER_IRQn); //Разрешения прерывания по ошибке I2C в контроллере прерываний
I2C1->CR1 |= I2C_CR1_PE; //Включить модуль
}
Манипуляции произведенные в пунктах 1 ... 14 необходимы для исключения ошибочной установки флага занятости из-за работы аналогового фильтра. Подробную информацию можно прочитать в es096 п.2.8.7