📄 dds_cpld.c
字号:
//////////////////////////////////////////////////////////////
//
// 1602子程序
//函数说明:delay(uchar d) 延时2us程序
// lcd_wrcmd(uchar cmd) 写命令子程序
// lcd_wrdata(uchar lcddata) 写数据子程序
// lcd_h() 建立自定义字符库
//Version: 4.11
//说明 : 在Menu的界面支持OK键和快捷键
//Version: 4.2
// 说明 : 加入了TLC5620,当电压大于5V时出现Warning界面
//Time : 7/10 18:30
//Version: 4.3
// 说明 : 1.tlc5620更新成功后会出现"SUCCESSFUL!"的提示
// 2.上限电压提高到7.5V
//Time : 7/13 11:29
//Version: 5.0
// 说明 :DDS调试成功
// Time :7/13 14:54
//////////////////////////////////////////////////////////////
#include<reg51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define lcd_bus P1
#define key_bus P0
sbit rs=P3^2;
sbit rw=P3^3;
sbit e=P3^4;
sbit beep=P3^5;
sbit load=P2^0;
sbit sclk=P2^1;
sbit sdata=P2^2;
sbit sclk_cpld=P2^7;
sbit sdata_cpld=P2^6;
sbit cs=P2^5; //CS=1时,CPLD加载数据,CS=0移位寄存器接受数据MSB------LSB
sbit rst=P2^4; //RST=1 CPLD复位 f=1KHZ
//年月度
uchar code hanzi[]={0x80,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02, 0xf,0x9,0xf,0x9,0xf,0x9,0x11,0, 0x1C,0x14,0x1C,0x0,0x0,0x0,0x00,0x00};
uchar code str1[]="DDS BY H.C.H";
uchar code str2[]="INPUT FREQENCY:";
uchar code str3[]="INPUT PHASE:";
uchar code str4[]="1: FREQENCY"; //频率
uchar code str5[]="2: PHASE"; //相位
uchar code str6[]="3: AMPLITUDE"; //幅度
uchar code str7[]="4: HELP";
uchar code he[]=" A:OK B:DEL D:UP";
uchar code am[]="INPUT AMPLITUDE:";
uchar code warn[]="WARNING!!VOLTAGE < 7.5V";
uchar code ok[]="SUCCESSFUL!";
uchar state=0;
dac_tlc5620(uchar send_char)
{
uchar i;
load=1;
sclk=1;sdata=0;sclk=0;
sclk=1;sdata=0;sclk=0;
sclk=1;sdata=1;sclk=0;
for(i=0;i<8;i++)
{
sclk=1;
if(send_char&0x80) sdata=1;
else sdata=0;
sclk=0;
send_char=send_char<<1;
}
load=0;
load=1;
}
delay(uchar d)
{
while(--d);
}
spi(uint send_char)
{
uchar i;
rst=0;
cs=0;
for(i=0;i<=15;i++)
{
sclk_cpld=0;
delay(50);
if(send_char&0x8000)sdata_cpld=1;
else sdata_cpld=0;
sclk_cpld=1;
delay(50);
send_char=send_char<<1;
}
cs=1;
}
/**********判断忙标志,返回的是一个位BF**********/
bit lcd_busy(void)
{
uchar bflag;
rs=0;
rw=1;
_nop_();
e=1;
_nop_();
lcd_bus=0xff;
bflag=lcd_bus;
e=0;
return(bit)(bflag&0x80); //BF=1 busy
}
/*********写命令,有两个参数,第一个是要写的命令控制字,
第二个是用来控制是否进行忙标志的判断。
busyflag=1:判断;为 0:不判断****************/
void lcd_wrcmd(uchar cmd)
{
while(lcd_busy());
lcd_bus=cmd;
rs=0;
rw=0;
_nop_();
e=1;
_nop_();
_nop_();
e=0;
}
/************向液晶片写数据***************/
void lcd_wrdata( uchar lcddata)
{
while(lcd_busy());
lcd_bus=lcddata;
rs=1;
rw=0;
_nop_();
e=1;
_nop_();
_nop_();
e=0;
}
void lcd_ini(void)
{
lcd_wrcmd(0x38);
delay(100);
lcd_wrcmd(0x0c);
delay(100);
lcd_wrcmd(0x06);
delay(100);
lcd_wrcmd(0x01);
delay(100);
}
//////////////////////////////////////////////
//
// 生成汉字子模函数
// 当lcd_wrdata(0);显示第一个汉字
// 当lcd_wrdata(1);显示第二个汉字
//
//////////////////////////////////////////////
lcd_h()
{
uchar i;
lcd_wrcmd(0x40);
for(i=0;i<24;i++) lcd_wrdata(hanzi[i]);
}
uchar key_ii()
{
uchar keycode=0xff,temp,i;
key_bus=0x0f;
temp=key_bus&0x0f;
if(temp!=0x0f) //有键按下
{
beep=0;
key_bus=0x7f;
for(i=0;i<4;i++)
{
temp=key_bus&0x0f;
if(temp==0x07)
{
keycode=i*4;
break;
}
else if(temp==0x0b)
{
keycode=i*4+1;
break;
}
else if(temp==0x0d)
{
keycode=i*4+2;
break;
}
else if(temp==0x0e)
{
keycode=i*4+3;
break;
}
key_bus=(key_bus>>1)|0x80;
}
while((key_bus&0x0f)!=0x0f) //等待释放
{
key_bus=0x0f;
}
beep=1;
}
return keycode;
}
welcome()
{
uchar temp,i;
lcd_wrcmd(0x0c);
lcd_wrcmd(0x82);
for(i=0;i<12;i++)
lcd_wrdata(str1[i]);
lcd_h();
lcd_wrcmd(0xc4);
lcd_wrdata('2'); lcd_wrdata('0');lcd_wrdata('0');lcd_wrdata('4');
lcd_wrdata(0);
lcd_wrdata('0');lcd_wrdata('7');
lcd_wrdata(1);
while(1)
{
temp=key_ii();
if(temp!=0xff) //按任意键跳转
{
state=1;
lcd_wrcmd(1);
break;
}
}
}
phase()
{
uchar i,j,cnt=0;
lcd_wrcmd(0x0f);
lcd_wrcmd(0xc9);
lcd_wrdata(2);
lcd_wrcmd(0x83);
for(i=0;i<12;i++)lcd_wrdata(str3[i]);
lcd_wrcmd(0xc5);
while(1) //按键处理
{
i=key_ii();
if(i<10)
{ cnt++;
if(cnt<=3)
{
lcd_wrcmd(0xc5+cnt-1);
lcd_wrdata(0x30+i);
}
else
{
cnt=0;
lcd_wrcmd(0xc5);
for(j=0;j<=3;j++)
lcd_wrdata(' ');
lcd_wrcmd(0xc5);
}
}
else if(i==10)
{
state=1;
lcd_wrcmd(0x0c);
lcd_wrcmd(1);
lcd_wrcmd(0x80);
break;
}
else if(i==11)
{
cnt=0;
lcd_wrcmd(0xc5);
for(j=0;j<=3;j++)
lcd_wrdata(' ');
lcd_wrcmd(0xc5);
}
}
}
freq()
{
uchar i,j,p[6],cnt=0; // 假如将cnt定义成全局变量,当退出这个界面时,cnt仍然保存原来的值
uint n;
float f;
lcd_wrcmd(0x80); //会出现光标乱跳的错误
lcd_wrcmd(0xce);
lcd_wrdata('H');
lcd_wrdata('Z');
lcd_wrcmd(0x81);
for(i=0;i<15;i++)lcd_wrdata(str2[i]);
lcd_wrcmd(0x0f);
lcd_wrcmd(0xc4);
while(1) //按键处理
{
i=key_ii();
if(i<10)
{ cnt++;
if(cnt<=6)
{
p[6-cnt]=i;
lcd_wrcmd(0xc4+cnt-1);
lcd_wrdata(0x30+i);
}
else
{
cnt=0;
lcd_wrcmd(0xc4);
for(j=0;j<=6;j++)
lcd_wrdata(' ');
lcd_wrcmd(0xc4);
}
}
else if(i==10)
{
if(cnt==6)
{
f=p[5]*100000+p[4]*10000+p[3]*1000+p[2]*100+p[1]*10+p[0];
spi(f/5.035400390625);
lcd_wrcmd(1);
lcd_wrcmd(0x0c);
lcd_wrcmd(0xc2);
for(i=0;i<11;i++)
lcd_wrdata(ok[i]);
for(n=0;n<1500;n++)
delay(250);
}
state=1;
lcd_wrcmd(0x0c);
lcd_wrcmd(1);
lcd_wrcmd(0x80);
break;
}
}
}
warning()
{
uchar i,ii;
lcd_wrcmd(1);
lcd_wrcmd(0x0c);
lcd_wrcmd(0x83);
for(i=0;i<9;i++)
lcd_wrdata(warn[i]);
lcd_wrcmd(0xc1);
for(i=0;i<14;i++)
lcd_wrdata(warn[i+9]);
while(1)
{
ii=key_ii();
if(ii!=0xff)
{
lcd_wrcmd(1);
break;
}
}
}
uchar dac_convert(uchar *amp)
{
uint v,n;
uchar i;
v=amp[2]*100+amp[1]*10+amp[0]; //减44为实验得到的数据
if(v<750)
{
v=32*v;
dac_tlc5620(v/100);
lcd_wrcmd(1);
lcd_wrcmd(0x0c);
lcd_wrcmd(0xc2);
for(i=0;i<11;i++)
lcd_wrdata(ok[i]);
for(n=0;n<1500;n++)
delay(250);
return 0;
}
else
{
return 1;
}
}
amplitude()
{
uchar i,ii;
uchar amp[3],t=0;
lcd_wrcmd(0x80);
for(i=0;i<16;i++)
lcd_wrdata(am[i]);
lcd_wrcmd(0xcc);
lcd_wrdata('V');
lcd_wrcmd(0xc8);
lcd_wrdata('.');
lcd_wrcmd(0x0f); //开光标
lcd_wrcmd(0xc7);
while(1)
{
ii=key_ii();
if(ii==10)
{
if(t==4)
{
if(dac_convert(amp))
{
warning();
break;
}
}
lcd_wrcmd(0x0c);
state=1;
lcd_wrcmd(1);
break;
}
if(ii<10)
{
t++;
if(t==1)
{
lcd_wrcmd(0xc9);
}
if(t==2)t++;
if(t==1)amp[2]=ii;
else if(t==3)amp[1]=ii;
else if(t==4)amp[0]=ii;
if(t==5)
{
t=0;
lcd_wrcmd(0xc7);
lcd_wrdata(' '); lcd_wrdata('.');lcd_wrdata(' ');lcd_wrdata(' ');
lcd_wrcmd(0xc7);
}
else
{
lcd_wrcmd(0xc6+t);
lcd_wrdata(0x30+ii);
}
}
}
}
menu()
{
uchar i,ii,cnt=1;
lcd_wrcmd(0x83);
for(i=0;i<11;i++)
lcd_wrdata(str4[i]);
lcd_wrcmd(0xc3);
i=0;
while(str5[i]!='\0')
{
lcd_wrdata(str5[i]);
i++;
}
lcd_wrcmd(0x80);
lcd_wrdata('-');
lcd_wrdata('>');
while(1)
{
ii=key_ii();
///////////////////////////翻屏///////////////////////////////
if(ii==13)
{ cnt++;
if(cnt==5) cnt=1;
if(cnt==1)
{
//////////////////////
// ->1: FREQENCY
// 2: PHASE
/////////////////////
lcd_wrcmd(1);//clear
lcd_wrcmd(0x83); //frequency
for(i=0;i<11;i++)
lcd_wrdata(str4[i]);
lcd_wrcmd(0xc3); //phase
i=0;
while(str5[i]!='\0')
{
lcd_wrdata(str5[i]);
i++;
}
lcd_wrcmd(0x80);
lcd_wrdata('-');
lcd_wrdata('>');
}
else if(cnt==2)
{
//////////////////////
// 1: FREQENCY
// ->2: PHASE
/////////////////////
lcd_wrcmd(1);//clear
lcd_wrcmd(0x83); //frequency
for(i=0;i<11;i++)
lcd_wrdata(str4[i]);
lcd_wrcmd(0xc3); //phase
i=0;
while(str5[i]!='\0')
{
lcd_wrdata(str5[i]);
i++;
}
lcd_wrcmd(0xc0);
lcd_wrdata('-');
lcd_wrdata('>');
}
else if(cnt==3)
{
//////////////////////
// 2: PHASE
// -> 3: Amplitude
/////////////////////
lcd_wrcmd(1);
lcd_wrcmd(0xc3); //Amplitude
for(i=0;i<12;i++)
lcd_wrdata(str6[i]);
lcd_wrcmd(0x83);
i=0;
while(str5[i]!='\0') //phase
{
lcd_wrdata(str5[i]);
i++;
}
lcd_wrcmd(0xc0);
lcd_wrdata('-');
lcd_wrdata('>');
}
else if(cnt==4)
{
//////////////////////
// 3: Amplitude
// -> 4: HELP
/////////////////////
lcd_wrcmd(1);
lcd_wrcmd(0x83); //setting
for(i=0;i<12;i++)
lcd_wrdata(str6[i]);
lcd_wrcmd(0xc3);
for(i=0;i<7;i++)
lcd_wrdata(str7[i]); //help
lcd_wrcmd(0xc0);
lcd_wrdata('-');
lcd_wrdata('>');
}
}
////////////////////////////////////////////////////////////////
else if(ii==10)
{
if(cnt==1)
{
state=2;
lcd_wrcmd(1);
break;
}
else if(cnt==2)
{
state=3;
lcd_wrcmd(1);
break;
}
else if(cnt==3)
{
state=5;
lcd_wrcmd(1);
break;
}
else if(cnt==4) //help
{
state=4;
lcd_wrcmd(1);
break;
}
}
else if(ii==1)
{
state=2;
lcd_wrcmd(1);
break;
}
else if(ii==2)
{
state=3;
lcd_wrcmd(1);
break;
}
else if(ii==3)
{
state=5;
lcd_wrcmd(1);
break;
}
else if(ii==4)
{
state=4;
lcd_wrcmd(1);
break;
}
}
}
help()
{
uchar i,ii;
lcd_wrcmd(0x80);
for(i=0;i<16;i++)
{
lcd_wrdata(he[i]);
}
while(1)
{
ii=key_ii();
if(ii!=0xff)
{
lcd_wrcmd(1);
state=1;
break;
}
}
}
main()
{
lcd_bus=0xff;
lcd_ini();
dac_tlc5620(165); //A(LPS)=1.586
rst=1; //f=1KHZ
while(1)
{
if(state==0)welcome();
else if(state==1)menu();
else if(state==2)freq();
else if(state==3)phase();
else if(state==4)help();
else if(state==5)amplitude();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -