AD9959-STM32F1驱动程序
AD9959-STM32F1驱动程序
适用于STM32F103系列的AD9959的驱动程序,是用github上的代码改写的。
1. AD9959.C
#include "ad9959.h"
uint8_t FR2_DATA[2] = {0x20, 0x00};//default Value = 0x0000
uint8_t CFR_DATA[3] = {0x00, 0x03, 0x02};//default Value = 0x000302
uint8_t CPOW0_DATA[2] = {0x00, 0x00};//default Value = 0x0000 @ = POW/2^14*360
uint8_t LSRR_DATA[2] = {0x00, 0x00};//default Value = 0x----
uint8_t RDW_DATA[4] = {0x00, 0x00, 0x00, 0x00};//default Value = 0x--------
uint8_t FDW_DATA[4] = {0x00, 0x00, 0x00, 0x00};//default Value = 0x--------
/**
* @brief AD9959略微延时
* */
static void ad9959_delay(uint32_t length) {
length = length * 12;
while (length--);
}
/**
* @brief AD9959初始化
* */
void ad9959_init(void) {
uint8_t FR1_DATA[3] = {0xD0, 0x00,
0x00};//20倍频 Charge pump control = 75uA FR1<23> -- VCO gain control =0时 system clock below 160 MHz;
ad9959_io_init();
ad9959_reset();
ad9959_write_data(AD9959_REG_FR1, 3, FR1_DATA, 1);//写功能寄存器1
ad9959_write_data(AD9959_REG_FR2, 2, FR2_DATA, 1);
//写入初始频率
ad9959_write_frequency(AD9959_CHANNEL_0, 1000);
ad9959_write_frequency(AD9959_CHANNEL_1, 1000);
ad9959_write_frequency(AD9959_CHANNEL_2, 1000);
ad9959_write_frequency(AD9959_CHANNEL_3, 1000);
ad9959_write_phase(AD9959_CHANNEL_0, 0);
ad9959_write_phase(AD9959_CHANNEL_1, 0);
ad9959_write_phase(AD9959_CHANNEL_2, 0);
ad9959_write_phase(AD9959_CHANNEL_3, 0);
ad9959_write_amplitude(AD9959_CHANNEL_0, 0xFF);
ad9959_write_amplitude(AD9959_CHANNEL_1, 0xFF);
ad9959_write_amplitude(AD9959_CHANNEL_2, 0xFF);
ad9959_write_amplitude(AD9959_CHANNEL_3, 0xFF);
}
/**
* @brief AD9959复位
* */
void ad9959_reset(void) {
AD9959_RESET_0;
ad9959_delay(1);
AD9959_RESET_1;
ad9959_delay(30);
AD9959_RESET_0;
}
/**
* @brief AD9959IO口初始化
* */
void ad9959_io_init(void) {
AD9959_PDC_0;
AD9959_CS_1;
AD9959_SCLK_0;
AD9959_UPDATE_0;
AD9959_PS0_0;
AD9959_PS1_0;
AD9959_PS2_0;
AD9959_PS3_0;
AD9959_SDIO0_0;
AD9959_SDIO1_0;
AD9959_SDIO2_0;
AD9959_SDIO3_0;
}
/**
* @brief AD9959更新IO寄存器
* */
void ad9959_io_update(void) {
AD9959_UPDATE_0;
ad9959_delay(2);
AD9959_UPDATE_1;
ad9959_delay(4);
AD9959_UPDATE_0;
}
/**
* @brief 通过SPI向AD9959写数据
* @param register_address 寄存器地址
* @param number_of_registers 所含字节数
* @param register_data 数据起始地址
* @param update 是否更新IO寄存器
* */
void ad9959_write_data(AD9959_REG_ADDR register_address, uint8_t number_of_registers, const uint8_t *register_data,
bool update) {
uint8_t ControlValue = 0;
uint8_t ValueToWrite = 0;
uint8_t RegisterIndex = 0;
uint8_t i = 0;
assert_param(IS_AD9959_REG_ADDR(register_address));
ControlValue = register_address;
//写入地址
AD9959_SCLK_0;
AD9959_CS_0;
for (i = 0; i < 8; i++) {
AD9959_SCLK_0;
if (0x80 == (ControlValue & 0x80))
AD9959_SDIO0_1;
else
AD9959_SDIO0_0;
AD9959_SCLK_1;
ControlValue <<= 1;
}
AD9959_SCLK_0;
//写入数据
for (RegisterIndex = 0; RegisterIndex < number_of_registers; RegisterIndex++) {
ValueToWrite = register_data[RegisterIndex];
for (i = 0; i < 8; i++) {
AD9959_SCLK_0;
if (0x80 == (ValueToWrite & 0x80))
AD9959_SDIO0_1;
else
AD9959_SDIO0_0;
AD9959_SCLK_1;
ValueToWrite <<= 1;
}
AD9959_SCLK_0;
}
if (update) ad9959_io_update();
AD9959_CS_1;
}
/**
* @brief 设置通道输出相位
* @param channel 输出通道
* @param phase 输出相位 14bit 输出相位范围:0~16383(对应角度:0°~360°)
* */
void ad9959_write_phase(AD9959_CHANNEL channel, uint16_t phase) {
uint8_t cs_data = channel;
assert_param(IS_AD9959_CHANNEL(channel));
CPOW0_DATA[1] = (uint8_t) phase;
CPOW0_DATA[0] = (uint8_t) (phase >> 8);
ad9959_write_data(AD9959_REG_CSR, 1, &cs_data, 1);
ad9959_write_data(AD9959_REG_CPOW0, 2, CPOW0_DATA, 1);
}
/**
* @brief 设置通道输出频率
* @param channel 输出通道
* @param amplitude 输出频率 (频率范围 1 ~ 200000000Hz)
* */
void ad9959_write_frequency(AD9959_CHANNEL channel, uint32_t Freq) {
uint8_t CFTW0_DATA[4] = {0x00, 0x00, 0x00, 0x00}; //中间变量
uint32_t frequency;
uint8_t cs_data = channel;
assert_param(IS_AD9959_CHANNEL(channel));
frequency = (uint32_t) Freq * 8.589934592; //将输入频率因子分为四个字节 8.589934592=(2^32)/500000000 其中500M=25M*20(倍频数可编程)
CFTW0_DATA[3] = (uint8_t) frequency;
CFTW0_DATA[2] = (uint8_t) (frequency >> 8);
CFTW0_DATA[1] = (uint8_t) (frequency >> 16);
CFTW0_DATA[0] = (uint8_t) (frequency >> 24);
ad9959_write_data(AD9959_REG_CSR, 1, &cs_data, 1);
ad9959_write_data(AD9959_REG_CFTW0, 4, CFTW0_DATA, 1);
}
/**
* @brief 设置通道输出幅度
* @param channel 输出通道
* @param amplitude 输出幅度 10bit 输出相位范围:0~1023(对应幅度:0 ~ 530mV)
* */
void ad9959_write_amplitude(AD9959_CHANNEL channel, uint16_t amplitude) {
uint8_t ACR_DATA[3] = {0x00, 0x00, 0x00};//default Value = 0x--0000 Rest = 18.91/Iout
uint8_t cs_data = channel;
assert_param(IS_AD9959_CHANNEL(channel));
amplitude = amplitude | 0x1000;
ACR_DATA[2] = (uint8_t) amplitude;
ACR_DATA[1] = (uint8_t) (amplitude >> 8);
ad9959_write_data(AD9959_REG_CSR, 1, &cs_data, 1);
ad9959_write_data(AD9959_REG_ACR, 3, ACR_DATA, 1);
}
2.AD9959.H
AD9959\ad9959.h
#ifndef AD9959_AD9959_H
#define AD9959_AD9959_H
#include "main.h"
#include "stdbool.h"
#include "gpio.h"
#include "main.h"
#define AD9959_CS_1 HAL_GPIO_WritePin(AD9959_CS_GPIO_Port,AD9959_CS_Pin,GPIO_PIN_SET)
#define AD9959_SCLK_1 HAL_GPIO_WritePin(AD9959_SCLK_GPIO_Port,AD9959_SCLK_Pin,GPIO_PIN_SET)
#define AD9959_UPDATE_1 HAL_GPIO_WritePin(AD9959_UPDATE_GPIO_Port,AD9959_UPDATE_Pin,GPIO_PIN_SET)
#define AD9959_PS0_1 HAL_GPIO_WritePin(AD9959_PS0_GPIO_Port,AD9959_PS0_Pin,GPIO_PIN_SET)
#define AD9959_PS1_1 HAL_GPIO_WritePin(AD9959_PS1_GPIO_Port,AD9959_PS1_Pin,GPIO_PIN_SET)
#define AD9959_PS2_1 HAL_GPIO_WritePin(AD9959_PS2_GPIO_Port,AD9959_PS2_Pin,GPIO_PIN_SET)
#define AD9959_PS3_1 HAL_GPIO_WritePin(AD9959_PS3_GPIO_Port,AD9959_PS3_Pin,GPIO_PIN_SET)
#define AD9959_SDIO0_1 HAL_GPIO_WritePin(AD9959_SDIO0_GPIO_Port,AD9959_SDIO0_Pin,GPIO_PIN_SET)
#define AD9959_SDIO1_1 HAL_GPIO_WritePin(AD9959_SDIO1_GPIO_Port,AD9959_SDIO1_Pin,GPIO_PIN_SET)
#define AD9959_SDIO2_1 HAL_GPIO_WritePin(AD9959_SDIO2_GPIO_Port,AD9959_SDIO2_Pin,GPIO_PIN_SET)
#define AD9959_SDIO3_1 HAL_GPIO_WritePin(AD9959_SDIO3_GPIO_Port,AD9959_SDIO3_Pin,GPIO_PIN_SET)
#define AD9959_PDC_1 HAL_GPIO_WritePin(AD9959_PDC_GPIO_Port,AD9959_PDC_Pin,GPIO_PIN_SET)
#define AD9959_RESET_1 HAL_GPIO_WritePin(AD9959_RESET_GPIO_Port,AD9959_RESET_Pin,GPIO_PIN_SET)
#define AD9959_CS_0 HAL_GPIO_WritePin(AD9959_CS_GPIO_Port,AD9959_CS_Pin,GPIO_PIN_RESET)
#define AD9959_SCLK_0 HAL_GPIO_WritePin(AD9959_SCLK_GPIO_Port,AD9959_SCLK_Pin,GPIO_PIN_RESET)
#define AD9959_UPDATE_0 HAL_GPIO_WritePin(AD9959_UPDATE_GPIO_Port,AD9959_UPDATE_Pin,GPIO_PIN_RESET)
#define AD9959_PS0_0 HAL_GPIO_WritePin(AD9959_PS0_GPIO_Port,AD9959_PS0_Pin,GPIO_PIN_RESET)
#define AD9959_PS1_0 HAL_GPIO_WritePin(AD9959_PS1_GPIO_Port,AD9959_PS1_Pin,GPIO_PIN_RESET)
#define AD9959_PS2_0 HAL_GPIO_WritePin(AD9959_PS2_GPIO_Port,AD9959_PS2_Pin,GPIO_PIN_RESET)
#define AD9959_PS3_0 HAL_GPIO_WritePin(AD9959_PS3_GPIO_Port,AD9959_PS3_Pin,GPIO_PIN_RESET)
#define AD9959_SDIO0_0 HAL_GPIO_WritePin(AD9959_SDIO0_GPIO_Port,AD9959_SDIO0_Pin,GPIO_PIN_RESET)
#define AD9959_SDIO1_0 HAL_GPIO_WritePin(AD9959_SDIO1_GPIO_Port,AD9959_SDIO1_Pin,GPIO_PIN_RESET)
#define AD9959_SDIO2_0 HAL_GPIO_WritePin(AD9959_SDIO2_GPIO_Port,AD9959_SDIO2_Pin,GPIO_PIN_RESET)
#define AD9959_SDIO3_0 HAL_GPIO_WritePin(AD9959_SDIO3_GPIO_Port,AD9959_SDIO3_Pin,GPIO_PIN_RESET)
#define AD9959_PDC_0 HAL_GPIO_WritePin(AD9959_PDC_GPIO_Port,AD9959_PDC_Pin,GPIO_PIN_RESET)
#define AD9959_RESET_0 HAL_GPIO_WritePin(AD9959_RESET_GPIO_Port,AD9959_RESET_Pin,GPIO_PIN_RESET)
typedef enum {
AD9959_CHANNEL_0 = 0x10U,
AD9959_CHANNEL_1 = 0x20U,
AD9959_CHANNEL_2 = 0x40U,
AD9959_CHANNEL_3 = 0x80U,
} AD9959_CHANNEL;
typedef enum {
AD9959_REG_CSR = 0x00U, //CSR 通道选择寄存器
AD9959_REG_FR1 = 0x01U, //FR1 功能寄存器1
AD9959_REG_FR2 = 0x02U, //FR2 功能寄存器2
AD9959_REG_CFR = 0x03U, //CFR 通道功能寄存器
AD9959_REG_CFTW0 = 0x04U, //CTW0 通道频率转换字寄存器
AD9959_REG_CPOW0 = 0x05U, //CPW0 通道相位转换字寄存器
AD9959_REG_ACR = 0x06U, //ACR 幅度控制寄存器
AD9959_REG_LSRR = 0x07U, //LSR 通道线性扫描寄存器
AD9959_REG_RDW = 0x08U, //RDW 通道线性向上扫描寄存器
AD9959_REG_FDW = 0x09U, //FDW 通道线性向下扫描寄存器
} AD9959_REG_ADDR;
#define IS_AD9959_REG_ADDR(REG_ADDR) (((REG_ADDR) == AD9959_REG_CSR ) || \
((REG_ADDR) == AD9959_REG_FR1 ) || \
((REG_ADDR) == AD9959_REG_FR2 ) || \
((REG_ADDR) == AD9959_REG_CFR ) || \
((REG_ADDR) == AD9959_REG_CFTW0) || \
((REG_ADDR) == AD9959_REG_CPOW0) || \
((REG_ADDR) == AD9959_REG_ACR ) || \
((REG_ADDR) == AD9959_REG_LSRR ) || \
((REG_ADDR) == AD9959_REG_RDW ) || \
((REG_ADDR) == AD9959_REG_FDW ))
#define IS_AD9959_CHANNEL(CHANNEL) (((CHANNEL) == AD9959_CHANNEL_0 ) || \
((CHANNEL) == AD9959_CHANNEL_1 ) || \
((CHANNEL) == AD9959_CHANNEL_2 ) || \
((CHANNEL) == AD9959_CHANNEL_3 ))
void ad9959_init(void);
void ad9959_reset(void);
void ad9959_io_init(void);
void ad9959_io_update(void);
void ad9959_write_data(AD9959_REG_ADDR register_address, uint8_t number_of_registers, const uint8_t *register_data, bool update);
void ad9959_write_phase(AD9959_CHANNEL channel, uint16_t phase);
void ad9959_write_frequency(AD9959_CHANNEL channel, uint32_t frequency);
void ad9959_write_amplitude(AD9959_CHANNEL channel, uint16_t amplitude);
#endif //AD9959_AD9959_H
3. CUBEMX的引脚配置图
更新一下main.c代码,我把代码进行了一些删减,原本是由LCD显示,按键扫描等等功能,我基本上都去掉了,增加一下可读性,方便只想看AD9959驱动函数的朋友。
/* USER CODE BEGIN Header */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ad9959.h"
#include "lcd_init.h"
#include "lcd.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
int freq = 2000000;
int SWEEP = 0;
int t = 0;
int flag;
int flag_t;
int flag_s;
int tx = 0;
int NUM_T[4];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void delay_x(void);
void for_delay_us(uint32_t nus);
void NUM_ENcode(int num);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int KEY_scan(void);
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
ad9959_init();
ad9959_write_amplitude(AD9959_CHANNEL_0,1023);
ad9959_write_amplitude(AD9959_CHANNEL_1,1023);
ad9959_write_amplitude(AD9959_CHANNEL_2,1023);
ad9959_write_amplitude(AD9959_CHANNEL_3,1023);
ad9959_write_frequency(AD9959_CHANNEL_3,20000000);
ad9959_write_frequency(AD9959_CHANNEL_0,20000000);
ad9959_write_frequency(AD9959_CHANNEL_1,20000000);
LCD_Init();
LCD_Fill(0,0,320,240,WHITE);
LCD_ShowString(20,15,"Plase input: ",BLACK,WHITE,16,0);
LCD_ShowString(20,150,"Carrier franquency: ",BLACK,WHITE,16,0);
LCD_ShowString(185,140,"20M ",BLACK,WHITE,24,0);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
ad9959_write_frequency(AD9959_CHANNEL_3,20000000);
ad9959_write_frequency(AD9959_CHANNEL_0,40000000);
ad9959_write_frequency(AD9959_CHANNEL_1,20000000);
HAL_Delay(1000);
ad9959_write_frequency(AD9959_CHANNEL_3,25000000);
ad9959_write_frequency(AD9959_CHANNEL_0,25000000);
ad9959_write_frequency(AD9959_CHANNEL_1,25000000);
HAL_Delay(1000);
ad9959_write_frequency(AD9959_CHANNEL_3,275000000);
ad9959_write_frequency(AD9959_CHANNEL_0,27.5000000);
ad9959_write_frequency(AD9959_CHANNEL_1,27500000);
HAL_Delay(1000);
ad9959_write_frequency(AD9959_CHANNEL_3,30000000);
ad9959_write_frequency(AD9959_CHANNEL_0,30000000);
ad9959_write_frequency(AD9959_CHANNEL_1,30000000);
HAL_Delay(1000);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @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 */
__disable_irq();
while (1)
{
}
/* 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,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
因为这个工程原本是比较复杂的,也是作为资源分享给我的学弟学妹们,为了方便我没有对原工程做改动,不过关于AD9959的驱动函数的调用以及初始化在工程里面都有。地址如下:
链接:https://pan.baidu.com/s/1DFTN3vquNmw2yZcuC_N3IQ?pwd=5zi5
提取码:5zi5
原github项目地址连接:
https://github.com/d258519/AD9959-STM32