|
I2C, stm32f4, мастер, проблемы с запуском. |
|
|
|
Aug 2 2012, 23:58
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
Я генерирую старт устанавливая бит8 в регистре CR1, затем проверяю бит0 в регистре SR1, нот тот бит так и не устанавливается. Вот привожу ниже фрагменты основного кода. генерирую клоки, системный 168МГц, АПБ1 - 42МГц: Код static uint32_t pll_start(uint32_t N, uint32_t M, uint32_t P) { RCC_CR_HSEON_bb = 1; // enable HSE clock flash_latency(168000000ul); // configure Flash latency for given frequency
RCC->PLLCFGR = (M << RCC_PLLCFGR_PLLM_bit) | (N << RCC_PLLCFGR_PLLN_bit) | ((P/2-1) << RCC_PLLCFGR_PLLP_bit) | RCC_PLLCFGR_PLLQ_DIV9 | RCC_PLLCFGR_PLLSRC_HSE; // configure PLL factors, // always divide USB clock by 9
RCC->CFGR = RCC_CFGR_PPRE2_DIV2 | // APB2 - divide by 2 RCC_CFGR_PPRE1_DIV4 | // APB1 - divide by 4, RCC_CFGR_HPRE_DIV1; // AHB - no prescaler,
while (!RCC_CR_HSERDY_bb); // wait for stable clock
RCC_CR_PLLON_bb = 1; // enable PLL while (!RCC_CR_PLLRDY_bb); // wait for PLL lock
RCC->CFGR |= RCC_CFGR_SW_PLL; // change SYSCLK to PLL
// wait for switch while (((RCC->CFGR) & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
return 1; } тут я настраиваю ножки (для SPI2 и I2C1 который не работает): CODE #include <stdint.h> #include "inc/stm32f4xx.h"
uint32_t config_gpio_all(void) {
//============================================================================= // GPIOB configuration //=============================================================================
// enable GPIOB clock ((RCC_TypeDef *)(RCC_BASE))->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
// Configure GPIOB module // Alternate Function for SPI2, I2C1 ((GPIO_TypeDef *)(GPIOB_BASE))->MODER |= (GPIO_MODER_MODER13_1 | GPIO_MODER_MODER15_1 | GPIO_MODER_MODER9_1 | GPIO_MODER_MODER8_1 );
// Output type for SPI2, I2C1 ((GPIO_TypeDef *)(GPIOB_BASE))->OTYPER |= (GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9);
// Speed type for SPI2, I2C1 ((GPIO_TypeDef *)(GPIOB_BASE))->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR13_1 | GPIO_OSPEEDER_OSPEEDR15_1 | GPIO_OSPEEDER_OSPEEDR9_1 | GPIO_OSPEEDER_OSPEEDR8_1 );
// Push/Pull for I2C1, SPI2 ((GPIO_TypeDef *)(GPIOB_BASE))->PUPDR |= 0x00;
//((GPIO_TypeDef *)(GPIOB_BASE))->IDR |= RCC_AHB1ENR_GPIOBEN; //((GPIO_TypeDef *)(GPIOB_BASE))->ODR |= RCC_AHB1ENR_GPIOBEN; //((GPIO_TypeDef *)(GPIOB_BASE))->BSRRL |= RCC_AHB1ENR_GPIOBEN; //((GPIO_TypeDef *)(GPIOB_BASE))->BSRRH |= RCC_AHB1ENR_GPIOBEN; //((GPIO_TypeDef *)(GPIOB_BASE))->LCKR |= RCC_AHB1ENR_GPIOBEN; //((GPIO_TypeDef *)(GPIOB_BASE))->AFR[1] |= (0x500000 | 0x50000000);
// Alternate Function pin connection for I2C1, SPI2 ((GPIO_TypeDef *)(GPIOB_BASE))->AFR[1] |= ((5 << ((13 - 8) << 2)) | // SPI2 SCK, AF5 (5 << ((15 - 8) << 2)) | // SPI2 MOSI, AF5 (5 << ((8 - 8) << 2)) | // I2C1 SCL, AF4 (5 << ((9 - 8) << 2)) ); // I2C1 SDA, AF4
return 0; }
тут я инициализирую I2C1: CODE #include <stdint.h> #include "inc/stm32f4xx.h" #include "i2c.h"
uint32_t config_i2c_all(void) {
//============================================================================= // I2C1 Related configuration //============================================================================= // enable I2C1 clock ((RCC_TypeDef *) (RCC_BASE))->APB1ENR |= RCC_APB1ENR_I2C1EN;
// 1) configure I2C_CR2 ((I2C_TypeDef *) (I2C1_BASE)) -> CR2 |= (I2C_CR2_FREQ_5 | I2C_CR2_FREQ_3 | I2C_CR2_FREQ_1); // APB1 clock is 42MHz
// 2) Configure Clock Control Register, I2C_CCR // // 100KHz, APB1clk=42MHz, T_high = T_low = (1/42MHz)*210 = 5us ((I2C_TypeDef *) (I2C1_BASE)) -> CCR = 0xd2; // d210
// 3) Configure I2C_TRISE, Rise Time register ((I2C_TypeDef *) (I2C1_BASE)) -> TRISE = 0x2b; // d42 (42 + 1)
// 4) enable I2C1 peripheral ((I2C_TypeDef *) (I2C1_BASE)) -> CR1 |= (I2C_CR1_PE);
return 0; }
вроде как все просто, стандартный режим, 100КГц, соответственная инициализация, но он во время дебага застревает на первом цикле где я читаю SR1 чтобы проверить бит SB == 1 Код //============================================================================= // generating START //=============================================================================
((I2C_TypeDef *) (I2C1_BASE)) -> CR1 |= I2C_CR1_START;
//============================================================================= // Check if start bit is set, and writing Slave Address to the DR register //=============================================================================
// Read SR1, check if SB == 1 while ( !(((tmp0 >> 0) & 0x01) == 1) ) { tmp0 = ((I2C_TypeDef *) (I2C1_BASE)) -> SR1; } tmp0 = 0; // clear Клок периферии настроен на 42МГц. Это я точно знаю, проверяю даже осциллографом на выходах SPI, там делитель на 8 стоит, и у меня клок 5.25МГц. А вот I2C даже не запускается, и тут пока проблема не в самом протоколе, а именно в том что само событие СТАРТ не генерируется. В референс мануале например пишется на странице 580 последовательность: 1) загрузить CR2 частотой, и я кладу туда 101010 = 42, т.к. частота периферийного клока 42МГц. 2) сконфигурировать CCR, и я кладу туда: 210, т.к. (1/42МГц) * 210 = 5 микросекунд, что и нужно для 100КГц скорости 3) запрагроммировать TRISE значением на 1МГц больше чем значение частоты в регистре CR2, в моем случае это 42 + 1 = 43 4) и наконец включить сам модуль I2C Ну и все, после этого как генерируеш старт то бит SB в регистре SR1 должен быть проставлен, но он по прежнему ноль. что там может быть еще не так?
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
 |
Ответов
(1 - 8)
|
Aug 3 2012, 07:51
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
кстати с GPIO тоже есть вопросы. мне кажется он в начале не совсем был правильно настроен. вот как он настроен сейчас: в коментах для удобства привожу в какой режим какой пин ставлю Код uint32_t config_gpio_all(void) {
//============================================================================= // GPIOB configuration //=============================================================================
// enable GPIOB clock ((RCC_TypeDef *)(RCC_BASE))->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
// Configure GPIOB module // Alternate Function for SPI2, I2C1 ((GPIO_TypeDef *)(GPIOB_BASE))->MODER |= (GPIO_MODER_MODER13_1 | // Alternate Function GPIO_MODER_MODER15_1 | // Alternate Function GPIO_MODER_MODER9_1 | // Alternate Function, I2C1, SDA GPIO_MODER_MODER8_1 ); // Alternate Function, I2C1, SCL
// Output type for SPI2, I2C1 ((GPIO_TypeDef *)(GPIOB_BASE))->OTYPER |= (GPIO_OTYPER_OT_8 | // Open-Drain, I2C1, SCL GPIO_OTYPER_OT_9); // OPen-Drain, I2C1, SDA
// Speed type for SPI2, (I2C1 is LOW Speed, 2MHz) ((GPIO_TypeDef *)(GPIOB_BASE))->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR13_1 | GPIO_OSPEEDER_OSPEEDR15_1);
// Push/Pull for I2C1, SPI2 ((GPIO_TypeDef *)(GPIOB_BASE))->PUPDR |= ( GPIO_PUPDR_PUPDR8_1 | // Pull-Down, I2C1, SCL GPIO_PUPDR_PUPDR9_1 // Pull-Down, I2C1, SDA );
// Alternate Function pin connection for I2C1, SPI2 ((GPIO_TypeDef *)(GPIOB_BASE))->AFR[1] |= ((5 << ((13 - 8) << 2)) | // SPI2 SCK, AF5 (5 << ((15 - 8) << 2)) | // SPI2 MOSI, AF5 (5 << ((8 - 8) << 2)) | // I2C1 SCL, AF4 (5 << ((9 - 8) << 2)) ); // I2C1 SDA, AF4
return 0; } но всеравно не работает. Не ставится тот бит после активации события СТАРТ. и еще, копаюсь тут в интернете, и вижу что почти аналогичная проблема (застой после активации старта) вроде как часто всплывает, и все пишут по разному у кого как сработало. немного не ясно.
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Aug 3 2012, 14:46
|

Знающий
   
Группа: Свой
Сообщений: 618
Регистрация: 7-06-08
Из: USSR
Пользователь №: 38 121

|
вот я прикрепляю снимок с осциллографа, верхний график SDA нижний SCL. т.е. Мастер модуль вроде как пытается сгенерить старт пока клок=1, хоть и с большим опозданием, но клок так и не становится активным, почемуто всевремя прижат к нулю. и SDA идет вверх. пробовал тоже самое просто после того как включил мастер модуль, т.е. без посылки СТАРТа и чего либо. тоже самое. Может чтото не так сконфигурировано всетаки? Может еще чтото там должно быть? перепроверил уже почти все комбинации пина: пуш-пулл, пулл-даун пуш-пулл, пулл-ап, опэн-дрэйн, пулл-ап, опэн-дрэйн, пулл-даун картина одна и таже на осциллографе. какая комбинация там вообще должна быть? мне кажется чтото не так с клоком, он просто не тикает, но почему? ведь все же настроено правильно. я пробовал снизить клок периферии (ну и соответственно подправить параметры инициализации I2C), та же фигня.
Эскизы прикрепленных изображений
--------------------
Нажми на кнопку - получишь результат, и твоя мечта осуществится
|
|
|
|
|
Aug 4 2012, 12:37
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(BlackOps @ Aug 4 2012, 07:10)  незнаю, это правда что в этих чипах аппаратный глюк есть на модуле i2c? Кто нибудь сдесь использовал данный чип с i2c? как его запустить (без использования этой стандартной библиотеки) ? Работает. Код RCC->APB1ENR = (1 << RCC_APB1_I2C1); RCC->APB2ENR = (1 << RCC_APB2_SYSCFG); RCC->AHB1ENR = (1 << RCC_AHB1_PORTB); GPIOB->MODER = (GPIO_MODE_ALTERNATE << GPIO_MODER_PIN8) | (GPIO_MODE_ALTERNATE << GPIO_MODER_PIN9); GPIOB->AFR[1] = (AF_PB8_I2C1_SCL << GPIO_AFR1_PIN8) | (AF_PB9_I2C1_SDA << GPIO_AFR1_PIN9);
GPIOB->OTYPER = (1 << 8) | (1 << 9);
I2C1->CR1 = (0 << I2C_CR1_PE); I2C1->CR2 = (I2C_FREQ_42MHZ << I2C_CR2_FREQ) | (1 << I2C_CR2_ITEVTEN); I2C1->CCR = I2C_FREQ_42MHZ * 1000000 / 2 / I2C_SPD; I2C1->CR1 = (1 << I2C_CR1_PE);
// start con_str("[START]"); I2C1->CR1 |= (1 << I2C_CR1_START); while((I2C1->SR1 & (1 << I2C_SR1_SB)) == 0);
// devsel con_str("[DEVSEL]"); I2C1->SR1; I2C1->DR = 0xA0; while((I2C1->SR1 & (1 << I2C_SR1_ADDR)) == 0); I2C1->SR1; I2C1->SR2; con_str("[DOK]");
// wr-addrh while((I2C1->SR1 & (1 << I2C_SR1_TXE)) == 0); con_str("[WR "); con_byte(0x00); con_str("]"); I2C1->DR = 0x00;
// wr-addrl while((I2C1->SR1 & (1 << I2C_SR1_TXE)) == 0); con_str("[WR "); con_byte(0x00); con_str("]"); I2C1->DR = 0x00;
// r-start con_str("[R-START]"); I2C1->CR1 |= (1 << I2C_CR1_START); while((I2C1->SR1 & (1 << I2C_SR1_SB)) == 0);
// devsel con_str("[DEVSEL]"); I2C1->SR1; I2C1->DR = 0xA1; while((I2C1->SR1 & (1 << I2C_SR1_ADDR)) == 0); I2C1->CR1 |= (1 << I2C_CR1_ACK); I2C1->SR1; I2C1->SR2; con_str("[DOK]");
// rd while((I2C1->SR1 & (1 << I2C_SR1_RXNE)) == 0); I2C1->CR1 &= ~(1 << I2C_CR1_ACK); con_str("[RD "); con_byte(I2C1->DR); con_str("]");
// rd while((I2C1->SR1 & (1 << I2C_SR1_RXNE)) == 0); con_str("[RD "); con_byte(I2C1->DR); con_str("]");
// stop while((I2C1->SR1 & (1 << I2C_SR1_TXE)) == 0); con_str("[STOP]"); I2C1->CR1 |= (1 << I2C_CR1_STOP); Код // Alternate Function pin connection for I2C1, SPI2 ((GPIO_TypeDef *)(GPIOB_BASE))->AFR[1] |= ((5 << ((13 - 8) << 2)) | // SPI2 SCK, AF5 (5 << ((15 - 8) << 2)) | // SPI2 MOSI, AF5 (5 << ((8 - 8) << 2)) | // I2C1 SCL, AF4 (5 << ((9 - 8) << 2)) ); // I2C1 SDA, AF4 Для I2C AF=4, а не 5!
Эскизы прикрепленных изображений
|
|
|
|
|
Dec 6 2012, 08:11
|
Частый гость
 
Группа: Участник
Сообщений: 90
Регистрация: 7-10-11
Из: Москва
Пользователь №: 67 593

|
Дабы не плодить новой темы... Никак не могу запустить модуль i2с1 на 417-м стм. Проц lqfp 176, модуль висит на GPIOB 8 и 9. Дебагером дохожу до старт бита, на этом всё заканчивается. при попытке что-то записать в DR уходит в несознанку и выкидывает флаг BUSY. Осциллом кажет что SDA прижата, на SCL прижимает и всё... Код: Код #include "stm32f4xx.h" #include "stdio.h" #define MPU_6050_address_write 0xD0 #define MPU_6050_address_read 0xD1 //----------------------------------------------------------------------------------------------- void Delay (unsigned int time) { unsigned int temp; for (temp=time;temp>0;temp--); } void Init_GPIOB (void) { RCC->AHB1ENR|=RCC_AHB1ENR_GPIOBEN; // подаем клок на порт В /* . . Insert GPIOB code here . . */ } void Init_I2C1 (void) { GPIOB->MODER|=(GPIO_MODER_MODER8_1|GPIO_MODER_MODER9_1); // PB8, PB9 as I2C1 GPIOB->OTYPER|=(GPIO_OTYPER_OT_8|GPIO_OTYPER_OT_9); GPIOB->OSPEEDR|=(GPIO_OSPEEDER_OSPEEDR8_1|GPIO_OSPEEDER_OSPEEDR9_1); // 50 MHz GPIOB clock speed GPIOB->AFR[1]|=4; //PB8 SCL GPIOB->AFR[1]|=(4<<4); //PB9 SDA RCC->APB1ENR|=RCC_APB1ENR_I2C1EN; //Enable clock RCC->APB1RSTR|=RCC_APB1RSTR_I2C1RST; //reset I2C1 RCC->APB1RSTR&=~(RCC_APB1RSTR_I2C1RST); //set I2C1 I2C1->CR1&=~I2C_CR1_PE;//disable all I2C peripherial I2C1->CR2|=0x002A; //Fclk1 = 42 MHz I2C1->CCR|=(1<<15)|(1<<14);//fast mode, 400 KHz duty cycle I2C1->CCR|=0x05; //Tscl = 2970 ns ~ < 400 KHz I2C1->TRISE|=0x0E; //Rise time 300ns I2C1->CR1|=I2C_CR1_PE;//enable all I2C peripherial } /*-------------------------------------------------------------------------------*/ void I2C1_Start (void) { I2C1->CR1|=I2C_CR1_START; } //-------------------------------------------------------------------------------- void MPU6050_Init (unsigned char *data) { I2C1_Start(); while (!(I2C1->SR1&I2C_SR1_SB)); // ждём установки старт бита.. (void) I2C1->SR1; // читаем статус регистер I2C1->DR=MPU_6050_address_write; // на этом всё умирает!!! while(!(I2C1->SR1 & I2C_SR1_ADDR)) {}; (void) I2C1->SR1; (void) I2C1->SR2; I2C1->DR=0x75; while (!(I2C1->SR1&I2C_SR1_BTF)) {}; I2C1_Start(); while (!(I2C1->SR1&I2C_SR1_SB)); (void) I2C1->SR1; I2C1->DR=MPU_6050_address_read; (void) I2C1->SR1; (void) I2C1->SR2; while (!(I2C1->SR1&I2C_SR1_RXNE)); *data=I2C1->DR; I2C1->CR1|=I2C_CR1_STOP; } //-------------------------------------------------------------------------------- void Send_Data_I2C (unsigned char data) { } int main (void) { unsigned char mpu_reg; SystemInit(); // стандартная функция для СТМ32, клок ядра 168 МГц, 42 МГц клок АРВ1 Init_GPIOB(); Init_I2C1(); MPU6050_Init (&mpu_reg); //I2C1_Start(); while (1); return 0; } На шине висит модуль MPU-6050 (3D motion processor). Не думаю что проблема в неём, т.к. он аппаратно залочен на слейв. Какие догдаки: возможно намудрил в регистрах CCR и TRISE, но с другой стороны тогда всё равно хоть что-нибудь было бы на линии данных. Такое ощущение что модуль после старт бита подвисает. Вобщем у кого есть опыт, прошу помощи зала. Если у кого-то есть рабочий код I2C мастер на 400 КГц, выложите пжлст, сам тогда буду копаться-анализировать свои баги. З.Ы. Эррату читал, там по моему вопросу ничего нету.. Код недописан, на мусор не обращайте внимание. UPDATE:Отключил гиру от проца, прошёлся осциллом (линии подтянуты к vcc +3.3v), при генерации старта проц опускает обе линии к земле вместо только SDA. я в полном замешательстве. Это что же получается, глюк уже аппаратный?
Сообщение отредактировал NaughtyFreak - Dec 6 2012, 19:36
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|