|
楼主 |
发表于 2012-2-18 11:14:09
|
显示全部楼层
接下来就是程序了:
laghi.c
//============
#include <reg51.h>
#include <intrins.h>
#include <stdio.h>
sbit ad9850_bit_data =P1^4; //ad9850的D7脚/PIN25
sbit ad9850_rest =P1^5; //ad9850的rest脚/PIN12
sbit ad9850_fq_up =P1^6; //ad9850的fq_up脚/PIN8
sbit ad9850_w_clk =P1^7; //ad9850的w_clk脚/PIN7
sbit SPK=P3^4; //SPK定义为P3口的第4位,就是驱动蜂鸣器的脚
code unsigned char table[]=
{0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x48,0x5c,
0x00,0x5e,0x76,0x71};
//共阴数码管显示 0-9 a-f 表
code unsigned char key_tab[17]={0xed,0x7e,0x7d,0x7b,
0xbe,0xbd,0xbb,0xde,
0xdd,0xdb,0x77,0xb7,
0xee,0xd7,0xeb,0xe7,0Xff};
//========================此数组为键盘编码,
//Laghi采用类式类似电话按键的编码方式,方便以后设计
// 1 2 3 up 0x01 0x02 0x03 0x0a
// 4 5 6 dn对应16进制码 0x04 0x05 0x06 0x0b
// 7 8 9 M1 0x07 0x08 0x09 0x0d
// *c 0 #ok M1 0x0c 0x00 0x0e 0x0f
//打个比方,如果你按下0键,P0口读到数据为0xed
//如果你按下2键,P0口读到数据为0x7d,按下9键为0xdb,
//将读到的P0口数据经过查表法就能得到相应的16进制码
//键盘的读取,采用中断法,电路用一个4与门(74HC21)接入
//中断口(INT0),利用中断来扫描键盘矩阵,读取数据
//输入数据后按#确认后向ad9850发送控制数据,按*后重新输入频率
unsigned char l_tmpdate[8]={15,11,10,0,0,14,2,12};
//定义数组变量显示:Fo=000Hz
unsigned char l_key=0xff; //定义变量,存放键值
unsigned char l_keyold=0xFF; //做为按键松开否的凭证
unsigned char count_i=0;
unsigned long freq=10000;
void ad9850_reset();//ad9850复位(串口模式)
void ad9850_wr(unsigned char w0,double frequence);
//向ad9850中写命令与数据(串口)//
void diszf();//处理转换给数码管显示字符
void ReadKey(void); //扫描键盘 获取键值
void delay();//延时子函数,5个空指令
void display(unsigned char *lp,unsigned char lc);
//void AD9850_w(unsigned char *lp,unsigned char lc);
//数字的显示函数;lp为指向数组的地址,lc为显示的个数
//==================================================
void main(void) //入口函数
{
EA=1; //首先开启总中断
EX0=1; //开启外部中断 0
IT0=1; // 设置成 下降沿触发方式
P0=0xf0; //P0口高位输高电平,经过74HC21四输入与门,
//连接外中断0,有键按下调用中断函数
P1=0x00;
P2=0x00;
P3=0xff;
//***************************************************//
// 测试程序freqHz频率 //
//---------------------------------------------------//
ad9850_reset();
//ad9850_wr(0x00,1000);//串行写1000Hz频率测试程序
//---------------------------------------------------//
while(1){
display(l_tmpdate,8); //输出获取的键值码
if(l_key==0x01){ //1按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=1;break;
case 2: freq=freq*10+1;break;
case 3: freq=freq*10+1;break;
case 4: freq=freq*10+1;break;
case 5: freq=freq*10+1;break;
case 6: freq=freq*10+1;break;
case 7: freq=freq*10+1;break;
case 8: freq=freq*10+1;break;
}
count_i++;
}
diszf();
}
if(l_key==0x02){ //2按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=2;break;
case 2: freq=freq*10+2;break;
case 3: freq=freq*10+2;break;
case 4: freq=freq*10+2;break;
case 5: freq=freq*10+2;break;
case 6: freq=freq*10+2;break;
case 7: freq=freq*10+2;break;
case 8: freq=freq*10+2;break;
}
count_i++;
}
diszf();
}
if(l_key==0x03){ //3按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=3;break;
case 2: freq=freq*10+3;break;
case 3: freq=freq*10+3;break;
case 4: freq=freq*10+3;break;
case 5: freq=freq*10+3;break;
case 6: freq=freq*10+3;break;
case 7: freq=freq*10+3;break;
case 8: freq=freq*10+3;break;
}
count_i++;
}
diszf();
}
if(l_key==0x04){ //4按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=4;break;
case 2: freq=freq*10+4;break;
case 3: freq=freq*10+4;break;
case 4: freq=freq*10+4;break;
case 5: freq=freq*10+4;break;
case 6: freq=freq*10+4;break;
case 7: freq=freq*10+4;break;
case 8: freq=freq*10+4;break;
}
count_i++;
}
diszf();
}
if(l_key==0x05){ //5按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=5;break;
case 2: freq=freq*10+5;break;
case 3: freq=freq*10+5;break;
case 4: freq=freq*10+5;break;
case 5: freq=freq*10+5;break;
case 6: freq=freq*10+5;break;
case 7: freq=freq*10+5;break;
case 8: freq=freq*10+5;break;
}
count_i++;
}
diszf();
}
if(l_key==0x06){ //6按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=6;break;
case 2: freq=freq*10+6;break;
case 3: freq=freq*10+6;break;
case 4: freq=freq*10+6;break;
case 5: freq=freq*10+6;break;
case 6: freq=freq*10+6;break;
case 7: freq=freq*10+6;break;
case 8: freq=freq*10+6;break;
}
count_i++;
}
diszf();
}
if(l_key==0x07){ //7按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=7;break;
case 2: freq=freq*10+7;break;
case 3: freq=freq*10+7;break;
case 4: freq=freq*10+7;break;
case 5: freq=freq*10+7;break;
case 6: freq=freq*10+7;break;
case 7: freq=freq*10+7;break;
case 8: freq=freq*10+7;break;
}
count_i++;
}
diszf();
}
if(l_key==0x08){ //8按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=8;break;
case 2: freq=freq*10+8;break;
case 3: freq=freq*10+8;break;
case 4: freq=freq*10+8;break;
case 5: freq=freq*10+8;break;
case 6: freq=freq*10+8;break;
case 7: freq=freq*10+8;break;
case 8: freq=freq*10+8;break;
}
count_i++;
}
diszf();
}
if(l_key==0x09){ //9按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=9;break;
case 2: freq=freq*10+9;break;
case 3: freq=freq*10+9;break;
case 4: freq=freq*10+9;break;
case 5: freq=freq*10+9;break;
case 6: freq=freq*10+9;break;
case 7: freq=freq*10+9;break;
case 8: freq=freq*10+9;break;
}
count_i++;
}
diszf();
}
if(l_key==0x00){ //0按键判断
l_key=0xff;
if(count_i && count_i<9){
switch(count_i){
case 1: freq=0;break;
case 2: freq=freq*10;break;
case 3: freq=freq*10;break;
case 4: freq=freq*10;break;
case 5: freq=freq*10;break;
case 6: freq=freq*10;break;
case 7: freq=freq*10;break;
case 8: freq=freq*10;break;
}
count_i++;
}
diszf();
}
if(l_key==0x0a){ //步进按键
l_key=0xff;
freq+=100;
diszf();
ad9850_reset();
ad9850_wr(0x00,freq);//串行写freqHz频率程序
}
if(l_key==0x0b){ //步退按键
l_key=0xff;
freq-=100;
diszf();
ad9850_reset();
ad9850_wr(0x00,freq);//串行写freqHz频率程序
}
if(l_key==0x0c){ //更改按键
l_key=0xff;
count_i=1;
freq=0;
ad9850_reset();
diszf();
}
if(l_key==0x0e){ //确认输出按键
l_key=0xff;
count_i=0;
diszf();
ad9850_reset();
ad9850_wr(0x00,freq);//串行写freqHz频率程序
}
if(l_key==0x0d){ //记忆1按键
l_key=0xff;
count_i=0;
freq=38000000;
diszf();
ad9850_reset();
ad9850_wr(0x00,freq);//串行写freqHz频率程序
}
if(l_key==0x0f){ //记忆2按键,弄个蛙鸣的频率试试
l_key=0xff;
count_i=0;
freq=7023000;
diszf();
ad9850_reset();
ad9850_wr(0x00,freq);//串行写freqHz频率程序
}
}
}//入口函数结束。
void key_scan() interrupt 0 //外部中断 0 0的优先级最高
{
EX0=0; //在读键盘期间,我们关闭中断,防止干扰带来的多次中断
//为了消除抖动带来的干扰,在按下键后我们采用延时十多毫秒再读取键值
//如果采用循环语句来延时,比如(for,while。。。)会使CPU处理循环而占用
//系统资源,所以这里我们采用定时器中断法,让定时器等待十多毫秒触发定时器
//中断,这里用到定时器0
TMOD&=0XF1;//设置定时器0为模式1方式,
TH0=0X2E; //设置初值,为12毫秒
TL0=0X00;
ET0=1; //开启定时器中断0
TR0=1; //启动定时器计数
}
void timer0_isr(void) interrupt 1 //定时器0的中断函数
{
TR0=0; //中断后我们停止计数
ReadKey(); //定时器计数12毫秒后产生中断,调用此函数,
读取键值
}
void ReadKey(void) //读键盘值
{
unsigned char i,j,key;
j=0xfe;
key=0xff; //设定初值
for (i=0;i<4;i++){
P0=j; //P0口低4位循环输出0,扫描键盘
//leday();
if ((P0&0xf0)!=0xf0){ //如果有键按下,P0口高4位不会为1,
key=P0; //读取P0口,退出循环,否则循环下次
break;
}
j=_crol_(j,1); //此函数功能为左循环移位
}
if (key==0xff){ //如果读取不到P0口的值,比如是干扰,我们不做键值处
理,返回
l_keyold=0xff;
//l_key=0xff;
P0=0xf0; //恢复P0口,等待按键按下
EX0=1; //返回之前,开启外中断
SPK=1;
return;
}
// SPK=0; //有键按下,就驱动蜂鸣器响。有干扰就停了
if(l_keyold==key){ //检测按键放开否,如果一样表明没放开,
TH0=0X2E; //继续启动定时器,检测按键松开否
TL0=0;
TR0=1;
return;
}
TH0=0X2E;
TL0=0;
TR0=1; //继续启动定时器,检测按键松开否
l_keyold=key; //获取键码做为放开的凭证
for(i=0;i<17;i++){ //查表获得相应的16进制值存放l_key变量中
if (key==key_tab)
{
l_key=i;
break;
}
}
//程序运行到这里,就表明有键值被读取存放于l_key变量中,
//主程序就可以检测此变量做相应外理,此时我们回到主程序
}
void display(unsigned char *lp,unsigned char lc)//显示
{
unsigned char i; //定义变量
P2=0; //端口2为输出
P1=P1&0xF8; //将P1口的前3位输出0,对应138译门输入脚,全0为第一
位数码管
for(i=0;i<lc;i++)
{ //循环显示
P2=table[lp]; //查表法得到要显示数字的数码段
delay(); //延时5个空指令
if(i==7) //检测显示完8位否,完成直接退出,不让P1口再加1,否
则进位影响到第四位数据
break;
P2=0; //清0端口,准备显示下位
P1++; //下一位数码管
}
}
void diszf()//处理转换给数码管显示字符
{
bit nums=1;
unsigned long tmp;
l_tmpdate[0]=freq/10000000;
tmp=freq/10000000;
if(tmp==0 && nums)l_tmpdate[0]=12;
else {
nums=0; }
tmp=freq%10000000;
l_tmpdate[1]=tmp/1000000;
if(l_tmpdate[1]==0 && nums)l_tmpdate[1]=12;
else {
nums=0; }
tmp=tmp%1000000;
l_tmpdate[2]=tmp/100000;
if(l_tmpdate[2]==0 && nums)l_tmpdate[2]=12;
else {
nums=0; }
tmp=tmp%100000;
l_tmpdate[3]=tmp/10000;
if(l_tmpdate[3]==0 && nums)l_tmpdate[3]=12;
else {
nums=0; }
tmp=tmp%10000;
l_tmpdate[4]=tmp/1000;
if(l_tmpdate[4]==0 && nums)l_tmpdate[4]=12;
else {
nums=0; }
tmp=tmp%1000;
l_tmpdate[5]=tmp/100;
if(l_tmpdate[5]==0 && nums)l_tmpdate[5]=12;
else {
nums=0; }
tmp=tmp%100;
l_tmpdate[6]=tmp/10;
if(l_tmpdate[6]==0 && nums)l_tmpdate[6]=12;
else {
nums=0; }
tmp=tmp%10;
l_tmpdate[7]=tmp%10;
}
//***************************************************//
// ad9850复位(串口模式) //
//---------------------------------------------------//
void ad9850_reset()
{
ad9850_w_clk=0;
ad9850_fq_up=0;
//rest信号
ad9850_rest=0;
ad9850_rest=1;
ad9850_rest=0;
//w_clk信号
ad9850_w_clk=0;
ad9850_w_clk=1;
ad9850_w_clk=0;
//fq_up信号
ad9850_fq_up=0;
ad9850_fq_up=1;
ad9850_fq_up=0;
}
//***************************************************//
// 向ad9850中写命令与数据(串口) //
//---------------------------------------------------//
void ad9850_wr(unsigned char w0,double frequence)
{
unsigned char i,w;
long int y;
double x;//和long int长度一样,但是实验告诉.......
//计算频率的HEX值
x=4294795550/125;//修正频率使之更精确,减小晶振带来的误差
//x=4294967295/125;//适合125M晶振,理论算法
//如果时钟频率不为125MHZ,修改该处的频率值,单位MHz !!!
frequence=frequence/1000000;
frequence=frequence*x;
y=frequence;
//写w4数据
w=(y>>=0);
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//写w3数据
w=(y>>8);
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//写w2数据
w=(y>>16);
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//写w1数据
w=(y>>24);
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//写w0数据
w=w0;
for(i=0;i<8;i++)
{
ad9850_bit_data=(w>>i)&0x01;
ad9850_w_clk=1;
ad9850_w_clk=0;
}
//移入始能
ad9850_fq_up=1;
ad9850_fq_up=0;
}
//================================================
void delay(void) //空5个指令
{
_nop_();_nop_();_nop_();_nop_();_nop_();
} |
评分
-
2
查看全部评分
-
|