嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元微信扫码支付:2 元
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
利用51单片机控制DDS发出FM波,对ADC采集的音频信号进行调制
所有代码都在一个main.c里,可根据注释修改具体参数如中心频率带宽等等
#include <reg52.h>
#define uc unsigned char //DDSwri(...);
#define DELC 103000000 //103,000,000
#define dell 102950000 //DELC-128*DELF;
#define DELF 850 //单位赫兹 //理论值390.625,还需实际调整! //1227
#define XTL 12000 //单片机时钟频率,单位kHz
//#define DDSCLK 67108864 //AD9851工作频率设定为2^26Hz~67MHZ
#define TIM0 50 //DDS接收数据的定时,相位计时,0x32=50,单位uS
//#define FAD 600 //ADC时钟频率600k,单位k
//#define F0 3068800 //B6EA 2C00,102,950,000对应2^32中位置 //3068800000
//#define DEL 25 //0000 61A8,100,000Hz*2^6/256=25,000,对应2^32中的单位大小 //25000
//#define PI 3.1416 //相位计算中用到Π
#define ADC0809 P1 //单片机ADC数据接收脚
#define AD9851 P0 //单片机DDS数据发送脚
//sbit CLK = P3^7; //单片机P1.3接CLK ,ADC0809时钟,输入50-800KHZ的频率
sbit STR = P2^7; //单片机P1.0接模块STR引脚, 启动转换信号
sbit EOC = P2^6; //单片机P1.1接模块EOC, 转换结束信号,高电平有效
sbit OE = P2^5; //单片机P1.2接模块OE,输出允许信号,高电平有效
sbit rest = P3^7; //P0.3口接AD9851的rest脚, 复位清楚40位输入寄存器
sbit Data = P3^6; //P0.6口接AD9851的D7脚,
sbit fq_up= P3^5; //P0.5口接AD9851的fq_up脚, 频率更新,上升沿将40位数据传送至DDS核心
sbit w_clk= P3^4; //P0.4口接AD9851的w_clk脚, 字加载时钟,上升沿加载
sbit SCL = P2^0; // Serial Clock Input
sbit SDA = P2^1; // Serial Data Input
unsigned char ADdata; //保存IN0通道转换后的数据
unsigned char phase; //相位控制字5位
unsigned char i = 0; //0-7循环,ADC八个输入通道循环中使用
//unsigned char j = 0; //用于相位纠正
double freq; //频率HZ
long int fq; //用于频率显示
//long int dell; //最低频率(103M-50k)Hz
double PH; //相位系数
unsigned char det=54; //更新DDS前执行的机器周期数(包括入栈、赋值等),数汇编代码
double x=4294967295/180000000; //去掉了freq=freq/1000000; 4294967295/180000000
long int y; //频率控制字
unsigned char w0; //第32-39位控制字(后八位,2工作方式 1电源休眠 5相位)
unsigned char w1; //第24-31位控制字
unsigned char w2; //第16-23位控制字
unsigned char w3; //第8-15位控制字
unsigned char w4; //第0-7位控制字
unsigned char th; //timer0初值高八位
unsigned char tl; //timer0初值低八位
//函数声明
void AD();
void parameter(); //参数计算函数
void ADInit(); //ADC0809初始化函数
void DDSInit(); //DDS初始化函数
void TimerInit(); //定时器初始化函数
void DDSpre(unsigned char ADdata);
void DDSwri(unsigned char w0,unsigned char w1,unsigned char w2,unsigned char w3,unsigned char w4 ); //AD9851并行模式数据输出函数
void I2C_3(unsigned char mcmd); //I2C oled命令发送函数
void I2C_Ack3(); //ACK信号发送函数
void I2C_Start3();
void I2C_Stop3();
void Write_Command3(unsigned char Data);//写入命令函数
void Write_Data3(unsigned char Data); //写入数据函数
void picint();
void picf(long int f);
void parameter() //参数计算
{
tl=65536-XTL*TIM0/1000; //timer1初始值计算
th=tl>>64; //timer1高8位
PH=0.000064*(TIM0 12000*det/XTL); //相位系数
// dell=DELC-128*DELF; //计算频率下限
}
void TimerInit() //定时器初始化
{
TMOD=0x01; //设定定时器,T0工作方式2,T1工作方式1
TH0=th; //高8位为初值寄存器 600kHz=12MHz20分频=计数20,2^8-20=236; 216
TL0=tl; //利用T0中断产生CLK信号 216 t0s
TR0=1; //启动定时器T0
ET0=1; //timer0溢出中断允许
EA=1; //打开总中断
}
void ADInit() //ADC0809初始化
{
STR=0; //上升沿复位寄存器,下降沿启动AD转换
OE=0; //进行AD转换时变低,转换完成后变高
rest=1; //清除AD9851内40位数据
rest=0;
}
void DDSInit() //DDS初始化
{
w_clk=0; //关闭字加载时钟
fq_up=0; //关闭控制字更新时钟
rest=0; //为后面产生上升沿清除AD9851内40位数据
phase=0; //初始相位规定为0°
w0=0x01; //初始控制字末8位0x01
freq=48000000; //初始频率规定为48MHz
}
void DDSpre(unsigned char ADdata)//控制字产生及分段
{
double freq; //频率值
freq=(ADdata*DELF dell); //计算频率值
y=freq*x; //转换为频率控制字
phase=PH*freq phase; //计算新相位
w0=(phase<<3)|0x01; //第32-39位控制字(后八位,2工作方式 1电源休眠 5相位)
w1=(y>>24); //第24-31位控制字
w2=(y>>16); //第16-23位控制字
w3=(y>>8); //第8-15位控制字
w4=(y>>=0); //第0-7位控制字
}
void DDSwri(uc w0,uc w1,uc w2,uc w3,uc w4) //写入控制字
{
AD9851=w0;
w_clk=1; //w_clk上升沿发送数据
w_clk=0;
AD9851=w1;
w_clk=1;
w_clk=0;
AD9851=w2;
w_clk=1;
w_clk=0;
AD9851=w3;
w_clk=1;
w_clk=0;
AD9851=w4;
w_clk=1;
w_clk=0;
fq_up=1; //fq_up上升沿写入40个控制字到DDS核心
fq_up=0; //关闭控制字更新时钟
}
void AD()
{
STR=1; //启动AD转换
STR=0;
while(0==EOC); //等待转换结束
OE=1;
ADdata=ADC0809; //读取AD数据,数据范围为0-255
OE=0;
}
void Timer1() interrupt 3 //定时计数器1
{
TH0=th; //载入parameter()函数中计算的初始值
TL0=tl;
DDSwri(w0,w1,w2,w3,w4); //写入控制字(放在第一个放目的是使其相位计算精确)
AD(); //进行AD转换
DDSpre(ADdata); //产生控制字及分段
}
void I2C_Ack3() //每个字节后会跟随一个ACK信号。
{ //使得接收者通知发送者已经成功接收数据并准备接收下一个数据
SDA=1;
// uDelay(3);
SCL=1;
// uDelay(3);
SCL=0;
// uDelay(3);
}
void I2C_Start3()
{
SDA=0;
// uDelay(3);
SCL=1;
// uDelay(3);
SCL=0;
// uDelay(3);
I2C_3(0x78);
I2C_Ack3();
}
void I2C_Stop3()
{
SCL=1;
// uDelay(5);
SDA=0;
// uDelay(5);
SDA=1;
// uDelay(5);
}
void Write_Command3(unsigned char Data) //写入命令函数
{
I2C_Start3();
I2C_3(0x00);
I2C_Ack3();
I2C_3(Data);
I2C_Ack3();
I2C_Stop3();
}
void Write_Data3(unsigned char Data) //写入数据函数
{
I2C_Start3();
I2C_3(0x40);
I2C_Ack3();
I2C_3(Data);
I2C_Ack3();
I2C_Stop3();
}
void main() //主函数
{
unsigned char i;
unsigned char j;
parameter(); //参数计算函数
TimerInit(); //定时器初始化
ADInit(); //ADC0809初始化
DDSInit(); //DDS初始化
ADdata=128; //初始AD转换值设为中值,初始频率为中心频率
Write_Command3(0xae);
while(1);
}