Контроллер - STM32F100 на отладке Discovery. Для начала попробовал спрашивать ID производителя, пишут, что датчик должен отвечать "TI".
Код инициализации:
Код
//I2C1 is the master
void I2C1Init (void){
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
//SCL line
GPIOB->CRL &= ~GPIO_CRL_MODE6;
GPIOB->CRL |= GPIO_CRL_MODE6_1;
GPIOB->CRL |= GPIO_CRL_CNF6;
//SDA line
GPIOB->CRL &= ~GPIO_CRL_MODE7;
GPIOB->CRL |= GPIO_CRL_MODE7_1;
GPIOB->CRL |= GPIO_CRL_CNF7;
//Periph init
I2C1->CR2 |= 0x18;//24 MHz - APB2 frequency
I2C1->CCR |= I2C_CCR_FS;
I2C1->CCR &= ~I2C_CCR_DUTY;
I2C1->CCR |= 0x24;//1500 ns high, 3000 ns low state
I2C1->TRISE |= 0x08;//300 ns rise time
//I2C1->CR1 |= I2C_CR1_ACK;
//I2C1->CR1 |= I2C_CR1_PE;
}
void I2C1Init (void){
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
//SCL line
GPIOB->CRL &= ~GPIO_CRL_MODE6;
GPIOB->CRL |= GPIO_CRL_MODE6_1;
GPIOB->CRL |= GPIO_CRL_CNF6;
//SDA line
GPIOB->CRL &= ~GPIO_CRL_MODE7;
GPIOB->CRL |= GPIO_CRL_MODE7_1;
GPIOB->CRL |= GPIO_CRL_CNF7;
//Periph init
I2C1->CR2 |= 0x18;//24 MHz - APB2 frequency
I2C1->CCR |= I2C_CCR_FS;
I2C1->CCR &= ~I2C_CCR_DUTY;
I2C1->CCR |= 0x24;//1500 ns high, 3000 ns low state
I2C1->TRISE |= 0x08;//300 ns rise time
//I2C1->CR1 |= I2C_CR1_ACK;
//I2C1->CR1 |= I2C_CR1_PE;
}
Функция опроса:
Код
uint16_t I2C1Send (void){
uint8_t OPTWriteAddress = 0x88;
uint8_t OPTReadAddress = 0x89;
uint8_t IDRegister = 0x7E;
uint8_t OPTIDMSB = 0;
uint8_t OPTIDLSB = 0;
uint16_t result = 0;
I2C1->CR1 |= I2C_CR1_PE;
I2C1->CR1 |= I2C_CR1_ACK;
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB)){}
I2C1->DR = OPTWriteAddress;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){}
(void)I2C1->SR1;
(void)I2C1->SR2;
I2C1->DR = IDRegister;
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB)){}
I2C1->DR = OPTReadAddress;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){}
(void)I2C1->SR1;
(void)I2C1->SR2;
while(!(I2C_SR1_RXNE)){}
OPTIDMSB = I2C1->DR;
while(!(I2C_SR1_RXNE)){}
OPTIDLSB = I2C1->DR;
I2C1->CR1 &= ~I2C_CR1_ACK;
I2C1->CR1 |= I2C_CR1_STOP;
result = (OPTIDMSB<<8) | OPTIDLSB;
return result;
}
uint8_t OPTWriteAddress = 0x88;
uint8_t OPTReadAddress = 0x89;
uint8_t IDRegister = 0x7E;
uint8_t OPTIDMSB = 0;
uint8_t OPTIDLSB = 0;
uint16_t result = 0;
I2C1->CR1 |= I2C_CR1_PE;
I2C1->CR1 |= I2C_CR1_ACK;
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB)){}
I2C1->DR = OPTWriteAddress;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){}
(void)I2C1->SR1;
(void)I2C1->SR2;
I2C1->DR = IDRegister;
I2C1->CR1 |= I2C_CR1_START;
while (!(I2C1->SR1 & I2C_SR1_SB)){}
I2C1->DR = OPTReadAddress;
while(!(I2C1->SR1 & I2C_SR1_ADDR)){}
(void)I2C1->SR1;
(void)I2C1->SR2;
while(!(I2C_SR1_RXNE)){}
OPTIDMSB = I2C1->DR;
while(!(I2C_SR1_RXNE)){}
OPTIDLSB = I2C1->DR;
I2C1->CR1 &= ~I2C_CR1_ACK;
I2C1->CR1 |= I2C_CR1_STOP;
result = (OPTIDMSB<<8) | OPTIDLSB;
return result;
}
Проблема:
Сейчас функция зависает на строке "while(!(I2C1->SR1 & I2C_SR1_ADDR)){}", т.е. подтверждения адреса от датчика не приходит.
Вопросы:
1) Правильно ли организована функция опроса?
2) Можно ли при отладке проходить функцию пошагово - в паспорте на OPT пишут, что у него есть 25 мс таймаут по шине при SCLK в низком, не мешает ли это шагать по строкам?
3) В документации на отладку с датчиком написано, что его нога ADDR подключена к земле, т.е. адрес 1000100.
Т.е. если я хочу туда что-то записать, то получаю адрес 10001000 = 0х88, правильно посчитал?
До этого делал передачу по Айтуси на самой отладке между двумя интерфейсами, функции были другие, но работали.