stm32+AD9910 并口驱动

这篇具有很好参考价值的文章主要介绍了stm32+AD9910 并口驱动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

搞了好几天DAC芯片AD9910 ,找到多数资料时SPI控制内部RAM或者DDS输出波形,这里总结一下STM32 FMSC 总线输出到AD9910 ,由于AD9910 的PDCLK 为输出,这里采用PWM输入捕获模式获取 AD9910 PDCLK 的下降沿,采用捕获信号触发DMA2  ,DMA 在将数据搬移到总线上,具体代码如下:


#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模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 51单片机课程设计——基于单片机的AD模数转换设计

    一、功能简介 1.A/D 是模拟量到数字量的转换,依靠的是模数转换器(AnalogtoDigitalConverter),简称ADC。D/A是数字量到模拟量的转换,依靠的是数模转换器(DigitaltoAnalogConverter),简称DAC。它们的道理是完全一样的,只是转换方向不同,因此我们讲解过程主要以A/D为例来讲解。

    2024年02月04日
    浏览(24)
  • 51单片机(十六)AD/DA

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月05日
    浏览(19)
  • 十四、51单片机之AD转换

    (1)A是指analog、模拟的;D是指digital、数字的。 (2)现实世界是模拟的,连续分布的,无法被分成有限份;计算机世界是数字的,离散分布的,是可以被分成有限份的; (3)AD转换就是把一个物理量从模拟的转换成数字的。 自然界多数是模拟量,为了方便计算机处理,人为的数字

    2024年02月06日
    浏览(20)
  • 用FPGA驱动AD9910输出跳频信号

    虽然AD9910芯片老掉牙了,但是还有人在使用。前段时间一直比较忙,又赶上换工作,没时间写博文。最近才慢慢的闲下来,所以又开始分享一下自己工作中的调试经验。 AD9910是一种直接数字合成器(DDS),具有集成的14位DAC,支持高达1 Gsps的采样率。AD9910采用了先进的专有DDS技

    2024年02月02日
    浏览(14)
  • 【单片机】15-AD和DA转换

    1.什么是AD转换? A(A,analog,模拟的,D,digital,数字的) 现实世界是模拟的,连续分布的,无法被分成有限份; 计算机世界是数字的,离散分布的,可以被分成有限份的 AD转换就是把一个物理量从模拟的转换成数字的。 2.AD转换的意义 想要计算机来实现现实世界 3.什么情

    2024年02月07日
    浏览(23)
  • 51单片机学习笔记AD/DA

    AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号。比如单片机只能识别0与5V数字信号,当输入为2.5V——模拟信号时,就需要转化为单片机所能读取的数字信号。 DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号。

    2024年02月09日
    浏览(22)
  • 【【51单片机AD/DA的分析】】

    模数转换 与 数模转换 运算放大器 DA的转换就是利用运算放大器实现的 输出电压v0=-(D7~D0)/256 x (VrefxRfb)/R D7~D0 就是我们控制的按键看输入多少 然后再划分256份 Vref是我们设置的一个基准电压 PWM 这种类型的方波 完全可以看成是一个交流和直流叠加而成的 回忆一下数电的东西

    2024年02月15日
    浏览(24)
  • PIC单片机之AD转换学习记录

            首先,简单介绍一下AD原理。ADC是指将模拟信号转换成数字信号的过程。通俗理解ADC采样就是采集电路中的电压,通过数值的方式表现出来。         以PIC16F877芯片为例,它是10位ADC,供电电压是5V,它能检测的电压也是0~5V(参考电压可以自己修改)。这就好理解了,

    2024年02月04日
    浏览(22)
  • 单片机学习笔记---AD模数转换&DA数模转换

    目录 AD模数转换 XPT2046.c XPT2046.h main.c DA数模转换 main.c 上一篇博客讲了AD/DA转换的工作原理,也介绍了运算放大器的工作原理,这节开始代码演示! 新创建一个工程:AD模数转换 第一个工程将用到LCD1602和Delay函数,所以首先将我们之前讲过的代码模块添加进来 然后创建主程序

    2024年02月19日
    浏览(17)
  • STM32单片机驱动L298N

    L298N的工作原理及电路接线以在之前一章博客中讲解完毕,讲解了三种接线方式的区别,及建议。https://blog.csdn.net/m0_59113542/article/details/121038048?spm=1001.2014.3001.5501 本文章主要讲解STM32的驱动程序    众所周知,L298N可以驱动两个电机,分别为通道A、通道B。 ENA是通道A的使能端,

    2023年04月21日
    浏览(18)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包