генерирую клоки, системный 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;
}
{
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
// 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 должен быть проставлен, но он по прежнему ноль.
что там может быть еще не так?