Skip to content

Instantly share code, notes, and snippets.

@Chryseus
Created November 25, 2019 20:44
Show Gist options
  • Save Chryseus/9dbd4a5a30bb5f81c153a3265497a125 to your computer and use it in GitHub Desktop.
Save Chryseus/9dbd4a5a30bb5f81c153a3265497a125 to your computer and use it in GitHub Desktop.
ADF4351 on STM32F103C8
#include "main.h"
#include "dwt_delay.h"
#include <stdlib.h>
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
typedef struct adf4351
{
uint16_t FRAC; // Fractional frequency component
uint16_t INT; // Integral frequency component
uint16_t MOD:12; // Modulo frequency component
uint16_t PHASE:12; // Phase value
uint8_t PRESCALER:1; // 0 = 4/5, 1 = 8/9
uint8_t PHASE_ADJ:1; // Phase adjustment enable
uint8_t COUNTER_RESET:1;
uint8_t CP_THREE_STATE:1;
uint8_t POWER_DOWN:1;
uint8_t PD_POLARITY:1; // 0 = Negative, 1 = Positive
uint8_t LOCK_DETECT_PRECISION:1; // 0 = 10ns, 1 = 6ns
uint8_t LOCK_DETECT_FUNCTION:1; // 0 = 40 cycles, 1 = 5 cycles
uint8_t CHARGE_PUMP_I:4; // See page 16 of datasheet
uint8_t DOUBLE_BUFFER:1;
uint16_t R_COUNTER:10; // 1-1023
uint8_t REF_DIV2:1; // Reference clock divide by 2
uint8_t REF_DOUBLER:1; // Reference clock doubler
uint8_t MUXOUT:3; // See page 16 of datasheet
uint8_t LNLS_MODES:2; // 0 = low noise, 3 = low spur
uint16_t CLOCK_DIV:12; // 0-4095
uint8_t CLOCK_DIV_MODE:2; // 0 = off, 1 = fast lock enable, 2 = resync enable
uint8_t CYCLE_SLIP_REDUCTION:1;
uint8_t CHARGE_CANCEL:1;
uint8_t ANTIBACKLASH_PULSE_WIDTH:1; // 0 = 6ns (FRAC-N), 1 = 3ns (INT_N)
uint8_t BAND_SELECT_CLK_MODE:1; // 0 = low, 1 = high
uint8_t OUTPUT_POWER:2; // See page 17 of datasheet
uint8_t RF_OUTPUT_ENABLE:1;
uint8_t AUX_OUTPUT_POWER:2; // See page 17 of datasheet
uint8_t AUX_OUTPUT_ENABLE:1;
uint8_t AUX_OUTPUT_SELECT:1; // 0 = Divided Output. 1 = Fundamental
uint8_t MUTE_LOCK_DETECT:1;
uint8_t VCO_POWER_DOWN:1;
uint8_t BAND_SELECT_CLOCK_DIV; // 1-255
uint8_t RF_DIV_SELECT:3; // See page 17 of datasheet
uint8_t FEEDBACK_SELECT:1; // 0 = Divided, 1 = Fundamental
uint8_t LOCK_DET_PIN_MODE:2 // 0 = Low, 1 = Digital Lock Detect, 2 = Low, 3 = High
}adf4351;
float REF_CLK = 25e6;
uint32_t r0 = 0;
uint32_t r1 = 0;
uint32_t r2 = 0;
uint32_t r3 = 0;
uint32_t r4 = 0;
uint32_t r5 = 0;
void send(uint32_t delay)
{
uint32_t delay_packet = 100;
//uint32_t test = 1431655765;
uint32_t mask = 2147483648;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 0); // LE
for (int i = 0; i < 32; i++)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, (r5 & mask) ? 1 : 0); // Data
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 1); // CLK
DWT_Delay(delay);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 0); // CLK
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, 0); // Data
DWT_Delay(delay);
mask >>= 1;
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 1); // LE
DWT_Delay(delay_packet);
mask = 2147483648;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 0); // LE
for (int i = 0; i < 32; i++)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, (r4 & mask) ? 1 : 0); // Data
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 1); // CLK
DWT_Delay(delay);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 0); // CLK
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, 0); // Data
DWT_Delay(delay);
mask >>= 1;
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 1); // LE
DWT_Delay(delay_packet);
mask = 2147483648;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 0); // LE
for (int i = 0; i < 32; i++)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, (r3 & mask) ? 1 : 0); // Data
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 1); // CLK
DWT_Delay(delay);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 0); // CLK
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, 0); // Data
DWT_Delay(delay);
mask >>= 1;
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 1); // LE
DWT_Delay(delay_packet);
mask = 2147483648;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 0); // LE
for (int i = 0; i < 32; i++)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, (r2 & mask) ? 1 : 0); // Data
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 1); // CLK
DWT_Delay(delay);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 0); // CLK
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, 0); // Data
DWT_Delay(delay);
mask >>= 1;
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 1); // LE
DWT_Delay(delay_packet);
mask = 2147483648;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 0); // LE
for (int i = 0; i < 32; i++)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, (r1 & mask) ? 1 : 0); // Data
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 1); // CLK
DWT_Delay(delay);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 0); // CLK
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, 0); // Data
DWT_Delay(delay);
mask >>= 1;
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 1); // LE
DWT_Delay(delay_packet);
mask = 2147483648;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 0); // LE
for (int i = 0; i < 32; i++)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, (r0 & mask) ? 1 : 0); // Data
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 1); // CLK
DWT_Delay(delay);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, 0); // CLK
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, 0); // Data
DWT_Delay(delay);
mask >>= 1;
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, 1); // LE
}
void calculate_frequency(adf4351 *adf4351, double MCLK, double target)
{
double PFD = MCLK * ((1+adf4351->REF_DOUBLER) / (adf4351->R_COUNTER * (1 + adf4351->REF_DIV2)));
/*if (PFD % target == 0)
{
adf4351->INT = target / PFD;
}*/
double RFOUT = PFD * (adf4351->INT + (adf4351->FRAC/adf4351->MOD));
}
void init(adf4351 *adf4351)
{
adf4351->INT = 12900;
adf4351->FRAC = 0;
adf4351->MOD = 1;
adf4351->PHASE = 1;
adf4351->PRESCALER = 1;
adf4351->PHASE_ADJ = 0;
adf4351->COUNTER_RESET = 0;
adf4351->CP_THREE_STATE = 0;
adf4351->POWER_DOWN = 0;
adf4351->PD_POLARITY = 1;
adf4351->LOCK_DETECT_FUNCTION = 0;
adf4351->LOCK_DETECT_PRECISION = 0;
adf4351->CHARGE_PUMP_I = 7; // 2.5
adf4351->DOUBLE_BUFFER = 0;
adf4351->R_COUNTER = 100;
adf4351->REF_DIV2 = 0;
adf4351->REF_DOUBLER = 0;
adf4351->MUXOUT = 0;
adf4351->LNLS_MODES = 3; // low spur
adf4351->CLOCK_DIV = 150;
adf4351->CLOCK_DIV_MODE = 0; // off
adf4351->CYCLE_SLIP_REDUCTION = 0;
adf4351->CHARGE_CANCEL = 0;
adf4351->ANTIBACKLASH_PULSE_WIDTH = 0;
adf4351->BAND_SELECT_CLK_MODE = 0;
adf4351->OUTPUT_POWER = 3 ;// -4 dBm
adf4351->RF_OUTPUT_ENABLE = 1;
adf4351->AUX_OUTPUT_POWER = 0; // -4 dBm
adf4351->AUX_OUTPUT_ENABLE = 0;
adf4351->AUX_OUTPUT_SELECT = 0;
adf4351->MUTE_LOCK_DETECT = 0;
adf4351->VCO_POWER_DOWN = 0;
adf4351->BAND_SELECT_CLOCK_DIV = 200;
adf4351->RF_DIV_SELECT = 5; // 32
adf4351->FEEDBACK_SELECT = 1;
adf4351->LOCK_DET_PIN_MODE = 1; // Digital lock detect
}
void update_registers(adf4351 *adf4351)
{
r0 = 0;
r1 = 0;
r2 = 0;
r3 = 0;
r4 = 0;
r5 = 0;
r0 |= adf4351->INT << 15;
r0 |= adf4351->FRAC << 3;
r1 = 1;
r1 |= adf4351->MOD << 3;
r1 |= adf4351->PHASE << 15;
r1 |= adf4351->PRESCALER << 27;
r1 |= adf4351->PHASE_ADJ << 28;
r2 = 2;
r2 |= adf4351->COUNTER_RESET << 3;
r2 |= adf4351->CP_THREE_STATE << 4;
r2 |= adf4351->POWER_DOWN << 5;
r2 |= adf4351->PD_POLARITY << 6;
r2 |= adf4351->LOCK_DETECT_PRECISION << 7;
r2 |= adf4351->LOCK_DETECT_FUNCTION << 8;
r2 |= adf4351->CHARGE_PUMP_I << 9;
r2 |= adf4351->DOUBLE_BUFFER << 13;
r2 |= adf4351->R_COUNTER << 14;
r2 |= adf4351->REF_DIV2 << 24;
r2 |= adf4351->REF_DOUBLER << 25;
r2 |= adf4351->MUXOUT << 26;
r2 |= adf4351->LNLS_MODES << 29;
r3 = 3;
r3 |= adf4351->CLOCK_DIV << 3;
r3 |= adf4351->CLOCK_DIV_MODE << 15;
r3 |= adf4351->CYCLE_SLIP_REDUCTION << 18;
r3 |= adf4351->CHARGE_CANCEL << 21;
r3 |= adf4351->ANTIBACKLASH_PULSE_WIDTH << 22;
r3 |= adf4351->BAND_SELECT_CLK_MODE << 23;
r4 = 4;
r4 |= adf4351->OUTPUT_POWER << 3;
r4 |= adf4351->RF_OUTPUT_ENABLE << 5;
r4 |= adf4351->AUX_OUTPUT_POWER << 6;
r4 |= adf4351->AUX_OUTPUT_ENABLE << 8;
r4 |= adf4351->AUX_OUTPUT_SELECT << 9;
r4 |= adf4351->MUTE_LOCK_DETECT << 10;
r4 |= adf4351->VCO_POWER_DOWN << 11;
r4 |= adf4351->BAND_SELECT_CLOCK_DIV << 12;
r4 |= adf4351->RF_DIV_SELECT << 20;
r4 |= adf4351->FEEDBACK_SELECT << 23;
r5 = 5;
r5 |= adf4351->LOCK_DET_PIN_MODE << 22;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
DWT_Init();
adf4351 pll;
init(&pll);
while (1)
{
update_registers(&pll);
HAL_Delay(3000);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 1);
send(50);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0);
}
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, CLK_Pin|DATA_Pin|CE_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : LED_Pin */
GPIO_InitStruct.Pin = LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : CLK_Pin DATA_Pin CE_Pin */
GPIO_InitStruct.Pin = CLK_Pin|DATA_Pin|CE_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment