PA2.3

请先确保完成pa2.2,现在bug不改,后面迟早要回去填坑。

1.正确实现in 和out指令

    依旧参照手册完成,不同的是调用的函数不是rtl函数,而是pio_read和pio_write。
    in就是从设备输入到cpu,out就是输出到设备。因此从设备寄存器获取数据,使用inb或者inl,用法为in(端口号),返回值即为寄存器中的值。

2.实现串口功能

    正确实现in和out指令,打开串口宏HAS_SERIAL即可。
    这里写图片描述

3.实现时钟功能

    实现_uptime函数。修改返回值即可。由于设备寄存器中存储的是当前时间,为得到相对时间,应和开始的时间作差。如何得到开始的时间,_uptime上面的初始化函数里有。
    这里写图片描述

4.实现键盘功能

    if(状态为1) then 返回设备寄存器的值; else 返回_KEY_NONE;
    提示:inl不行还有inb
    这里写图片描述

5.实现图形功能

    将pixels数组的值一一对应赋值给fb即可,如何对应看讲义描述。
    这里写图片描述
    这里写图片描述

6.其他

    根据程序的顺序来完成2.2的在2.3中会有新的指令需要填写,而且2.2通过的指令在2.3中也可能触发bug。从2.3开始,一般情况下关闭diff-test和debug,仅在调试需要时才打开,不然会非常非常非常非常的慢,而且si单步调试的时候,si几十万是没问题的。

请你尝试迁移下述库文件: AD9959.h #ifndef _AD9959_H_ #define _AD9959_H_ #include "ti_msp_dl_config.h" #include "stdint.h" #include "key.h" //AD9959管脚宏定义 #define CS PAout(6) #define SCLK PBout(1) #define UPDATE PBout(0) #define PS0 PAout(7) #define PS1 PAout(2) #define PS2 PBout(10) #define PS3 PCout(0) #define SDIO0 PAout(5) #define SDIO1 PAout(4) #define SDIO2 PAout(3) #define SDIO3 PAout(8) #define AD9959_PWR PAout(9) #define Reset PAout(10) //AD9959寄存器地址定义 #define CSR_ADD 0x00 //CSR 通道选择寄存器 #define FR1_ADD 0x01 //FR1 功能寄存器1 #define FR2_ADD 0x02 //FR2 功能寄存器2 #define CFR_ADD 0x03 //CFR 通道功能寄存器 #define CFTW0_ADD 0x04 //CTW0 通道频率转换字寄存器 #define CPOW0_ADD 0x05 //CPW0 通道相位转换字寄存器 #define ACR_ADD 0x06 //ACR 幅度控制寄存器 #define LSRR_ADD 0x07 //LSR 线性扫描斜率寄存器 #define RDW_ADD 0x08 //RDW 上升扫描增量寄存器 #define FDW_ADD 0x09 //FDW 下降扫描增量寄存器 #define PROFILE_ADDR_BASE 0x0A //Profile寄存器,配置文件寄存器起始地址 //CSR[7:4]通道选择启用位 #define CH0 0x10 #define CH1 0x20 #define CH2 0x40 #define CH3 0x80 //FR1[9:8] 调制电平选择位 #define LEVEL_MOD_2 0x00//2电平调制 2阶调制 #define LEVEL_MOD_4 0x01//4电平调制 4阶调制 #define LEVEL_MOD_8 0x02//8电平调制 8阶调制 #define LEVEL_MOD_16 0x03//16电平调制 16阶调制 //CFR[23:22] 幅频相位(AFP)选择位 #define DISABLE_Mod 0x00 //00 调制已禁用 #define ASK 0x40 //01 振幅调制,幅移键控 #define FSK 0x80 //10 频率调制,频移键控 #define PSK 0xc0 //11 相位调制,相移键控 //(CFR[14])线性扫描启用 sweep enable #define SWEEP_ENABLE 0x40 //1 启用 #define SWEEP_DISABLE 0x00 //0 不启用 void delay1 (uint32_t length);//延时 void IntReset(void); //AD9959复位 void IO_Update(void); //AD9959更新数据 void Intserve(void); //IO口电平状态初始化 void AD9959_Init(void); //IO口初始化 /***********************AD9959基本寄存器操作函数*****************************************/ void AD9959_WriteData(uint8_t RegisterAddress, uint8_t NumberofRegisters, uint8_t *RegisterData);//向AD9959写数据 void Write_CFTW0(uint32_t fre); //写CFTW0通道频率转换字寄存器 void Write_ACR(uint16_t Ampli); //写ACR通道幅度转换字寄存器 void Write_CPOW0(uint16_t Phase); //写CPOW0通道相位转换字寄存器 void Write_LSRR(uint8_t rsrr,uint8_t fsrr); //写LSRR线性扫描斜率寄存器 void Write_RDW(uint32_t r_delta); //写RDW上升增量寄存器 void Write_FDW(uint32_t f_delta); //写FDW下降增量寄存器 void Write_Profile_Fre(uint8_t profile,uint32_t data);//写Profile寄存器,频率 void Write_Profile_Ampli(uint8_t profile,uint16_t data);//写Profile寄存器,幅度 void Write_Profile_Phase(uint8_t profile,uint16_t data);//写Profile寄存器,相位 /********************************************************************************************/ /*****************************点频操作函数***********************************/ void AD9959_Set_Fre(uint8_t Channel,uint32_t Freq); //写频率 void AD9959_Set_Amp(uint8_t Channel, uint16_t Ampli);//写幅度 void AD9959_Set_Phase(uint8_t Channel,uint16_t Phase);//写相位 /****************************************************************************/ /*****************************调制操作函数 ***********************************/ void AD9959_Modulation_Init(uint8_t Channel,uint8_t Modulation,uint8_t Sweep_en,uint8_t Nlevel);//设置各个通道的调制模式。 void AD9959_SetFSK(uint8_t Channel, uint32_t *data,uint16_t Phase);//设置FSK调制的参数 void AD9959_SetASK(uint8_t Channel, uint16_t *data,uint32_t fre,uint16_t Phase);//设置ASK调制的参数 void AD9959_SetPSK(uint8_t Channel, uint16_t *data,uint32_t Freq);//设置PSK调制的参数 void AD9959_SetFre_Sweep(uint8_t Channel, uint32_t s_data,uint32_t e_data,uint32_t r_delta,uint32_t f_delta,uint8_t rsrr,uint8_t fsrr,uint16_t Ampli,uint16_t Phase);//设置线性扫频的参数 void AD9959_SetAmp_Sweep(uint8_t Channel, uint32_t s_Ampli,uint16_t e_Ampli,uint32_t r_delta,uint32_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Phase);//设置线性扫幅的参数 void AD9959_SetPhase_Sweep(uint8_t Channel, uint16_t s_data,uint16_t e_data,uint16_t r_delta,uint16_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Ampli);//设置线性扫相的参数 /********************************************************************************************/ #endif AD9959.c /************************************************************ AD9959 驱动程序 AD9959--单片机 硬件连接: CS ——PA6; SCLK ——PB1; UPDATE ——PB0; SP0 ——PA7; SP1 ——PA2; SP2 ——PB10; SP3 ——PC0; SDIO0 ——PA5; SDIO1 ——PA4; SDIO2 ——PA3; SDIO3 ——PA8; AD9959_PWR(PDC)——PA9; RST ——PA10; GND --GND(0V) //AD9959.c //康威电子工作室 //说明:本程序基于硬件的外接晶振为25MHZ **************************************************************/ #include "AD9959.h" uint8_t FR1_DATA[3] = {0xD0,0x00,0x00};//VCO gain control[23]=1系统时钟高于255Mhz; PLL[22:18]=10100,20倍频,20*25M=500MHZ; Charge pump control = 75uA uint8_t FR2_DATA[2] = {0x00,0x00}; // 双方向扫描,即从起始值扫到结束值后,又从结束值扫到起始值 //uint8_t FR2_DATA[2] = {0x80,0x00};// 单方向扫描,即从起始值扫到结束值后,又从起始值扫到结束值,以此类推 double ACC_FRE_FACTOR = 8.589934592; //频率因子8.589934592=(2^32)/500000000 其中500M=25M*20(倍频数可编程) uint8_t CFR_DATA[3] = {0x00,0x03,0x02};//default Value = 0x000302 //通道功能寄存器 /************************************************************ ** 函数名称 :void AD9959_Init(void) ** 函数功能 :初始化控制AD9959需要用到的IO口,及寄存器 ** 入口参数 :无 ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void AD9959_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //PA,PB,PC端口时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_2|GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;//初始化管脚PA2.3.4.5.6.7.8.9.10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_10;//初始化管脚PB0.1.10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //IO口速度为2MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //初始化管脚PC0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //IO口速度为2MHz GPIO_Init(GPIOC, &GPIO_InitStructure); //根据设定参数初始化GPIOC Intserve(); //IO口电平状态初始化 IntReset(); //AD9959复位 //初始化功能寄存器 AD9959_WriteData(FR1_ADD,3,FR1_DATA);//写功能寄存器1 AD9959_WriteData(FR2_ADD,2,FR2_DATA);// } //延时 void delay1 (uint32_t length) { length = length*12; while(length--); } /************************************************************ ** 函数名称 :void Intserve(void) ** 函数功能 :IO口电平状态初始化 **************************************************************/ void Intserve(void) { AD9959_PWR=0; CS = 1; SCLK = 0; UPDATE = 0; PS0 = 0; PS1 = 0; PS2 = 0; PS3 = 0; SDIO0 = 0; SDIO1 = 0; SDIO2 = 0; SDIO3 = 0; } /************************************************************ ** 函数名称 :void IntReset(void) ** 函数功能 :AD9959复位 **************************************************************/ void IntReset(void) { Reset = 0; delay1(1); Reset = 1; delay1(30); Reset = 0; } /************************************************************ ** 函数名称 void IO_Update(void) ** 函数功能 : AD9959更新数据 **************************************************************/ void IO_Update(void) { UPDATE = 0; delay1(2); UPDATE = 1; delay1(4); UPDATE = 0; } /************************************************************ ** 函数名称 :void AD9959_WriteData(u8 RegisterAddress, u8 NumberofRegisters, u8 *RegisterData) ** 函数功能 :使用模拟SPI向AD9959写数据 ** 入口参数 :RegisterAddress: 寄存器地址 NumberofRegisters: 要写入的字节数 *RegisterData: 数据起始地址 ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void AD9959_WriteData(uint8_t RegisterAddress, uint8_t NumberofRegisters, uint8_t *RegisterData) { uint8_t ControlValue = 0; uint8_t ValueToWrite = 0; uint8_t RegisterIndex = 0; uint8_t i = 0; ControlValue = RegisterAddress; //写入地址 SCLK = 0; CS = 0; for(i=0; i<8; i++) { SCLK = 0; if(0x80 == (ControlValue & 0x80)) SDIO0= 1; else SDIO0= 0; SCLK = 1; ControlValue <<= 1; } SCLK = 0; //写入数据 for (RegisterIndex=0; RegisterIndex<NumberofRegisters; RegisterIndex++) { ValueToWrite = RegisterData[RegisterIndex]; for (i=0; i<8; i++) { SCLK = 0; if(0x80 == (ValueToWrite & 0x80)) SDIO0= 1; else SDIO0= 0; SCLK = 1; ValueToWrite <<= 1; } SCLK = 0; } CS = 1; } /************************************************************ ** 函数名称 :void Write_CFTW0(uint32_t fre) ** 函数功能 :写CFTW0通道频率转换字寄存器 ** 入口参数 : Freq: 写入频率,范围0~200 000 000 Hz ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_CFTW0(uint32_t fre) { uint8_t CFTW0_DATA[4] ={0x00,0x00,0x00,0x00}; //中间变量 uint32_t Temp; Temp=(uint32_t)fre*ACC_FRE_FACTOR; CFTW0_DATA[3]=(uint8_t)Temp; CFTW0_DATA[2]=(uint8_t)(Temp>>8); CFTW0_DATA[1]=(uint8_t)(Temp>>16); CFTW0_DATA[0]=(uint8_t)(Temp>>24); AD9959_WriteData(CFTW0_ADD,4,CFTW0_DATA);//CTW0 address 0x04 } /************************************************************ ** 函数名称 :void Write_ACR(uint16_t Ampli) ** 函数功能 :写ACR通道幅度转换字寄存器 ** 入口参数 :Ampli: 输出幅度,范围0~1023,控制值0~1023对应输出幅度0~500mVpp左右 ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_ACR(uint16_t Ampli) { uint32_t A_temp=0; uint8_t ACR_DATA[3] = {0x00,0x00,0x00};//default Value = 0x--0000 Rest = 18.91/Iout A_temp=Ampli|0x1000; ACR_DATA[1] = (uint8_t)(A_temp>>8); //高位数据 ACR_DATA[2] = (uint8_t)A_temp; //低位数据 AD9959_WriteData(ACR_ADD,3,ACR_DATA); //ACR address 0x06.CHn设定幅度 } /************************************************************ ** 函数名称 :void Write_CPOW0(uint16_t Phase) ** 函数功能 :写CPOW0通道相位转换字寄存器 ** 入口参数 :Phase: 输出相位,范围:0~16383(对应角度:0°~360°) ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_CPOW0(uint16_t Phase) { uint8_t CPOW0_data[2] = {0x00,0x00}; CPOW0_data[1]=(uint8_t)Phase; CPOW0_data[0]=(uint8_t)(Phase>>8); AD9959_WriteData(CPOW0_ADD,2,CPOW0_data);//CPOW0 address 0x05.CHn设定相位 } /************************************************************ ** 函数名称 :void Write_LSRR(uint8_t rsrr,uint8_t fsrr) ** 函数功能 :写LSRR线性扫描斜率寄存器 ** 入口参数 : rsrr: 上升斜率,范围:0~255 fsrr: 下降斜率,范围:0~255 ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_LSRR(uint8_t rsrr,uint8_t fsrr) { uint8_t LSRR_data[2]={0x00,0x00}; LSRR_data[1]=rsrr; LSRR_data[0]=fsrr;//高8位下降斜率 AD9959_WriteData(LSRR_ADD,2,LSRR_data); } /************************************************************ ** 函数名称 :void Write_RDW(uint32_t r_delta) ** 函数功能 :写RDW上升增量寄存器 ** 入口参数 :r_delta:上升增量,0-4294967295 ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_RDW(uint32_t r_delta) { uint8_t RDW_data[4] ={0x00,0x00,0x00,0x00}; //中间变量 RDW_data[3]=(uint8_t)r_delta; RDW_data[2]=(uint8_t)(r_delta>>8); RDW_data[1]=(uint8_t)(r_delta>>16); RDW_data[0]=(uint8_t)(r_delta>>24); AD9959_WriteData(RDW_ADD,4,RDW_data); } /************************************************************ ** 函数名称 :void Write_FDW(uint32_t f_delta) ** 函数功能 :写FDW下降增量寄存器 ** 入口参数 :f_delta:下降增量,0-4294967295 ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_FDW(uint32_t f_delta) { uint8_t FDW_data[4] ={0x00,0x00,0x00,0x00}; //中间变量 FDW_data[3]=(uint8_t)f_delta; FDW_data[2]=(uint8_t)(f_delta>>8); FDW_data[1]=(uint8_t)(f_delta>>16); FDW_data[0]=(uint8_t)(f_delta>>24); AD9959_WriteData(FDW_ADD,4,FDW_data); } /************************************************************ ** 函数名称 :void Write_Profile_Fre(uint8_t profile,uint32_t data) ** 函数功能 :写Profile寄存器 ** 入口参数 :profile: profile号(0~14) data: 写入频率,范围0~200 000 000 Hz ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_Profile_Fre(uint8_t profile,uint32_t data) { uint8_t profileAddr; uint8_t Profile_data[4] ={0x00,0x00,0x00,0x00}; //中间变量 uint32_t Temp; Temp=(uint32_t)data*ACC_FRE_FACTOR; //将输入频率因子分为四个字节 4.294967296=(2^32)/500000000 Profile_data[3]=(uint8_t)Temp; Profile_data[2]=(uint8_t)(Temp>>8); Profile_data[1]=(uint8_t)(Temp>>16); Profile_data[0]=(uint8_t)(Temp>>24); profileAddr = PROFILE_ADDR_BASE + profile; AD9959_WriteData(profileAddr,4,Profile_data); } /************************************************************ ** 函数名称 :void Write_Profile_Ampli(uint8_t profile,uint16_t data) ** 函数功能 :写Profile寄存器 ** 入口参数 :profile: profile号(0~14) data: 写入幅度,范围0~1023, ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_Profile_Ampli(uint8_t profile,uint16_t data) { uint8_t profileAddr; uint8_t Profile_data[4] ={0x00,0x00,0x00,0x00}; //中间变量 //为幅度调制时幅度数据为[31:22]位 Profile_data[1]=(uint8_t)(data<<6);//[23:22] Profile_data[0]=(uint8_t)(data>>2);//[31:24] profileAddr = PROFILE_ADDR_BASE + profile; AD9959_WriteData(profileAddr,4,Profile_data);//写入32位数据 } /************************************************************ ** 函数名称 :void Write_Profile_Phase(uint8_t profile,uint16_t data) ** 函数功能 :写Profile寄存器 ** 入口参数 :profile: profile号(0~14) data: 写入相位,范围:0~16383 ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void Write_Profile_Phase(uint8_t profile,uint16_t data) { uint8_t profileAddr; uint8_t Profile_data[4] ={0x00,0x00,0x00,0x00}; //中间变量 //为相位调制时相位数据为[31:18]位 Profile_data[1]=(uint8_t)(data<<2);//[23:18] Profile_data[0]=(uint8_t)(data>>6);//[31:24] profileAddr = PROFILE_ADDR_BASE + profile; AD9959_WriteData(profileAddr,4,Profile_data);//写入32位数据 } /************************************************************ ** 函数名称 :void AD9959_Set_Fre(uint8_t Channel,uint32_t Freq) ** 函数功能 :设置通道的输出频率 ** 入口参数 :Channel: 输出通道 CH0-CH3 Freq: 输出频率,范围0~200 000 000 Hz ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void AD9959_Set_Fre(uint8_t Channel,uint32_t Freq) { uint8_t CHANNEL[1] = {0x00}; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL);//控制寄存器写入CHn通道,选择CHn Write_CFTW0(Freq);//输出CHn设定频率 } /************************************************************ ** 函数名称 :void AD9959_Set_Amp(uint8_t Channel, uint16_t Ampli) ** 函数功能 :设置通道的输出幅度 ** 入口参数 :Channel: 输出通道 CH0-CH3 Ampli: 输出幅度,范围0~1023,控制值0~1023对应输出幅度0~500mVpp左右 ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void AD9959_Set_Amp(uint8_t Channel, uint16_t Ampli) { uint8_t CHANNEL[1] = {0x00}; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn Write_ACR(Ampli); // CHn设定幅度 } /************************************************************ ** 函数名称 :void AD9959_Set_Phase(uint8_t Channel,uint16_t Phase) ** 函数功能 :设置通道的输出相位 ** 入口参数 :Channel: 输出通道 CH0-CH3 Phase: 输出相位,范围:0~16383(对应角度:0°~360°) ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void AD9959_Set_Phase(uint8_t Channel,uint16_t Phase) { uint8_t CHANNEL[1] = {0x00}; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn Write_CPOW0(Phase);//CHn设定相位 } /************************************************************ ** 函数名称 :void AD9959_Modulation_Init(uint8_t Channel,uint8_t Modulation,uint8_t Sweep_en,uint8_t Nlevel) ** 函数功能 :设置各个通道的调制模式。 ** 入口参数 : Channel: 输出通道 CH0-CH3 Modulation: 调制模式DISABLE_Mod,ASK,FSK,PSK Sweep_en: 线性扫描模式 SWEEP_ENABLE启用、SWEEP_DISABLE不启用;启用时Nlevel只能是LEVEL_MOD_2 Nlevel: 调制电平选择 LEVEL_MOD_2、4、8、16 ** 出口参数 :无 ** 函数说明 :如将调制电平设置为2电平调制时,对应的P0-P3引脚上的高低电平分别控制CH0-CH3通道(如果对应通道开启的话) 如将调制电平设置为4电平调制时,对应的P0,P1和P2,P3引脚上的高低电平分别控制CH0-CH1通道(如果对应通道开启的话) 由于AD9959只有P0-P3,4个用于调制控制的引脚,因此输出在4电平调制时,只能有2个通道同时设置为调制输出; 8电平和16电平调制时,只能有1个通道同时设置为调制输出。请适当设置几电平调制以满足应用需求。 **注意!!!:设置成4电平调制时,输出通道只能选择CH0-1 设置成8,16电平调制时,输出通道只能选择CH0 本函数未做任意通道兼容,具体方法请参考AD9959芯片手册22-23页,操作FR1[14:12]为对应值。 **************************************************************/ void AD9959_Modulation_Init(uint8_t Channel,uint8_t Modulation,uint8_t Sweep_en,uint8_t Nlevel) { uint8_t i=0; uint8_t CHANNEL[1]={0x00}; uint8_t FR1_data[3]; uint8_t FR2_data[2]; uint8_t CFR_data[3]; for(i=0;i<3;i++)//设置默认值 { FR1_data[i]=FR1_DATA[i]; CFR_data[i]=CFR_DATA[i]; } FR2_data[0]=FR2_DATA[0]; FR2_data[1]=FR2_DATA[1]; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn FR1_data[1]=Nlevel; CFR_data[0]=Modulation; CFR_data[1]|=Sweep_en; CFR_data[2]=0x00; if(Channel!=0)//有通道被使能 { AD9959_WriteData(FR1_ADD,3,FR1_data);//写功能寄存器1 AD9959_WriteData(FR2_ADD,2,FR2_data);//写功能寄存器1 AD9959_WriteData(CFR_ADD,3,CFR_data);//写通道功能寄存器 } } /************************************************************ ** 函数名称 :void AD9959_SetFSK(uint8_t Channel, uint32_t *data,uint16_t Phase) ** 函数功能 :设置FSK调制的参数 ** 入口参数 :Channel: 输出通道 CH0-CH3 *data: 调整频率数据的起始地址 Phase: 输出相位,范围:0~16383(对应角度:0°~360°) ** 出口参数 :无 ** 函数说明 :FSK时信号幅度默认为最大 **************************************************************/ void AD9959_SetFSK(uint8_t Channel, uint32_t *data,uint16_t Phase) { uint8_t i=0; uint8_t CHANNEL[1]={0x00}; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn Write_CPOW0(Phase);//设置相位 Write_CFTW0(data[0]); for(i=0;i<15;i++) Write_Profile_Fre(i, data[i+1]); } /************************************************************ ** 函数名称 :void AD9959_SetASK(uint8_t Channel, uint32_t *data,uint32_t fre,uint16_t Phase) ** 函数功能 :设置ASK调制的参数 ** 入口参数 :Channel: 输出通道 CH0-CH3 *data: 调整幅度数据的起始地址 Freq: 输出频率,范围0~200 000 000 Hz Phase: 输出相位,范围:0~16383(对应角度:0°~360°) ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void AD9959_SetASK(uint8_t Channel, uint16_t *data,uint32_t fre,uint16_t Phase) { uint8_t i=0; uint8_t CHANNEL[1]={0x00}; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn Write_CFTW0(fre);//设置频率 Write_CPOW0(Phase);//设置相位 Write_ACR(data[0]); for(i=0;i<15;i++) Write_Profile_Ampli(i, data[i+1]); } /************************************************************ ** 函数名称 :void AD9959_SetPSK(uint8_t Channel, uint16_t *data,uint32_t fre,uint16_t Phase) ** 函数功能 :设置PSK调制的参数 ** 入口参数 :Channel: 输出通道 CH0-CH3 *data: 调整相位数据的起始地址 Freq: 输出频率,范围0~200 000 000 Hz ** 出口参数 :无 ** 函数说明 :无 **************************************************************/ void AD9959_SetPSK(uint8_t Channel, uint16_t *data,uint32_t Freq) { uint8_t i=0; uint8_t CHANNEL[1]={0x00}; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn Write_CFTW0(Freq); Write_CPOW0(data[0]); for(i=0;i<15;i++) Write_Profile_Phase(i, data[i+1]); } /************************************************************ ** 函数名称 :void AD9959_SetFre_Sweep(uint8_t Channel, uint32_t s_data,uint32_t e_data,uint8_t fsrr,uint8_t rsrr,uint32_t r_delta,uint32_t f_delta,uint16_t Phase) ** 函数功能 :设置线性扫频的参数 ** 入口参数 :Channel: 输出通道 CH0-CH3 s_data: 起始频率,范围0~200 000 000 Hz e_data: 结束频率,范围0~200 000 000 Hz r_delta:上升步长频率,0~200 000 000Hz f_delta:下降步长频率,0~200 000 000Hz rsrr: 上升斜率,范围:1~255,系统时钟为500Mhz时一个控制字约为8ns fsrr: 下降斜率,范围:1~255 Ampli: 输出幅度,范围0~1023,控制值0~1023对应输出幅度0~500mVpp左右 Phase: 输出相位,范围:0~16383(对应角度:0°~360°) ** 出口参数 :无 ** 函数说明 :频点与频点间停留时间 dT = Xsrr*8 单位ns,扫描点数=(起始-结束)/步长 扫频总时间=总扫描频点数*dT **************************************************************/ void AD9959_SetFre_Sweep(uint8_t Channel, uint32_t s_data,uint32_t e_data,uint32_t r_delta,uint32_t f_delta,uint8_t rsrr,uint8_t fsrr,uint16_t Ampli,uint16_t Phase) { uint8_t CHANNEL[1]={0x00}; uint32_t Fer_data=0; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn Write_CPOW0(Phase);//设置相位 Write_ACR(Ampli); //幅度设置 Write_LSRR(rsrr,fsrr);//斜率 Fer_data=(uint32_t)r_delta*ACC_FRE_FACTOR; //频率转换成控制字 Write_RDW(Fer_data);//上升步长 Fer_data=(uint32_t)f_delta*ACC_FRE_FACTOR; Write_FDW(Fer_data);//下降步长 Write_CFTW0(s_data);//起始频率 Write_Profile_Fre(0, e_data);//结束频率 } /************************************************************ ** 函数名称 :void AD9959_SetAmp_Sweep(uint8_t Channel, uint32_t s_Ampli,uint16_t e_Ampli,uint32_t r_delta,uint32_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Phase) ** 函数功能 :设置线性扫幅的参数 ** 入口参数 :Channel: 输出通道 CH0-CH3 s_Ampli: 起始幅度,控制值0~1023对应输出幅度0~500mVpp左右 e_Ampli: 结束幅度, r_delta: 上升步长幅度,0~1023 f_delta: 下降步长幅度,0~1023 rsrr: 上升斜率,范围:1~255,系统时钟为500Mhz时一个控制字约为8ns fsrr: 下降斜率,范围:1~255 fre: 输出频率,范围0~200 000 000 Hz Phase: 输出相位,范围:0~16383(对应角度:0°~360°) ** 出口参数 :无 ** 函数说明 :幅点与幅点间停留时间 dT = Xsrr*8 单位ns;扫描点数=(起始-结束)/步长 扫幅总时间=总扫描幅点数*dT **************************************************************/ void AD9959_SetAmp_Sweep(uint8_t Channel, uint32_t s_Ampli,uint16_t e_Ampli,uint32_t r_delta,uint32_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Phase) { uint8_t CHANNEL[1]={0x00}; uint8_t ACR_data[3] = {0x00,0x00,0x00}; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn Write_CFTW0(fre); //幅度频率 Write_CPOW0(Phase);//设置相位 Write_LSRR(rsrr,fsrr);//斜率 Write_RDW(r_delta<<22);//上升步长 Write_FDW(f_delta<<22);//下降步长 ACR_data[1] = (uint8_t)(s_Ampli>>8); //高位数据 ACR_data[2] = (uint8_t)s_Ampli; //低位数据 AD9959_WriteData(ACR_ADD,3,ACR_data); //ACR 设定起始幅度 Write_Profile_Ampli(0, e_Ampli);//结束幅度 } /************************************************************ ** 函数名称 :void AD9959_SetPhase_Sweep(uint8_t Channel, uint16_t s_data,uint16_t e_data,uint16_t r_delta,uint16_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Ampli) ** 函数功能 :设置线性扫相的参数 ** 入口参数 :Channel: 输出通道 CH0-CH3 s_data: 起始相位,范围:0~16383(对应角度:0°~360°) e_data: 结束相位, r_delta:上升步长,范围:0~16383(对应角度:0°~360°) f_delta:下降步长, rsrr: 上升斜率,范围:1~255,系统时钟为500Mhz时一个控制字约为8ns fsrr: 下降斜率,范围:1~255 fre: 输出频率,范围0~200 000 000 Hz Ampli: 输出幅度,范围0~1023,控制值0~1023对应输出幅度0~500mVpp左右 ** 出口参数 :无 ** 函数说明 :频点与频点间停留时间 dT = Xsrr*8 单位ns;扫描点数=(起始-结束)/步长 扫频总时间=总扫描频点数*dT **************************************************************/ void AD9959_SetPhase_Sweep(uint8_t Channel, uint16_t s_data,uint16_t e_data,uint16_t r_delta,uint16_t f_delta,uint8_t rsrr,uint8_t fsrr,uint32_t fre,uint16_t Ampli) { uint8_t CHANNEL[1]={0x00}; CHANNEL[0]=Channel; AD9959_WriteData(CSR_ADD,1,CHANNEL); //控制寄存器写入CHn通道,选择CHn;以下设置均针对CHn Write_CFTW0(fre); //幅度频率 Write_ACR(Ampli); //幅度设置 Write_LSRR(rsrr,fsrr);//斜率 Write_RDW(r_delta<<18);//上升步长 Write_FDW(f_delta<<18);//下降步长 Write_CPOW0(s_data);//起始相位 Write_Profile_Phase(0, e_data);//结束相位 }
最新发布
08-01
<think>我们正在将STM32的AD9959驱动代码迁移到MSPM0G3507平台。AD9959是一款直接数字频率合成器(DDS),通常通过SPI接口进行控制。迁移的关键在于将STM32的硬件抽象层(HAL)或直接寄存器操作替换为MSPM0G3507的对应操作。 迁移步骤: 1. **接口分析**: - 确定AD9959在STM32上使用的通信接口(通常是SPI,也可能是并行或其他)。假设我们使用SPI。 - 对比STM32和MSPM0G3507的SPI外设特性,如数据宽度、时钟极性、相位、最大时钟频率等。 2. **SPI驱动移植**: - MSPM0G3507使用DriverLib库操作外设,因此需要将STM32的SPI初始化、发送和接收函数替换为MSPM0的对应函数。 - 注意:MSPM0G3507的SPI时钟频率最高为16MHz(在80MHz系统时钟下),需确保满足AD9959的时序要求(AD9959最高支持500MHz系统时钟,但SPI时钟最高为20MHz)。 3. **GPIO控制**: - AD9959通常需要一些控制引脚(如复位、IO更新、芯片选择等)。需要将STM32的GPIO操作替换为MSPM0的GPIO操作。 4. **时序调整**: - 由于MSPM0G3507是Cortex-M0+内核,主频较低(最高80MHz),在操作时序敏感的代码(如延时)时,可能需要调整延时函数。 5. **中断处理**(如果使用): - 如果原驱动使用中断(如DMA传输完成中断),需要将中断服务函数和中断配置迁移到MSPM0的中断系统。 具体代码迁移示例: 1. **SPI初始化**: STM32的SPI初始化可能使用HAL库: ```c SPI_HandleTypeDef hspi; hspi.Instance = SPI1; hspi.Init.Mode = SPI_MODE_MASTER; hspi.Init.Direction = SPI_DIRECTION_2LINES; hspi.Init.DataSize = SPI_DATASIZE_8BIT; hspi.Init.CLKPolarity = SPI_POLARITY_LOW; hspi.Init.CLKPhase = SPI_PHASE_1EDGE; hspi.Init.NSS = SPI_NSS_SOFT; hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; HAL_SPI_Init(&hspi); ``` 在MSPM0G3507上,使用DriverLib初始化SPI: ```c #include <ti/drivers/dpl/ClockP.h> #include <ti/drivers/SPI.h> #include <ti/drivers/spi/SPIMSPM0.h> SPI_Handle spiHandle; SPI_Params spiParams; SPI_Params_init(&spiParams); spiParams.bitRate = 1000000; // 1MHz,根据实际需求调整 spiParams.frameFormat = SPI_POL0_PHA0; // 模式0 spiParams.dataSize = SPI_WORDLENGTH_8BITS; spiHandle = SPI_open(CONFIG_SPI_0, &spiParams); ``` 或者使用寄存器级操作(DriverLib): ```c void initSPI(void) { // 使能SPI外设时钟 CS_setClockGatingMode(CS_SPI0, CS_CLOCK_GATE_ENABLE); // 配置GPIO为SPI功能 GPIO_setFunction(GPIO_PORT(0), GPIO_PIN(5), GPIO_0_PIN5_SPI0_CLK); // CLK GPIO_setFunction(GPIO_PORT(0), GPIO_PIN(6), GPIO_0_PIN6_SPI0_SOMI); // MISO GPIO_setFunction(GPIO_PORT(0), GPIO_PIN(7), GPIO_0_PIN7_SPI0_SIMO); // MOSI // 配置SPI为主机模式 SPI_setMasterMode(SPI0_BASE); // 设置相位和极性 SPI_setClockPhase(SPI0_BASE, SPI_CLOCK_PHASE_1_EDGE); SPI_setClockPolarity(SPI0_BASE, SPI_CLOCK_POLARITY_LOW); // 设置数据长度为8位 SPI_setDataSize(SPI0_BASE, 8); // 设置波特率(系统时钟80MHz,分频系数为40,得到2MHz) SPI_setBitRate(SPI0_BASE, 80000000, 2000000); // 使能SPI SPI_enableModule(SPI0_BASE); } ``` 2. **SPI数据传输**: STM32发送数据: ```c uint8_t data = 0xAA; HAL_SPI_Transmit(&hspi, &data, 1, HAL_MAX_DELAY); ``` MSPM0使用DriverLib发送数据: ```c void SPI_Write(uint8_t data) { SPI_setTransmitData(SPI0_BASE, data); while (SPI_getStatus(SPI0_BASE) & SPI_STATUS_TX_FULL); // 等待发送完成 } ``` 或者使用TI的SPI驱动API(更高级): ```c SPI_Transaction transaction; uint8_t txBuffer[1] = {0xAA}; transaction.count = 1; transaction.txBuf = txBuffer; transaction.rxBuf = NULL; SPI_transfer(spiHandle, &transaction); ``` 3. **GPIO操作**: STM32操作GPIO: ```c HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 拉低片选 ``` MSPM0操作GPIO: ```c // 假设片选引脚为PA4(GPIO0.4) #define CS_PIN 4 #define CS_PORT GPIO_PORT(0) GPIO_setOutputLow(CS_PORT, CS_PIN); ``` 4. **延时函数**: STM32使用HAL_Delay: ```c HAL_Delay(1); // 延时1ms ``` MSPM0使用DriverLib的延时函数(基于系统时钟): ```c #include <ti/devices/msp/msp.h> void delay_ms(uint32_t ms) { // 系统时钟频率(假设为80MHz) uint32_t cycles = ms * (SystemCoreClock / 1000); __delay_cycles(cycles); } ``` 5. **AD9959驱动函数迁移**: 将原有的AD9959驱动函数(如初始化、频率设置等)中的硬件相关部分(SPI、GPIO、延时)替换为上述MSPM0的实现。 注意事项: - 注意AD9959的时序要求,特别是SPI的时钟频率和建立保持时间。MSPM0的SPI时钟最高为16MHz(在80MHz系统时钟下),而AD9959支持最高20MHz的SPI时钟,因此可以满足。 - 如果原STM32驱动使用了DMA,由于MSPM0G3507的DMA功能与STM32不同,需要重新设计DMA传输(或者改用查询方式,因为AD9959的数据传输量通常不大)。 - 注意MSPM0的GPIO电平转换速度,必要时配置为高速模式。 验证方法: - 使用逻辑分析仪或示波器检查SPI信号,确保时序符合AD9959要求。 - 逐步测试AD9959的各个功能(如频率设置、幅度设置等)。 参考资源: - [MSPM0 SDK DriverLib文档](https://www.ti.com/lit/pdf/spruid1)(SPI、GPIO等章节) - AD9959数据手册(关注SPI时序部分) 通过以上步骤,应该能够将AD9959的驱动从STM32迁移到MSPM0G3507平台。 如果遇到具体问题(如特定寄存器配置不成功),可以进一步分析调试。 §§相关问题§§ 1. MSPM0G3507的SPI最大时钟频率是多少?如何配置才能达到最高速度? 2. 如何优化MSPM0G3507的SPI传输性能以匹配AD9959的高速要求? 3. 在MSPM0G3507上如何实现与AD9959通信时的精确时序控制(如IO更新信号)? 4. 如果AD9959需要并行接口,MSPM0G3507如何实现?</think>### 将STM32的AD9959驱动迁移至MSPM0G3507的步骤 #### 1. **硬件接口适配** **关键差异分析**: | 特性 | STM32典型实现 | MSPM0G3507适配要点 | |--------------|---------------------|--------------------------| | 通信接口 | SPI1/SPI2 | 仅支持特定引脚SPI (如`PA5/PA6/PA7`) [^1] | | 时钟频率 | 最高42MHz (SPI) | 最大16MHz (需配置`SPI_CLK = SYSCLK/5`) | | 控制引脚 | 任意GPIO | 需复用为SPI功能 (使用`GPIO_setFunction()`) | **SPI初始化示例**: ```c // === MSPM0 SPI配置 (替换STM32 HAL) === #include <ti/drivers/SPI.h> #include <ti/drivers/spi/SPIMSPM0.h> void AD9959_SPI_Init(void) { SPI_Params params; SPI_Params_init(&params); params.bitRate = 1000000; // 1MHz SPI时钟 params.mode = SPI_MASTER; params.dataSize = 8; // 8位数据 SPI_Handle spi = SPI_open(Board_SPI0, &params); // 配置GPIO复用为SPI功能 GPIO_setFunction(GPIO_PORT(0), GPIO_PIN(5), GPIO_0_PIN5_SPI0_CLK); GPIO_setFunction(GPIO_PORT(0), GPIO_PIN(6), GPIO_0_PIN6_SPI0_SOMI); GPIO_setFunction(GPIO_PORT(0), GPIO_PIN(7), GPIO_0_PIN7_SPI0_SIMO); } ``` #### 2. **通信协议层移植** **SPI数据传输重写**: ```c // 替换STM32的HAL_SPI_TransmitReceive() void AD9959_WriteReg(uint8_t reg, uint32_t data) { SPI_Transaction transaction; uint8_t txBuffer[5] = {reg | 0x80, (data>>24)&0xFF, (data>>16)&0xFF, (data>>8)&0xFF, data&0xFF}; transaction.count = 5; transaction.txBuf = txBuffer; transaction.rxBuf = NULL; SPI_transfer(spiHandle, &transaction); // TI DriverLib SPI传输 IOUpdate_Pulse(); // 触发IO更新信号 } ``` **注意事项**: 1. MSPM0的SPI FIFO深度仅4字节,需分多次传输32位数据 2. 使用`__delay_cycles()`实现精确时序(如复位脉冲): ```c void IOUpdate_Pulse(void) { GPIO_setOutputLow(IOUP_PORT, IOUP_PIN); __delay_cycles(80); // 80个周期延时 @80MHz = 1μs GPIO_setOutputHigh(IOUP_PORT, IOUP_PIN); } ``` #### 3. **时钟与功耗优化** **关键配置调整**: - **系统时钟**:MSPM0最高80MHz (STM32F4可达168MHz),需降低AD9959输出频率预期 - **低功耗模式**:在非工作时段启用睡眠 ```c // 进入低功耗模式 Power_setPerformanceLevel(POWER_PERF_LEVEL_2); __WFI(); // 等待中断唤醒 ``` #### 4. **验证与调试** **测试方法**: 1. **逻辑分析仪**:对比STM32与MSPM0的SPI时序波形 2. **功耗监测**:验证睡眠模式电流(典型值1.3μA) 3. **寄存器回读**:实现读寄存器函数验证配置 ```c uint32_t AD9959_ReadReg(uint8_t reg) { uint8_t txBuf[5] = {reg & 0x7F, 0, 0, 0, 0}; uint8_t rxBuf[5]; SPI_Transaction t = {.txBuf=txBuf, .rxBuf=rxBuf, .count=5}; SPI_transfer(spiHandle, &t); return (rxBuf[1]<<24)|(rxBuf[2]<<16)|(rxBuf[3]<<8)|rxBuf[4]; } ``` **迁移工具推荐**: 1. 使用TI [SysConfig](https://www.ti.com/tool/SYSCONFIG) 自动生成引脚配置代码 2. 利用DriverLib的[SPI示例](https://dev.ti.com/tirex/explore/node?node=A__A8PaqOtqNB9hQgr9e2QwRg__com.ti.MSPM0-SDK__1.4.0__A__MSPM0G3507)作为基础 > **注意**:AD9959的1GHz高频输出需严格遵循PCB布局规则,MSPM0的GPIO翻转速率较STM32慢,建议输出频率≤100MHz[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值