#include<STC12C56.h>//使用<>用来引用标准库的头文件,编译器将从标库目录开始搜索
#include<intrins.h>
#include"AD9833-12864下位机.h"//使用“”用来引用非标准库的头文件,编译器将从用户的工作目录开始搜索
int main()//系统主函数
{
Mcu_init();
while (1)
{
if (f10ms)
{
f10ms = 0;
BUF_dispose();
Key_dispose();
FREQ_dispose();
PWM_alert();
Wave_mode();
Result_9833(0, 45);
}
}
return 0;
}
//定时报警子程序
void PWM_alert(void)
{
pwm++;
if (alarm)
{
if (pwm < 15)
alert = 1;
else
alert = 0;
}
if (pwm > 30)
pwm = 0;
}
//频率转换以便于单片机快速处理按键控制任务
void FREQ_dispose(void)
{
if (FREQ > 6000)
{
FREQ = 6000;
alarm = 1;//频率超过6M时,报警指示灯亮,且频率仍视为6M
}
if ((FREQ>1) && (FREQ<6000))
{
alarm = 0;
alert = 0;
}
if (FREQ < 1)
{
FREQ = 1;
alarm = 1;//频率低于1K时,电路报警,且频率仍为1K
}
}
//延时nMs函数:为提高效率,将长循环放在内层,以减少CPU跨切循环层的次数
/*void Delay(uchar t)
{
uchar col;
uchar row;
while (t--)
{
for (col = 10; col>0; col--)
{
for (row = 0; row<169; row++);
}
}
}*/
//单片机上电初始化
void Mcu_init(void)
{
buf = 0x20;//默认开机显示三角波,步进1K,频率不增不减
alert = 0;
P1M0 = 0xe0;//1110 0000为了使5V单片机与3V的AD9833正常通讯,单片机对应端口设置成开漏输出,以便外部上拉使电平匹配
P1M1 = 0xe0;//1110 0000
P3M0 = 0x00;//0000 0000
P3M1 = 0x04;//0000 0100
TR0 = 1;//开定时/计数器0
AUXR = 0x80;//定时器时钟1T模式
TMOD = 0x21;//设置定时器模式:T0工作方式16位;T1是8位自动重载作为波特率发生器
TL0 = 0x66;//设置定时初值,定时500us
TH0 = 0xEA;
EA = 1;//开总中断
ET0 = 1;//定时/计数器0允许中断
SCON = 0x40;//串口工作在方式1:10位异步收发
PCON = 0x00;//波特率不加倍
TH1 = 0xFD;
TL1 = 0xFD;//波特率4800
TR1 = 1;
}
//发送数据处理,每500ms发送一次
void BUF_dispose(void)
{
buftime++;
if (buftime > 49)
{
TxdBUF[1] = FREQ>>8;
TxdBUF[0] = FREQ&0xff;
TxdBUF[3] = step>>8;
TxdBUF[2] = step&0xff;
TxdBUF[4] = add_flag2;
Checksum = 0;
Checksum += TxdBUF[0];
Checksum += TxdBUF[1];
Checksum += TxdBUF[2];
Checksum += TxdBUF[3];
Checksum += TxdBUF[4];
TxdBUF[5] = Checksum>>8;
TxdBUF[6] = Checksum&0xff;
TxdIndex=1;
SBUF=TxdBUF[0];
buftime = 0;
}
}
//AD9833写函数
void Write_9833_d16(uint x)//向AD9833写数据/命令函数
{
uchar i;
uchar w;
SCLK_H;//对SCLK置高电平,这是写数据的第一步
FSYNC_H;
FSYNC_L;//先对AD9833进行使能设置
w = (x >> 8);//取x的高8位进行传输
for (i=0; i<8; i++)
{
if ((w << i) & (0x80))
SDATA_H;
else
SDATA_L;;
SCLK_L;//模拟时钟
SCLK_H;
}//发送高8位数据
w = (x >> 0);//取x的低8位进行传输
for (i=0; i<8; i++)
{
if ((w << i) & (0x80))
SDATA_H;
else
SDATA_L;;
SCLK_L;
SCLK_H;
}//发送低8位数据
FSYNC_H;//关闭使能端
}
//AD9833转换函数
void Result_9833(uchar freq_SFR, uchar wave_PHASE)
{
double freq = 1000.0;
int freq_LSB;
int freq_MSB;
int phase_DAT;
double freq_MID;
double freq_DAT;
long int freq_HEX;
wait++;
if(wait == 10)
{
wait = 0;
freq = FREQ*1000;
/*计算频率的16进制值*/
freq_MID = 268435456/25;//适合25M贴片有源晶振
freq_DAT = freq;
freq_DAT = freq_DAT/1000000;
freq_DAT = freq_DAT*freq_MID;
freq_HEX = freq_DAT;//这个freq_HEX是个很大的值,需要拆分成两个14位的进行处理
freq_LSB = freq_HEX;//低16位送给freq_LSB
freq_LSB = freq_LSB&0x3fff;//去掉高两位变成14位的数据
freq_MSB = freq_HEX>>14;//高16位送给freq_MSB
freq_MSB = freq_MSB&0x3fff;
/*计算相位值*/
phase_DAT = wave_PHASE | 0xC000;
/*把数据设置到设置频率寄存器0*/
if (freq_SFR == 0)
{
freq_LSB = freq_LSB | 0x4000;
freq_MSB = freq_MSB | 0x4000;
Write_9833_d16(0x0100);//复位ad9833,即reset位为1
Write_9833_d16(0x2100);//选择数据一次写入,B28和reset位为1
Write_9833_d16(freq_LSB);//L14(低14位),选择频率寄存器0的低14位数据输入
Write_9833_d16(freq_MSB);//H14,频率寄存器的高14位数据输入
Write_9833_d16(phase_DAT);//设置相位
Write_9833_d16(0x2000);//设置FSELECT位为0,芯片开始工作,频率寄存器0输出波形
}
/*把数据设置到设置频率寄存器1*/
if (freq_SFR == 1)
{
freq_LSB = freq_LSB | 0x8000;
freq_MSB = freq_MSB | 0x8000;
//使用频率寄存器1输出波形
Write_9833_d16(0x0100);//复位ad9833,即reset位为1
Write_9833_d16(0x2100);//选择数据一次写入,B28和reset位为1
Write_9833_d16(freq_LSB);//L14(低14位),选择频率寄存器0的低14位数据输入
Write_9833_d16(freq_MSB);//H14(高14位),频率寄存器的高14位数据输入
Write_9833_d16(phase_DAT);//设置相位
Write_9833_d16(0x2800);//设置FSELECT位为1,芯片开始工作,频率寄存器1输出波形
}
}
}
//AD9833波形选择函数
void Wave_mode(void)
{
if (add_flag2 == 0)//输出三角波
{
//Delay(10);//延时10ms
Write_9833_d16(0x2002);//设置MODE位为1,输出三角波
//buf1 = 0;
//buf0 = 0;
}
if (add_flag2 == 1)//输出方波
{
//Delay(10);//延时10ms
Write_9833_d16(0x2028);//设置OPBITEN位为1,输出方波
//buf1 = 0;
//buf0 = 1;
}
if (add_flag2 == 2)//输出正弦波
{
//Delay(10);//延时10ms
Write_9833_d16(0x2000);//设置MODE位为0,输出正弦波
//buf1 = 1;
//buf0 = 0;
}
}
//按键扫描函数
void Key_dispose(void)
{
//按键去抖
if(keysave == keytemp)
{
keyms10++;
if(keyms10 >4)
{
keyms10 = 5;
key = keysave;//去抖动后记录按键有效值
}
}
else
{
keyms10 = 0;
keysave = keytemp;
}
//按键处理
if (key != keybefore)//短按生效
{
if (key == 0xfe)
{
switch (add_flag1)
{
case 0 : FREQ += 1;step = 1; break;//频率每次增加1K,即步进为1K
case 1 : FREQ += 10;step = 10; break;//频率每次增加10K,即步进为10K
case 2 : FREQ += 100;step = 100; break;//频率每次增加100K,即步进为100K
case 3 : FREQ += 1000;step = 1000; break;//频率每次增加1M,即步进为1M
default : break;
}
}
if (key == 0xfd)
{
switch (add_flag1)
{
case 0 : FREQ -= 1;step = 1; break;//频率减少1K,即步进为1K
case 1 : FREQ -= 10;step = 10; break;//频率减少10K,即步进为10K
case 2 : FREQ -= 100;step = 100; break;//频率减少100K,即步进为100K
case 3 : FREQ -= 1000; step = 1000; break;//频率减少1M,即步进为1M
default : break;
}
}
if (key == 0xfb)
{
add_flag1++;
if (add_flag1 > 3)
{
add_flag1 = 0;
}
}
if (key == 0xf7)
{
add_flag2++;
if (add_flag2 > 2)
{
add_flag2 = 0;
}
}
}
keybefore = key;
}
//定时器0中断服务函数
void timer0(void) interrupt 1 using 0//T1中断服务函数:按键处理,定时扫描要执行
{
keytemp = 0xff;
TR0 = 0;
TF0 = 0;//定时器0无溢出,中断由硬件清零此标志位,若是采用T0查询法则必须用软件清零
count++;
if (!key1)
keytemp &= 0xfe;
else
keytemp &= 0xff;
if (!key2)
keytemp &= 0xfd;
else
keytemp &= 0xff;
if (!key3)
keytemp &= 0xfb;
else
keytemp &= 0xff;
if (!key4)
keytemp &= 0xf7;
else
keytemp &= 0xff;
if (count > 20)
{
count = 0;
f10ms = 1;
}
//if ((FREQ>1000) && (FREQ<6000000)) alert = 0; //如果将此句放于此处,而FREQ又是32位的,导致按键功能失效,因为定时器中断服务函数执行过长
TL0 = 0x66; //设置定时初值 可以用示波器通过任意IO口输出测量加或不加该句中断执行所需时间
TH0 = 0xEA; //设置定时初值
TR0 = 1;//开定时器0
}
//串口中断函数,没过500ms连续发送一包数据,其他时间不发送
void uart(void) interrupt 4 using 1
{
if (TI)
{
TI = 0;
if (TxIndex < TXD_length)//一个主循环发送一帧数据,而一个数据包共有7帧数据,这就要循环发送7次,而最后两个字节是校验和
{
SBUF = TxdBUF[TxIndex];
TxIndex++;
}
}
}
#include<intrins.h>
#include"AD9833-12864下位机.h"//使用“”用来引用非标准库的头文件,编译器将从用户的工作目录开始搜索
int main()//系统主函数
{
Mcu_init();
while (1)
{
if (f10ms)
{
f10ms = 0;
BUF_dispose();
Key_dispose();
FREQ_dispose();
PWM_alert();
Wave_mode();
Result_9833(0, 45);
}
}
return 0;
}
//定时报警子程序
void PWM_alert(void)
{
pwm++;
if (alarm)
{
if (pwm < 15)
alert = 1;
else
alert = 0;
}
if (pwm > 30)
pwm = 0;
}
//频率转换以便于单片机快速处理按键控制任务
void FREQ_dispose(void)
{
if (FREQ > 6000)
{
FREQ = 6000;
alarm = 1;//频率超过6M时,报警指示灯亮,且频率仍视为6M
}
if ((FREQ>1) && (FREQ<6000))
{
alarm = 0;
alert = 0;
}
if (FREQ < 1)
{
FREQ = 1;
alarm = 1;//频率低于1K时,电路报警,且频率仍为1K
}
}
//延时nMs函数:为提高效率,将长循环放在内层,以减少CPU跨切循环层的次数
/*void Delay(uchar t)
{
uchar col;
uchar row;
while (t--)
{
for (col = 10; col>0; col--)
{
for (row = 0; row<169; row++);
}
}
}*/
//单片机上电初始化
void Mcu_init(void)
{
buf = 0x20;//默认开机显示三角波,步进1K,频率不增不减
alert = 0;
P1M0 = 0xe0;//1110 0000为了使5V单片机与3V的AD9833正常通讯,单片机对应端口设置成开漏输出,以便外部上拉使电平匹配
P1M1 = 0xe0;//1110 0000
P3M0 = 0x00;//0000 0000
P3M1 = 0x04;//0000 0100
TR0 = 1;//开定时/计数器0
AUXR = 0x80;//定时器时钟1T模式
TMOD = 0x21;//设置定时器模式:T0工作方式16位;T1是8位自动重载作为波特率发生器
TL0 = 0x66;//设置定时初值,定时500us
TH0 = 0xEA;
EA = 1;//开总中断
ET0 = 1;//定时/计数器0允许中断
SCON = 0x40;//串口工作在方式1:10位异步收发
PCON = 0x00;//波特率不加倍
TH1 = 0xFD;
TL1 = 0xFD;//波特率4800
TR1 = 1;
}
//发送数据处理,每500ms发送一次
void BUF_dispose(void)
{
buftime++;
if (buftime > 49)
{
TxdBUF[1] = FREQ>>8;
TxdBUF[0] = FREQ&0xff;
TxdBUF[3] = step>>8;
TxdBUF[2] = step&0xff;
TxdBUF[4] = add_flag2;
Checksum = 0;
Checksum += TxdBUF[0];
Checksum += TxdBUF[1];
Checksum += TxdBUF[2];
Checksum += TxdBUF[3];
Checksum += TxdBUF[4];
TxdBUF[5] = Checksum>>8;
TxdBUF[6] = Checksum&0xff;
TxdIndex=1;
SBUF=TxdBUF[0];
buftime = 0;
}
}
//AD9833写函数
void Write_9833_d16(uint x)//向AD9833写数据/命令函数
{
uchar i;
uchar w;
SCLK_H;//对SCLK置高电平,这是写数据的第一步
FSYNC_H;
FSYNC_L;//先对AD9833进行使能设置
w = (x >> 8);//取x的高8位进行传输
for (i=0; i<8; i++)
{
if ((w << i) & (0x80))
SDATA_H;
else
SDATA_L;;
SCLK_L;//模拟时钟
SCLK_H;
}//发送高8位数据
w = (x >> 0);//取x的低8位进行传输
for (i=0; i<8; i++)
{
if ((w << i) & (0x80))
SDATA_H;
else
SDATA_L;;
SCLK_L;
SCLK_H;
}//发送低8位数据
FSYNC_H;//关闭使能端
}
//AD9833转换函数
void Result_9833(uchar freq_SFR, uchar wave_PHASE)
{
double freq = 1000.0;
int freq_LSB;
int freq_MSB;
int phase_DAT;
double freq_MID;
double freq_DAT;
long int freq_HEX;
wait++;
if(wait == 10)
{
wait = 0;
freq = FREQ*1000;
/*计算频率的16进制值*/
freq_MID = 268435456/25;//适合25M贴片有源晶振
freq_DAT = freq;
freq_DAT = freq_DAT/1000000;
freq_DAT = freq_DAT*freq_MID;
freq_HEX = freq_DAT;//这个freq_HEX是个很大的值,需要拆分成两个14位的进行处理
freq_LSB = freq_HEX;//低16位送给freq_LSB
freq_LSB = freq_LSB&0x3fff;//去掉高两位变成14位的数据
freq_MSB = freq_HEX>>14;//高16位送给freq_MSB
freq_MSB = freq_MSB&0x3fff;
/*计算相位值*/
phase_DAT = wave_PHASE | 0xC000;
/*把数据设置到设置频率寄存器0*/
if (freq_SFR == 0)
{
freq_LSB = freq_LSB | 0x4000;
freq_MSB = freq_MSB | 0x4000;
Write_9833_d16(0x0100);//复位ad9833,即reset位为1
Write_9833_d16(0x2100);//选择数据一次写入,B28和reset位为1
Write_9833_d16(freq_LSB);//L14(低14位),选择频率寄存器0的低14位数据输入
Write_9833_d16(freq_MSB);//H14,频率寄存器的高14位数据输入
Write_9833_d16(phase_DAT);//设置相位
Write_9833_d16(0x2000);//设置FSELECT位为0,芯片开始工作,频率寄存器0输出波形
}
/*把数据设置到设置频率寄存器1*/
if (freq_SFR == 1)
{
freq_LSB = freq_LSB | 0x8000;
freq_MSB = freq_MSB | 0x8000;
//使用频率寄存器1输出波形
Write_9833_d16(0x0100);//复位ad9833,即reset位为1
Write_9833_d16(0x2100);//选择数据一次写入,B28和reset位为1
Write_9833_d16(freq_LSB);//L14(低14位),选择频率寄存器0的低14位数据输入
Write_9833_d16(freq_MSB);//H14(高14位),频率寄存器的高14位数据输入
Write_9833_d16(phase_DAT);//设置相位
Write_9833_d16(0x2800);//设置FSELECT位为1,芯片开始工作,频率寄存器1输出波形
}
}
}
//AD9833波形选择函数
void Wave_mode(void)
{
if (add_flag2 == 0)//输出三角波
{
//Delay(10);//延时10ms
Write_9833_d16(0x2002);//设置MODE位为1,输出三角波
//buf1 = 0;
//buf0 = 0;
}
if (add_flag2 == 1)//输出方波
{
//Delay(10);//延时10ms
Write_9833_d16(0x2028);//设置OPBITEN位为1,输出方波
//buf1 = 0;
//buf0 = 1;
}
if (add_flag2 == 2)//输出正弦波
{
//Delay(10);//延时10ms
Write_9833_d16(0x2000);//设置MODE位为0,输出正弦波
//buf1 = 1;
//buf0 = 0;
}
}
//按键扫描函数
void Key_dispose(void)
{
//按键去抖
if(keysave == keytemp)
{
keyms10++;
if(keyms10 >4)
{
keyms10 = 5;
key = keysave;//去抖动后记录按键有效值
}
}
else
{
keyms10 = 0;
keysave = keytemp;
}
//按键处理
if (key != keybefore)//短按生效
{
if (key == 0xfe)
{
switch (add_flag1)
{
case 0 : FREQ += 1;step = 1; break;//频率每次增加1K,即步进为1K
case 1 : FREQ += 10;step = 10; break;//频率每次增加10K,即步进为10K
case 2 : FREQ += 100;step = 100; break;//频率每次增加100K,即步进为100K
case 3 : FREQ += 1000;step = 1000; break;//频率每次增加1M,即步进为1M
default : break;
}
}
if (key == 0xfd)
{
switch (add_flag1)
{
case 0 : FREQ -= 1;step = 1; break;//频率减少1K,即步进为1K
case 1 : FREQ -= 10;step = 10; break;//频率减少10K,即步进为10K
case 2 : FREQ -= 100;step = 100; break;//频率减少100K,即步进为100K
case 3 : FREQ -= 1000; step = 1000; break;//频率减少1M,即步进为1M
default : break;
}
}
if (key == 0xfb)
{
add_flag1++;
if (add_flag1 > 3)
{
add_flag1 = 0;
}
}
if (key == 0xf7)
{
add_flag2++;
if (add_flag2 > 2)
{
add_flag2 = 0;
}
}
}
keybefore = key;
}
//定时器0中断服务函数
void timer0(void) interrupt 1 using 0//T1中断服务函数:按键处理,定时扫描要执行
{
keytemp = 0xff;
TR0 = 0;
TF0 = 0;//定时器0无溢出,中断由硬件清零此标志位,若是采用T0查询法则必须用软件清零
count++;
if (!key1)
keytemp &= 0xfe;
else
keytemp &= 0xff;
if (!key2)
keytemp &= 0xfd;
else
keytemp &= 0xff;
if (!key3)
keytemp &= 0xfb;
else
keytemp &= 0xff;
if (!key4)
keytemp &= 0xf7;
else
keytemp &= 0xff;
if (count > 20)
{
count = 0;
f10ms = 1;
}
//if ((FREQ>1000) && (FREQ<6000000)) alert = 0; //如果将此句放于此处,而FREQ又是32位的,导致按键功能失效,因为定时器中断服务函数执行过长
TL0 = 0x66; //设置定时初值 可以用示波器通过任意IO口输出测量加或不加该句中断执行所需时间
TH0 = 0xEA; //设置定时初值
TR0 = 1;//开定时器0
}
//串口中断函数,没过500ms连续发送一包数据,其他时间不发送
void uart(void) interrupt 4 using 1
{
if (TI)
{
TI = 0;
if (TxIndex < TXD_length)//一个主循环发送一帧数据,而一个数据包共有7帧数据,这就要循环发送7次,而最后两个字节是校验和
{
SBUF = TxdBUF[TxIndex];
TxIndex++;
}
}
}