Created
November 25, 2019 20:44
-
-
Save Chryseus/9dbd4a5a30bb5f81c153a3265497a125 to your computer and use it in GitHub Desktop.
ADF4351 on STM32F103C8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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