AD9910模块的使用
前言,究极折磨怪AD9910!本次尝试使用AD9910产生FM载波,但调试过程十分难受,特此记录下来
上AD9910模块,来自康威电子。听大佬说其并行数据通信实现困难,故明智地选择使用串行通信!
AD9910用来产生FM载波十分便利,来自AD官网的介绍。
在实现数据发丝前,先了解以下AD9910模块提供的引脚分别有什么作用
STM32引脚配置 | 模块引脚 | 描述 |
AD9910_PF0(GPIOA, GPIO_PIN_3) | PF0 |
Profile Select Pins.文件配置选择引脚,对应有8个配置文件寄存器, 根据引脚的状态进行选择。比如我使用的是第0个profile寄存器,引脚状态 为000. |
AD9910_PF1(GPIOA, GPIO_PIN_4) | PF1 | |
AD9910_PF2(GPIOA, GPIO_PIN_5) | PF2 | |
AD9910_IOUP(GPIOA, GPIO_PIN_6) | IOUP | 维持一段高电平,会将IO缓存中的值传输至内部寄存器中。与AD9910串行通信有关 |
AD9910_SDIO(GPIOA, GPIO_PIN_7) | SDIO | 数据 |
AD9910_SCK(GPIOB, GPIO_PIN_0) | SCK | 时钟 |
AD9910_CS(GPIOB, GPIO_PIN_1) | CSB | 片选 |
AD9910_RET(GPIOB, GPIO_PIN_2) | MASTER_RESET | 复位 。清除内存中的值,并恢复为默认值 |
AD9910_PWR(GPIOA, GPIO_PIN_8) | EXT_PWR_DWN | 掉电。如果不使用,应该接逻辑0 |
AD9910_OSK(GPIOA, GPIO_PIN_9) | OSK | Output Shift Keying.没用过,不清楚,本例程不需要使用 |
AD9910_DRC(GPIOA, GPIO_PIN_10) | DRCTL | Digital Ramp Control。AD官方文档说明,如果不使用,应该接逻辑0 |
AD9910_DRO(GPIOA, GPIO_PIN_11) | DROVER | Digital Ramp Over。不需要使用 |
AD9910_DRH(GPIOA, GPIO_PIN_12) | DRHOLD | Digital Ramp Hold。如果不使用,应该接逻辑0 |
RAM_SWP_OVR(RSO) | RSO | RAM Sweep Over。使用的是正弦调制模式,不需要RAM |
PLL_LOCK(PLL) | PLL | Clock Multiplier PLL Lock。输出口 |
TxENABLE(TEN) | TEN | Transmit Enable。用于并行通信,不用管 |
PDCLK(PD) | PD | Parallel Data Clock |
SDO | SDO | Serial Data Output。输出口 |
在硬件连接这里,有个大坑,就是表中标注的应该接逻辑0的地方,这里都需要单片机输出低电平(我尝试直接接地,但不管用,不懂)
这样连接硬件后,在写好串行通信,应该就可以正常输出了。
直接上网图
串行通信时序图
先是指令周期,后是数据。
1 void CSM_AD9910_TransByte(uint8_t dat) 2 { 3 uint8_t i, sbt = 0x80; 4 AD9910_SCK(0); 5 for (i = 0; i < 8; i++) 6 { 7 if ((dat & sbt) == 0) 8 { 9 AD9910_SDIO(0); 10 } 11 else 12 { 13 AD9910_SDIO(1); 14 } 15 AD9910_SCK(1); 16 sbt = sbt >> 1; 17 AD9910_SCK(0); 18 } 19 }
写数据完成,接下来就是向寄存器写内容了
直接上代码,我使用正弦单频调制,采用商家给的例程,cfr1,cfr2和cfr3寄存器都已经配好了
void CSM_AD9910_Init() { uint8_t i; uint8_t cfr1[5] = {0x00, 0x00, 0x40, 0x00, 0x00}; uint8_t cfr2[5] = {0x01, 0x01, 0x00, 0x00, 0x00}; uint8_t cfr3[5] = {0x02, 0x05, 0x0F, 0x41 ,0x32}; //寄存器控制字,40M输入 25倍频 VC0=101 ICP=001 AD9910_PWR(0);
AD9910_PF0(0); AD9910_PF1(0); AD9910_PF2(0);
AD9910_DRC(0); AD9910_DRH(0); AD9910_RET(1); HAL_Delay(5); AD9910_RET(0); //复位,寄存器恢复为默认值 AD9910_CS(0); for (i = 0; i < 5; i++) { CSM_AD9910_TransByte(cfr1[i]); } AD9910_CS(1); for (i = 0; i < 10; i++); AD9910_CS(0); for (i = 0; i < 5; i++) { CSM_AD9910_TransByte(cfr2[i]); } AD9910_CS(1); for (i = 0; i < 10; i++); AD9910_CS(0); for (i = 0; i < 5; i++) { CSM_AD9910_TransByte(cfr3[i]); } AD9910_CS(1); for (i = 0; i < 10; i++); AD9910_IOUP(1); for (i = 0; i < 10; i++); AD9910_IOUP(0); HAL_Delay(1); }
void CSM_AD9910_Config(uint32_t freq) { uint8_t i; uint32_t temp_freq = (uint32_t)(4.294967296 * freq); //(2^32/1G) profile0[8] = (uint8_t)temp_freq; profile0[7] = (uint8_t)(temp_freq >> 8); profile0[6] = (uint8_t)(temp_freq >> 16); profile0[5] = (uint8_t)(temp_freq >> 24); AD9910_CS(0); for (i = 0; i < 9; i++) { CSM_AD9910_TransByte(profile0[i]); } AD9910_CS(1); for (i = 0; i < 10; i++); AD9910_IOUP(1); for (i = 0; i < 10; i++); AD9910_IOUP(0); HAL_Delay(1); }