mirror of
https://github.com/ttrftech/NanoVNA.git
synced 2025-12-06 03:31:59 +01:00
110 lines
2.8 KiB
C
110 lines
2.8 KiB
C
|
|
#include "hal.h"
|
||
|
|
#include "si5351.h"
|
||
|
|
|
||
|
|
#define SI5351_I2C_ADDR (0x60<<1)
|
||
|
|
|
||
|
|
static void
|
||
|
|
rcc_gpio_init(void)
|
||
|
|
{
|
||
|
|
// Reset AHB,APB1,APB2
|
||
|
|
RCC->AHBRSTR |= 0xffffffff;
|
||
|
|
RCC->AHBRSTR = 0;
|
||
|
|
RCC->APB1RSTR |= 0xffffffff;
|
||
|
|
RCC->APB1RSTR = 0;
|
||
|
|
RCC->APB2RSTR |= 0xffffffff;
|
||
|
|
RCC->APB2RSTR = 0;
|
||
|
|
|
||
|
|
RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_I2C1EN;
|
||
|
|
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
|
||
|
|
RCC->CFGR3 |= RCC_CFGR3_I2C1SW_HSI;
|
||
|
|
|
||
|
|
// STM32F072
|
||
|
|
GPIOB->AFRH = 0x55550011; // PB8,PB9 Alternate Function 1
|
||
|
|
// STM32F303
|
||
|
|
//GPIOB->AFRH = 0x55550044; // PB8,PB9 Alternate Function 4
|
||
|
|
GPIOB->OTYPER |= 0x0300; // PB8,PB9 Open drain
|
||
|
|
GPIOB->MODER |= 0x000A0000;//
|
||
|
|
GPIOB->OSPEEDR |= 0x00050000;//
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
i2c_init(I2C_TypeDef* i2c)
|
||
|
|
{
|
||
|
|
// Disable the I2Cx peripheral
|
||
|
|
i2c->CR1 &= ~I2C_CR1_PE;
|
||
|
|
while (i2c->CR1 & I2C_CR1_PE);
|
||
|
|
|
||
|
|
// 100kHz @ 8MHz
|
||
|
|
i2c->TIMINGR = 0x10420F13;
|
||
|
|
|
||
|
|
// Use 7-bit addresses
|
||
|
|
i2c->CR2 &=~ I2C_CR2_ADD10;
|
||
|
|
|
||
|
|
// Enable the analog filter
|
||
|
|
i2c->CR1 &= ~I2C_CR1_ANFOFF;
|
||
|
|
|
||
|
|
// Disable NOSTRETCH
|
||
|
|
i2c->CR1 |= I2C_CR1_NOSTRETCH;
|
||
|
|
|
||
|
|
// Enable I2Cx peripheral clock.
|
||
|
|
// Select APB1 as clock source
|
||
|
|
if (i2c == I2C1) {
|
||
|
|
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
|
||
|
|
} else if (i2c == I2C2) {
|
||
|
|
RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Enable the I2Cx peripheral
|
||
|
|
i2c->CR1 |= I2C_CR1_PE;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
i2cSendByte(I2C_TypeDef* i2c, uint8_t addr, const uint8_t *buf, uint8_t len)
|
||
|
|
{
|
||
|
|
i2c->CR2 = (I2C_CR2_SADD & addr) // Set the slave address
|
||
|
|
| (I2C_CR2_NBYTES & (len << 16)) // Send one byte
|
||
|
|
| I2C_CR2_START // Generate start condition
|
||
|
|
| I2C_CR2_AUTOEND; // Generate stop condition after sent
|
||
|
|
|
||
|
|
// Send the data
|
||
|
|
while (len-- > 0) {
|
||
|
|
while (!(i2c->ISR & I2C_ISR_TXIS));
|
||
|
|
i2c->TXDR = (I2C_TXDR_TXDATA & *buf++);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// register addr, length, data, ...
|
||
|
|
const uint8_t si5351_configs_low[] = {
|
||
|
|
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff,
|
||
|
|
4, SI5351_REG_16_CLK0_CONTROL, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN,
|
||
|
|
2, SI5351_REG_183_CRYSTAL_LOAD, SI5351_CRYSTAL_LOAD_8PF,
|
||
|
|
// setup PLL (26MHz * 32 = 832MHz : 32/2-2=14)
|
||
|
|
9, SI5351_REG_26_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
|
||
|
|
// RESET PLL
|
||
|
|
2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B,
|
||
|
|
// setup multisynth (832MHz/8MHz=104,104/2-2=50)
|
||
|
|
9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0,
|
||
|
|
2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE,
|
||
|
|
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0,
|
||
|
|
0 // sentinel
|
||
|
|
};
|
||
|
|
|
||
|
|
void
|
||
|
|
si5351_init_bulk(void)
|
||
|
|
{
|
||
|
|
const uint8_t *p = si5351_configs_low;
|
||
|
|
while (*p) {
|
||
|
|
uint8_t len = *p++;
|
||
|
|
i2cSendByte(I2C1, SI5351_I2C_ADDR, p, len);
|
||
|
|
p += len;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
si5351_setup(void)
|
||
|
|
{
|
||
|
|
rcc_gpio_init();
|
||
|
|
i2c_init(I2C1);
|
||
|
|
si5351_init_bulk();
|
||
|
|
}
|