搞了好几天DAC芯片AD9910 ,找到多数资料时SPI控制内部RAM或者DDS输出波形,这里总结一下STM32 FMSC 总线输出到AD9910 ,由于AD9910 的PDCLK 为输出,这里采用PWM输入捕获模式获取 AD9910 PDCLK 的下降沿,采用捕获信号触发DMA2 ,DMA 在将数据搬移到总线上,具体代码如下:文章来源:https://www.toymoban.com/news/detail-638048.html
#include "ad9910.h"
#include <math.h>
#include "delay.h"
#include "string.h"
#include "dma.h"
volatile uint16_t ParallelTbl[25000]={0};// 最大点数
#define NOR_PSRAM_ADDRBASE (0x60000000) // BANK1 NOR_PSRAM 基地址
#define NOR_PSRAM_NE1_ADDRBASE (NOR_PSRAM_ADDRBASE+((uint32_t)0x0<<26)) //SRAM NE1 片选基地址
#define NOR_PSRAM_NE2_ADDRBASE (NOR_PSRAM_ADDRBASE+((uint32_t)0x1<<26)) //SRAM NE2 片选基地址
#define NOR_PSRAM_NE3_ADDRBASE (NOR_PSRAM_ADDRBASE+((uint32_t)0x2<<26)) //SRAM NE3 片选基地址
#define NOR_PSRAM_NE4_ADDRBASE (NOR_PSRAM_ADDRBASE+((uint32_t)0x3<<26)) //SRAM NE4 片选基地址
#define HDL_SET16BIT 1 //16bit FSMC
uint8_t cfr1[4] = {0x00, 0x40, 0x00, 0x02};//cfr1控制字
uint8_t cfr2[4] = {0x01, 0x40, 0x08, 0x00};//cfr2控制字
uint8_t cfr3[4] = {0x05, 0x0F, 0x41, 0x32};//cfr3控制字 40M输入 25倍频 VC0=101 ICP=001;
uint8_t profile[8][8] = {0x00}; //ramprofile0控制字
uint8_t drgparameter[20]={0x00};
uint32_t RAM_WAVE[1024]={0}; //RAM 波形文件
void F4xFsmcInit(void)
{
RCC->AHB1ENR|=0xF<<3; //使能PD,PE,PF,PG时钟
RCC->AHB3ENR|=1<<0; //使能FSMC时钟
GPIO_Set(GPIOD,(3<<0)|(7<<8)|(3<<14),\
GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//PD0,1,8,9,10,14,15 AF OUT
GPIO_Set(GPIOE,(0x1ff<<7),\
GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//PE7-15 AF OUT
GPIO_Set(GPIOF,(0X3F<<0)|(0XF<<12),\
GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//PF0~5,12~15
//COM DEF
GPIO_Set(GPIOD,(3<<4),\
GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//PD4~5 RD,WR
//PD7,//FSMC_NE1,/CS1
//PG9,//FSMC_NE2,/CS2
//PG10,//FSMC_NE3,/CS3
//PG12,//FSMC_NE4,/CS4
// GPIO_Set(GPIOG,PIN9,\
// GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//
GPIO_Set(GPIOD,PIN7,\
GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//
// DATA AF
GPIO_AF_Set(GPIOD,14,12); //PD14,AF12
GPIO_AF_Set(GPIOD,15,12); //PD15,AF12
GPIO_AF_Set(GPIOD,0,12); //PD0,AF12
GPIO_AF_Set(GPIOD,1,12); //PD1,AF12
GPIO_AF_Set(GPIOE,7,12); //PE7,AF12
GPIO_AF_Set(GPIOE,8,12); //PE8,AF12
GPIO_AF_Set(GPIOE,9,12); //PE9,AF12
GPIO_AF_Set(GPIOE,10,12); //PE10,AF12
GPIO_AF_Set(GPIOE,11,12); //PE11,AF12
GPIO_AF_Set(GPIOE,12,12); //PE12,AF12
GPIO_AF_Set(GPIOE,13,12); //PE13,AF12
GPIO_AF_Set(GPIOE,14,12); //PE14,AF12
GPIO_AF_Set(GPIOE,15,12); //PE15,AF12
GPIO_AF_Set(GPIOD,8,12); //PD8,AF12
GPIO_AF_Set(GPIOD,9,12); //PD9,AF12
GPIO_AF_Set(GPIOD,10,12); //PD10,AF12
GPIO_AF_Set(GPIOF,0,12); //PF0,AF12
GPIO_AF_Set(GPIOF,1,12); //PF1,AF12
GPIO_AF_Set(GPIOF,2,12); //PF2,AF12
GPIO_AF_Set(GPIOF,3,12); //PF3,AF12
GPIO_AF_Set(GPIOF,4,12); //PF4,AF12
GPIO_AF_Set(GPIOF,5,12); //PF5,AF12
GPIO_AF_Set(GPIOF,12,12); //PF12,AF12
GPIO_AF_Set(GPIOF,13,12); //PF13,AF12
GPIO_AF_Set(GPIOF,14,12); //PF14,AF12
GPIO_AF_Set(GPIOF,15,12); //PF15,AF12
GPIO_AF_Set(GPIOD,4,12); //PD4,AF12 //RD
GPIO_AF_Set(GPIOD,5,12); //PD5,AF12 //WR
GPIO_AF_Set(GPIOD,7,12); //PD7,AF12 //
//寄存器清零
//BANK 1 支持nor SRM控制
//bank1有NE1~4,每一个有一个BCR+TCR,所以总共八个寄存器。
//这里我们使用NE1 ,也就对应BTCR[0],[1]。
FMC_Bank1->BTCR[0]=0X00000000;//NE 1
FMC_Bank1->BTCR[1]=0X00000000;
FMC_Bank1E->BWTR[0]=0X00000000;
//操作BCR寄存器 使用异步模式,模式A(读写共用一个时序寄存器)
//BTCR[偶数]:BCR寄存器;BTCR[奇数]:BTR寄存器
FMC_Bank1->BTCR[0]|=1<<12;//存储器写使能
#if HDL_SET16BIT>0
FMC_Bank1->BTCR[0]|=1<<4; //存储器数据宽度为16bit
#else
FMC_Bank1->BTCR[0]&=~((uint32_t)1<<4); // 存储为8 bit
#endif
//操作BTR片选时序寄存器 (HCLK=168M, 1个HCLK=6ns
FMC_Bank1->BTCR[1]|=0xf<<8; //0000 0010: DATAST 阶段的持续时间 = 255 × HCLK 时钟周期
FMC_Bank1->BTCR[1]|=0<<4; //地址保持时间(ADDHLD)未用到
FMC_Bank1->BTCR[1]|=0<<0; //地址建立时间(ADDSET)为0个HCLK 0ns
//闪存写时序寄存器
// FMC_Bank1E->BWTR[0]=0x0FFFFFFF;//默认值
FMC_Bank1E->BWTR[0]|=(0xf<<8);//DATAST: 数据阶段的持续时间 (Data-phase duration)。
FMC_Bank1E->BWTR[0]|=0<<4;//地址保持阶段的持续时间
FMC_Bank1E->BWTR[0]|=0<<0;//地址设置阶段的持续时间
FMC_Bank1->BTCR[0]|=1<<0; //使能BANK1区域1
}
/******************************************************************************
* Init GPIO for DDS
******************************************************************************/
void DDS_GPIO_Init(void)
{
RCC->AHB1ENR|=1<<1;//使能PORTB时钟
//PB7-3
GPIO_Set(GPIOB,PIN3|PIN4|PIN5|PIN6|PIN7|PIN8|PIN9,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //
RCC->AHB1ENR|=1<<2;//使能PORTC时钟
GPIO_Set(GPIOC,PIN12|PIN13,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //
RCC->AHB1ENR|=(1<<6);//使能PORTG时钟
GPIO_Set(GPIOG,PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);
//其余引脚配置:
// 并口F[1:0] =00 ;控制幅度
// FSMC D15-D0 => AD9910 D[15:0];
// TXENABLE =1;// 接3.3v
// PDCLK => PA8 输入PWM 捕获
/*Configure GPIO pin Output Level */
DDS_OSK=0;
AD9910_PWR=0;
PROFILE2=0;
PROFILE1=0;
PROFILE0=0;
DRCTL =0;
DRHOLD=0;
UP_DAT=0;
MAS_REST=0;
CS=0;
F4xFsmcInit();
// 使用TIM1_ETR 作为并口数据输入,FSMC DATA 16bit 用作数据线
// 配置F[1:0]="00" ;用于14bit 振幅参数设置
RCC->AHB1ENR|=1<<0;//使能PORTA时钟
RCC->APB2ENR|=(1<<0);// enable TIM1
GPIO_Set(GPIOA,PIN8,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_AF_Set(GPIOA,8,1);// TIM1_CH1
TIM1->PSC =0;// =fosc /2 =84Mhz
TIM1->ARR=100;// 这里不使用,
TIM1->CR2 =(1<<3);// CCDS =1;
//DMA2-CH1 : TIM1_CH1
TIM1->DIER=(1<<9);// CC1DE CC1_DMA enable
TIM1->EGR =(1<<1);// CC1G enable
TIM1->CCMR1 =(1<<0);// IC1 <-> TI1
TIM1->CCER =(1<<1)| //下降沿触发
(1<<0);// enable capture CC1
//configure DMA
DmaConfigt dmacf;
dmacf.chx =6;
dmacf.par =(uint32_t)NOR_PSRAM_NE1_ADDRBASE;//FSMC ->NE1
dmacf.mar=(uint32_t)ParallelTbl;// MEM
dmacf.ndtr=25000;
dmacf.dir=SRAMtoPeripheral; // RAM -> FSMC
dmacf.width=width_16bit;
dmacf.burst=burst_single;//突发单次传输
dmacf.loopen=1;//循环DMA模式
MYDMA_Config(DMA2_Stream1,&dmacf);
DMA2_Stream1->FCR=0x21;//不使用FIFO
//初始化 正弦波
double Rad =0;
uint16_t temp =0;
for(int i=0;i<25000;i++){
Rad =sin((i%360) * 3.1415926/180.0)+1;
Rad*=8192;
temp =(uint16_t)Rad;
ParallelTbl[i] =temp<<2; // Get Sinus
}
}
/******************************************************************************
* Init SPI, 8bit, Master
* MODE 3, MSB,
******************************************************************************/
void DDS_SPI_Init(void)
{
SPI2_Init();
SPI2_SetSpeed(SPI_SPEED_256);
}
/*****************************************************************************************
Update - data updates from memory
*****************************************************************************************/
void DDS_UPDATE(void)
{
delay_ms(1);
UP_DAT = 0;
delay_ms(1);
UP_DAT = 1;
delay_ms(1);
UP_DAT = 0;
}
//高14位幅度控制
const unsigned char ramdata_Square[4096] = {
//方波
0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00,
0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00,
0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00,
0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00, 0xff,0xfc,0x00,0x00,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
};
//高14位幅度控制
const unsigned char ramdata_Sawtooth[4096] = {
//锯齿波
0x00,0x00,0x00,0x00, 0x03,0xfc,0x00,0x00, 0x07,0xf8,0x00,0x00, 0x0b,0xf4,0x00,0x00, 0x0f,0xf0,0x00,0x00, 0x13,0xec,0x00,0x00, 0x17,0xe8,0x00,0x00, 0x1b,0xe4,0x00,0x00,
0x1f,0xe0,0x00,0x00, 0x23,0xdc,0x00,0x00, 0x27,0xd8,0x00,0x00, 0x2b,0xd4,0x00,0x00, 0x2f,0xd0,0x00,0x00, 0x33,0xcc,0x00,0x00, 0x37,0xc8,0x00,0x00, 0x3b,0xc4,0x00,0x00,
0x3f,0xc0,0x00,0x00, 0x43,0xbc,0x00,0x00, 0x47,0xb8,0x00,0x00, 0x4b,0xb4,0x00,0x00, 0x4f,0xb0,0x00,0x00, 0x53,0xac,0x00,0x00, 0x57,0xa8,0x00,0x00, 0x5b,0xa4,0x00,0x00,
0x5f,0xa0,0x00,0x00, 0x63,0x9c,0x00,0x00, 0x67,0x98,0x00,0x00, 0x6b,0x94,0x00,0x00, 0x6f,0x90,0x00,0x00, 0x73,0x8c,0x00,0x00, 0x77,0x88,0x00,0x00, 0x7b,0x84,0x00,0x00,
0x7f,0x80,0x00,0x00, 0x83,0x7c,0x00,0x00, 0x87,0x78,0x00,0x00, 0x8b,0x74,0x00,0x00, 0x8f,0x70,0x00,0x00, 0x93,0x6c,0x00,0x00, 0x97,0x68,0x00,0x00, 0x9b,0x64,0x00,0x00,
0x9f,0x60,0x00,0x00, 0xa3,0x5c,0x00,0x00, 0xa7,0x58,0x00,0x00, 0xab,0x54,0x00,0x00, 0xaf,0x50,0x00,0x00, 0xb3,0x4c,0x00,0x00, 0xb7,0x48,0x00,0x00, 0xbb,0x44,0x00,0x00,
0xbf,0x40,0x00,0x00, 0xc3,0x3c,0x00,0x00, 0xc7,0x38,0x00,0x00, 0xcb,0x34,0x00,0x00, 0xcf,0x30,0x00,0x00, 0xd3,0x2c,0x00,0x00, 0xd7,0x28,0x00,0x00, 0xdb,0x24,0x00,0x00,
0xdf,0x20,0x00,0x00, 0xe3,0x1c,0x00,0x00, 0xe7,0x18,0x00,0x00, 0xeb,0x14,0x00,0x00, 0xef,0x10,0x00,0x00, 0xf3,0x0c,0x00,0x00, 0xf7,0x08,0x00,0x00, 0xfb,0x04,0x00,0x00,
};
void AD9110_IOInit(void)
{
DDS_SPI_Init();
DDS_GPIO_Init();
}
#define txd_8bit SPI2_ReadWriteByte
//======================ad9910初始化程序================================
void Init_ad9910(void)
{
AD9110_IOInit(); //IO初始化
AD9910_PWR = 0; //软件拉低
PROFILE2 = PROFILE1 = PROFILE0 = 0;
DRCTL = 0;
DRHOLD = 0;
MAS_REST = 1;
delay_ms(5);
MAS_REST = 0;
delay_ms(5);
Txcfr(0xf);
}
//======================发送cfr控制字====================================
void Txcfr(int8_t m)
{
uint8_t i;
if(m&1){
CS = 0;
txd_8bit(0x00); //发送CFR1控制字地址
for (i = 0; i < 4; i++)
txd_8bit(cfr1[i]);
CS = 1;
DDS_UPDATE();
}
if(m&2){
CS = 0;
txd_8bit(0x01); //发送CFR2控制字地址
for (i = 0; i < 4; i++)
txd_8bit(cfr2[i]);
CS = 1;
DDS_UPDATE();
}
if(m&4){
CS = 0;
txd_8bit(0x02); //发送CFR3控制字地址
for (i = 0; i < 4; i++)
txd_8bit(cfr3[i]);
CS = 1;
DDS_UPDATE();
}
}
//=====================================================================
void IoProfileUpdate(int8_t x)
{
PROFILE2=x&0x4?1:0;
PROFILE1=x&0x2?1:0;
PROFILE0=x&0x1?1:0;
DDS_UPDATE();
}
//ad9910发送profile0控制字程序
//int8_t profilex :8个profile
void Txprofile_cfg(int8_t profilex )
{
uint8_t m;
profilex&=0x7;//
CS=0;
txd_8bit(0x0e+profilex);
for (m=0;m<8;m++){
txd_8bit(profile[profilex][m]);
}
CS=1;
DDS_UPDATE();
IoProfileUpdate(profilex);
}
//计算频偏字、频率字和发送程序
//uint32_t Freq: 0-400000000 Hz
//uint16_t amplitude : 0-16383
//uint16_t phase :0-65535
void Freq_convert(uint32_t Freq,uint16_t amplitude,uint16_t phase)
{
int8_t si_profile =0;
uint32_t Temp = (uint32_t )Freq * 4.294967296;
//将输入频率因子分为四个字节 4.294967296=(2^32)/1000000000
profile[si_profile][7] = (uint8_t )Temp;
profile[si_profile][6] = (uint8_t )(Temp >> 8);
profile[si_profile][5] = (uint8_t )(Temp >> 16);
profile[si_profile][4] = (uint8_t )(Temp >> 24);
profile[si_profile][3] = phase&0xff;
profile[si_profile][2] = (phase>>8)&0xff;
profile[si_profile][1] = amplitude&0xff;
profile[si_profile][0] = (amplitude>>8)&0x3f;
Txprofile_cfg(si_profile);
cfr1[0] = 0x00;// disable RAM
cfr1[1] = 0x40;//反sin 滤波器on
cfr1[3] =0x02;//
cfr2[0] =0x01;// enable profile x
cfr2[1] =(1<<6);// enable SYNC_CLK out
cfr2[2] =(1<<3);// enable PDCLK out
cfr2[3] =0;// disable parallel I mode
cfr3[0] =0x05;//PLL =1Ghz
cfr3[2] =0x41;// PLL enable
Txcfr(0x7);//发送cfrx控制字
}
//计算正弦波幅值(Vpp)和发送程序
void Amp_convert(uint32_t Amp)
{
uint32_t Temp = (uint32_t )Amp * 28.4829;
//将输入幅度因子分为两个字节 25.20615385=(2^14)/650
if (Temp > 0x3fff)
Temp = 0x3fff;
Temp &= 0x3fff;
profile[1][1] = (uint8_t )Temp;
profile[1][0] = (uint8_t )(Temp >> 8);
Txprofile_cfg(1);
}
//======================ad9910发送DRG参数程序==================================
void Txdrg(void)
{
uint8_t i,m;
for(i=0;i<3;i++){
CS=0;
txd_8bit(0x0b+i);//发送数字斜坡限制地址0x0b,0x0c,0x0d
for (m=0;m<8;m++)
txd_8bit(drgparameter[m+(8*i)]);
CS=1;
DDS_UPDATE();
}
}
//=====================扫频波参数设置和发送程序===================================
void SweepFre(uint32_t SweepMinFre, uint32_t SweepMaxFre, uint32_t SweepStepFre, uint32_t SweepTime)
{
uint32_t Temp1, Temp2, ITemp3, DTemp3, ITemp4, DTemp4;
Temp1 = (uint32_t )SweepMinFre*4.294967296;
if(SweepMaxFre > 400000000)
SweepMaxFre = 400000000;
Temp2 = (uint32_t )SweepMaxFre*4.294967296;
if(SweepStepFre > 400000000)
SweepStepFre = 400000000;
ITemp3 = (uint32_t )SweepStepFre*4.294967296;
DTemp3 = ITemp3;
ITemp4 = (uint32_t )SweepTime/4; //1GHz/4, 单位:ns
if(ITemp4 > 0xffff)
ITemp4 = 0xffff;
DTemp4 = ITemp4;
//扫频上下限
drgparameter[7]=(uint8_t )Temp1;
drgparameter[6]=(uint8_t )(Temp1>>8);
drgparameter[5]=(uint8_t )(Temp1>>16);
drgparameter[4]=(uint8_t )(Temp1>>24);
drgparameter[3]=(uint8_t )Temp2;
drgparameter[2]=(uint8_t )(Temp2>>8);
drgparameter[1]=(uint8_t )(Temp2>>16);
drgparameter[0]=(uint8_t )(Temp2>>24);
//频率步进(单位:Hz)
drgparameter[15]=(uint8_t )ITemp3;
drgparameter[14]=(uint8_t )(ITemp3>>8);
drgparameter[13]=(uint8_t )(ITemp3>>16);
drgparameter[12]=(uint8_t )(ITemp3>>24);
drgparameter[11]=(uint8_t )DTemp3;
drgparameter[10]=(uint8_t )(DTemp3>>8);
drgparameter[9]=(uint8_t )(DTemp3>>16);
drgparameter[8]=(uint8_t )(DTemp3>>24);
//步进时间间隔(单位:us)
drgparameter[19]=(uint8_t )ITemp4;
drgparameter[18]=(uint8_t )(ITemp4>>8);
drgparameter[17]=(uint8_t )DTemp4;
drgparameter[16]=(uint8_t )(DTemp4>>8);
//发送DRG参数
Txdrg();
cfr1[0] = 0x00; //RAM 失能
cfr2[1] = 0x0e; //DRG 使能
Txcfr(0x3); //发送cfrx控制字
}
//发送方波、锯齿波波形程序
void Txramdata(uint8_t *data ,uint16_t len)
{
CS=0;
txd_8bit(0x16); //发送ram控制字地址
for (uint16_t m=0; m<len; m++){
txd_8bit(*data++);
}
CS=1;
DDS_UPDATE();
}
void Txramdata32(uint32_t *data ,uint16_t len)
{
union TagDat{
uint32_t data32;
uint8_t data8[4];
}TagDatSt;
CS=0;
txd_8bit(0x16); //发送ram控制字地址
for (uint16_t m=0; m<len; m++){
TagDatSt.data32 =*data++;
txd_8bit(TagDatSt.data8[3]);
txd_8bit(TagDatSt.data8[2]);
txd_8bit(TagDatSt.data8[1]);
txd_8bit(TagDatSt.data8[0]);
}
CS=1;
DDS_UPDATE();
}
//========================产生方波的程序======================================
void Square_wave(uint32_t Sample_interval)
{
int8_t sq_profile =2;
cfr1[0] = 0x00;
Txcfr(0x1);
uint32_t Temp = ((1000000000/(unsigned long int)(Sample_interval)/64/4)); //1GHz/4, 采样间隔范围:4*(1~65536)ns
if(Temp > 0xffff)
Temp = 0xffff;
profile[sq_profile][7] = 0x24;
profile[sq_profile][6] = 0x00;//DAC 播放开始地址
profile[sq_profile][5] = 0x00;
uint16_t RamAddrEnd =63; //ram 播放点数
profile[sq_profile][4] = (RamAddrEnd<<6)&0xff;// dac 播放RAM 结束地址
profile[sq_profile][3] = (RamAddrEnd>>2)&0xff;
profile[sq_profile][2] = (uint8_t )Temp;// dac 播放速度
profile[sq_profile][1] = (uint8_t )(Temp>>8);
profile[sq_profile][0] = 0x00;
Txprofile_cfg(sq_profile);
Txramdata((uint8_t*)ramdata_Square,RamAddrEnd*4); // 发送波形文件
cfr1[0] = 0xc0; //RAM 使能,幅度控制
Txcfr(0x1); //发送cfrx控制字
}
//产生锯齿波的程序=====================================
void Sawtooth_wave(uint32_t Sample_interval)
{
int8_t sa_profile =3;
cfr1[0] = 0x00;//根据pdf描述先,disable RAM mode
Txcfr(0x1);
uint32_t Temp = ((1000000000/(unsigned long int)(Sample_interval)/64/4));
//1GHz/4, 采样间隔范围:4*(1~65536)ns
if(Temp > 0xffff)
Temp = 0xffff;
profile[sa_profile][7] = (1<<5)|(4<<0);// 连续循环模式
profile[sa_profile][6] = 0x00;
profile[sa_profile][5] = 0x00;
uint16_t RamAddrEnd =63; //ram 播放点数
profile[sa_profile][4] = (RamAddrEnd<<6)&0xff;
profile[sa_profile][3] = (RamAddrEnd>>2)&0xff;
profile[sa_profile][2] = (uint8_t )Temp;
profile[sa_profile][1] = (uint8_t )(Temp>>8);
profile[sa_profile][0] = 0x00;
Txprofile_cfg(sa_profile);
Txramdata((uint8_t*)ramdata_Sawtooth,RamAddrEnd*4);//发送波形文件
cfr1[0] = 0xc0; //RAM 使能,幅度控制
Txcfr(0x1); //发送cfrx控制字
}
//方波输出
// 输出频率 =1Ghz/4/点数{1-1024}/播放速度{1-65535}
// => 250Mhz /点数{1-1024}/播放速度{1-65535}
// 生成原则: {保证点数,最快播放速度}
//uint32_t Freq : 0-20000000
//uint16_t amplitude: 0-16383
//uint16_t phase: = 度数*65535 /360
//int16_t DutyCycle : %1-1000% : {1-1000}
void Square_waveCalc(uint32_t Freq,uint16_t amplitude,uint16_t phase,int16_t DutyCycle){
int8_t sa_profile =2;
uint32_t wavebuf[1024]={0};
cfr1[0] = 0x00;//根据pdf描述先,disable RAM mode
Txcfr(0x1);
uint16_t StepRate =1;//range:1-65535
uint32_t DacPoint = 250000000L/Freq;
if(DacPoint > 1024){// DAC 采样点数
StepRate =DacPoint/1024;// 播放速度
DacPoint =1024;
}
//计算占空比
uint16_t HalfDacPoint =DacPoint*DutyCycle/1000;
//计算相位
uint32_t phaseIndex =phase*360/65535;
phaseIndex =DacPoint*phaseIndex/360;
if(phaseIndex)phaseIndex--;
uint16_t i;
for(i=0;i<DacPoint;i++){// 根据点数计算波形周期
RAM_WAVE[i]=(i<HalfDacPoint)? (uint32_t)amplitude<<18:0; //高低电平模式,幅度可变
}
if(phaseIndex>0){ //根据相位移动缓存数据
memcpy(wavebuf,RAM_WAVE,phaseIndex*4);
memcpy(RAM_WAVE,&RAM_WAVE[phaseIndex],(DacPoint-phaseIndex)*4);
memcpy(&RAM_WAVE[DacPoint-phaseIndex],wavebuf,phaseIndex*4);
}
profile[sa_profile][7] = (1<<5)|(4<<0);// 连续循环模式
profile[sa_profile][6] = 0x00;
profile[sa_profile][5] = 0x00;
profile[sa_profile][4] = (DacPoint<<6)&0xff;
profile[sa_profile][3] = (DacPoint>>2)&0xff;
profile[sa_profile][2] = (uint8_t )StepRate; //播放速度
profile[sa_profile][1] = (uint8_t )(StepRate>>8);
profile[sa_profile][0] = 0x00;
Txprofile_cfg(sa_profile);
Txramdata32(RAM_WAVE,DacPoint);//发送波形文件
cfr1[0] = 0xc0;//RAM 使能,幅度控制
cfr1[1] = 0x00;//反sin 滤波器关闭
cfr1[3] =0x02;//
cfr2[0] =0x01;// enable profile x
cfr2[1] =(1<<6);// enable SYNC_CLK out
cfr2[2] =(1<<3);// enable PDCLK out
cfr2[3] =0;// disable parallel I mode
cfr3[0] =0x05;//PLL =1Ghz
cfr3[2] =0x41;// PLL enable
Txcfr(0x7);//发送cfrx控制字
}
// 锯齿波
// 输出频率 =1Ghz/4/点数{1-1024}/播放速度{1-65535}
// => 250Mhz /点数{1-1024}/播放速度{1-65535}
// 生成原则: {保证点数,最快播放速度}
//uint32_t Freq : 0-20000000
//uint16_t amplitude: 0-16383
//uint16_t phase: = 度数*65535 /360
void Sawtooth_waveCalc(uint32_t Freq,uint16_t amplitude,uint16_t phase){
int8_t sa_profile =3;
uint32_t wavebuf[1024]={0};
cfr1[0] = 0x00;//根据pdf描述先,disable RAM mode
Txcfr(0x1);
uint16_t StepRate =1;//range:1-65535
uint32_t DacPoint = 250000000L/Freq;
if(DacPoint > 1024){// DAC 采样点数
StepRate =DacPoint/1024;// 播放速度
DacPoint =1024;
}
uint16_t HalfDacPoint =DacPoint>>1;
//计算相位
uint32_t phaseIndex =phase*360/65535;
phaseIndex =DacPoint*phaseIndex/360;
if(phaseIndex)phaseIndex--;
uint16_t i,j=0;
uint32_t tempval =0;
if(DacPoint&1){//奇数点数时正常对称显示
j = amplitude /HalfDacPoint; //得到单斜率点数间隔
for(i=0;i<HalfDacPoint+1;i++){//up
tempval =i*j;
RAM_WAVE[i] =tempval<<18;
}
for(j=0;j<HalfDacPoint;j++,i++){//down
tempval=RAM_WAVE[HalfDacPoint-j-1];
RAM_WAVE[i] =tempval<<18;
}
}else{//偶数点,上升比下降多一个点
j = amplitude /(HalfDacPoint+1); //得到单斜率点数间隔
for(i=0;i<HalfDacPoint+1;i++){//UP
tempval =i*j;
RAM_WAVE[i] =tempval<<18;
}
j = amplitude /(HalfDacPoint-1); //得到单斜率点数间隔
for(i=0;i<HalfDacPoint-1;i++){//DOWN
tempval =(HalfDacPoint-i-1)*j;
RAM_WAVE[i+HalfDacPoint+1] =tempval<<18;
}
}
if(phaseIndex>0){ //根据相位移动缓存数据
memcpy(wavebuf,RAM_WAVE,phaseIndex*4);
memcpy(RAM_WAVE,&RAM_WAVE[phaseIndex],(DacPoint-phaseIndex)*4);
memcpy(&RAM_WAVE[DacPoint-phaseIndex],wavebuf,phaseIndex*4);
}
profile[sa_profile][7] = (1<<5)|(4<<0);// 连续循环模式
profile[sa_profile][6] = 0x00;
profile[sa_profile][5] = 0x00;
profile[sa_profile][4] = (DacPoint<<6)&0xff;
profile[sa_profile][3] = (DacPoint>>2)&0xff;
profile[sa_profile][2] = (uint8_t )StepRate; //播放速度
profile[sa_profile][1] = (uint8_t )(StepRate>>8);
profile[sa_profile][0] = 0x00;
Txprofile_cfg(sa_profile);
Txramdata32(RAM_WAVE,DacPoint);//发送波形文件
cfr1[0] = 0xc0;//RAM 使能,幅度控制
cfr1[1] = 0x40;//反sin 滤波器on
cfr1[3] =0x02;//
cfr2[0] =0x01;// enable profile x
cfr2[1] =(1<<6);// enable SYNC_CLK out
cfr2[2] =(1<<3);// enable PDCLK out
cfr2[3] =0;// disable parallel I mode
cfr3[0] =0x05;//PLL =1Ghz
cfr3[2] =0x41;// PLL enable
Txcfr(0x7);//发送cfrx控制字
}
// 使能16bit 外部总线发送数据
void Parallel_wave(uint16_t length){
if(length){
cfr1[0] =0;// disable RAM mode
cfr1[1] = 0x00;//反sin 滤波器off
cfr1[3] =0x02;//
cfr2[0] =0;// disable profile x
cfr2[1] =(1<<6);// enable SYNC_CLK out
cfr2[2] =(1<<3);// enable PDCLK out
cfr2[3] =(1<<4);// enable parallel I mode
cfr3[0] = 0x07;//PLL 被旁路
cfr3[2] =0x40;// PLL disable
Txcfr(0x7);
delay_ms(10);
int8_t sa_profile =0;
// 清空 配置
profile[sa_profile][7] = 0x00;
profile[sa_profile][6] = 0x00;
profile[sa_profile][5] = 0x00;
profile[sa_profile][4] = 0x00;
profile[sa_profile][3] = 0x00;
profile[sa_profile][2] = 0x00;
profile[sa_profile][1] = 0x00;
profile[sa_profile][0] = 0x00;
Txprofile_cfg(sa_profile);
MYDMA_Enable(DMA2_Stream1,length);//start dma
TIM1->CR1=0x1;// enable TIM1
}else{
TIM1->CR1=0;
Disable_DMA(DMA2_Stream1);
}
}
#ifndef __AD9910_H
#define __AD9910_H
#include <stdint.h>
#include <stdlib.h>
#include <stdint.h>
#include "sys.h"
#include <spi.h>
#define DDS_OSK PBout(9)
#define AD9910_PWR PCout(12) //
#define PROFILE2 PBout(7)
#define PROFILE1 PBout(6)
#define PROFILE0 PBout(5)
#define DRCTL PBout(4)
#define DRHOLD PBout(3)
#define UP_DAT PCout(13)
#define MAS_REST PBout(8)
#define CS PGout(10)
void AD9110_IOInit(void);
void Init_ad9910(void);
void Freq_convert(uint32_t Freq,uint16_t amplitude,uint16_t phase); //写频率
void Amp_convert(unsigned int Amplitude); //写幅度
void Txcfr(int8_t);
extern void IoProfileUpdate(int8_t x);
void Square_wave(uint32_t Sample_interval); //方波;
void Sawtooth_wave(uint32_t Sample_interval); //三角波
void SweepFre(uint32_t SweepMinFre, uint32_t SweepMaxFre, uint32_t SweepStepFre, uint32_t SweepTime); //扫频
extern void Square_waveCalc(uint32_t Freq,uint16_t amplitude,uint16_t phase,int16_t DutyCycle);
extern void Sawtooth_waveCalc(uint32_t Freq,uint16_t amplitude,uint16_t phase);
extern volatile uint16_t ParallelTbl[25000];
extern void Parallel_wave(uint16_t length);
#endif
使用方法:文章来源地址https://www.toymoban.com/news/detail-638048.html
uint32_t freqSet =1000000;//1Mhz
uint16_t amplitude =0x3fff;//14bit
uint16_t phase =0xffff;//
uint16_t SampleRate =20000;
int16_t DutyCycle = 500;//50.0%
int8_t ModeSetType =0;
uint16_t parallelLength =360;
void makeOut(void){
switch(ModeSetType){
case 0://sine
Parallel_wave(0);
Freq_convert(freqSet,amplitude,phase);
break;
case 1://square
// Square_wave(SampleRate);
Parallel_wave(0);
Square_waveCalc(freqSet,amplitude,phase,DutyCycle);
break;
case 2://Triangular
// Sawtooth_wave(SampleRate);
Parallel_wave(0);
Sawtooth_waveCalc(freqSet,amplitude,phase);
break;
case 3:// parallel data port
Parallel_wave(parallelLength);//
break;
default:break;
}
}
到了这里,关于stm32+AD9910 并口驱动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!