在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例嵌入式开发 → 由51控制DDS做FM调制代码

由51控制DDS做FM调制代码

嵌入式开发

下载此实例
  • 开发语言:C/C++
  • 实例大小:5.88KB
  • 下载次数:8
  • 浏览次数:237
  • 发布时间:2021-01-14
  • 实例类别:嵌入式开发
  • 发 布 人:vangqi
  • 文件格式:.c
  • 所需积分:2
 相关标签: 调制 51 代码 控制 dd

实例介绍

【实例简介】利用51单片机控制DDS发出FM波,对ADC采集的音频信号进行调制
【实例截图】所有代码都在一个main.c里,可根据注释修改具体参数如中心频率带宽等等from clipboard

【核心代码】

#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);

}

标签: 调制 51 代码 控制 dd

实例下载地址

由51控制DDS做FM调制代码

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警