План был таков:
1) Настроить пины. Контроллер STM32F303VCT6, пины PB6 и PB7 принадлежат порту GPIOB. Тактирование порта осуществляется шиной AHB. Пины настраиваются без pull-up/pull-down, т.к. на схеме отладочной платы они оснащены резисторами. Также пины настраиваются на выполнение альтернативной функции AF4 (согласно даташиту STM32F303VCT6 эта функция представлят собой SDA и SCL линии I2C1).
2) Настройка I2C1. Содержимое регистра TIMINGR добыл из CubeMX, включив в нем I2C1 на PB6 и PB7 (параметры I2C - на вкладке Configuraion). Rise time = 500 нс и Fall time = 100 нс взяты из даташита на LSM303DLHC (там даны диапазоны, и я брал посерединке 500 и 100). CubeMX сгенерировал содержимое TIMINGR. В конце функции initSystem() включается периферия I2C1.
3) Функция main просто настраивает СR2 для I2C1 (для записи, чтобы ) и затем устанавливает START. Далее посылает адрес регистра 0x28 и потом она должна читать данные.
Программа компилируется, но не работает дальше строки 40. Цикл не прерывается, из-за того, что (I2C1->ISR & I2C_ISR_TXIS) == 0 постоянно выполняется. При этом, данные 0x28 находятся в регистре TXDR (вижу, запуская в отладчике uVision). После установки START, бит BUSY в I2C1->ISR устанавливается (тоже в отладчике смотрю).
Прошу подсказать, что не так. Сейчас копаю в сторону того, что пины PB6 и PB7 настроены некорректно. Пока безрезультатно. Код ниже.
Акселерометр рабочий, т.к. демонстрационные приложения к плате работают.
Код: Выделить всё
#include "stm32f3xx.h" // Device header
void initSystem()
{
// LSM303DLHC SCL на PB6, SDA на PB7.
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
GPIOB->MODER |= GPIO_MODER_MODER6_1|GPIO_MODER_MODER7_1;
GPIOB->OTYPER |= GPIO_OTYPER_OT_6|GPIO_OTYPER_OT_7;
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR6 | GPIO_PUPDR_PUPDR7 );
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6 |GPIO_OSPEEDER_OSPEEDR7;
// Альт. функция AF4 (0100=0x4) вкл. I2C1_SCL на PB6 и I2C1_SDA на PB7.
GPIOB->AFR[0] |= (0x4 << GPIO_AFRL_AFRL6_Pos);
GPIOB->AFR[0] |= (0x4 << GPIO_AFRL_AFRL7_Pos);
// Вкл. I2C peripheral clock.
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
// Уст. TIMINGR (CubeMX).
I2C1->TIMINGR = 0x00501E26;
// Peripheral Enable.
I2C1->CR1 |= I2C_CR1_PE;
}
// Переменная для данных.
uint32_t buffer[5];
// Счетчик.
uint32_t i = 5;
int main()
{
initSystem();
// Уст. CR2. Запись.
I2C1->CR2 |= (I2C_CR2_NBYTES & 1); // 1 байт (NBYTES).
I2C1->CR2 &= ~I2C_CR2_RD_WRN; // Запись. Бит 0 в RD_WRN.
I2C1->CR2 |= 0x19 << 1; // Адрес акселерометра (без r/w бита).
I2C1->CR2 |= I2C_CR2_START; // Уст. START. Мастер посылает СТАРТ, адрес слейва и R/W бит.
while ((I2C1->ISR & I2C_ISR_TC) == 0); // Ждем Transfer Complete.
I2C1->TXDR = 0x28; // Новые данные (адрес внутреннего регистра) кладем в TXDR.
while ((I2C1->ISR & I2C_ISR_TXIS) == 0); // Ждем пока TXDR станет пустым и готовым к новым данным. ------ ЗДЕСЬ программа виснет-----
// Уст. CR2 для чтения.
I2C1->CR2 = I2C_CR2_AUTOEND | (I2C_CR2_NBYTES & 5) | I2C_CR2_RD_WRN | 0x19 << 1;
I2C1->CR2 |= I2C_CR2_START;
// Чтение.
while (i-- > 0)
{
while((I2C1->ISR & I2C_ISR_RXNE) == 0); // Ждем пока recieve data register будет готов.
buffer [i] = I2C1->RXDR; // Копируем данные из recieve data register.
}
while(1)
{
}
}


