资源描述
/*1 、可通过按键实现频率输出步进加减;步进频率范围010MHz;2、步进值有七种选择:1HZ,10Hz、100Hz、1000Hz、10KHz、100KHz、1000KHz3、采用1602液晶显示屏,可以实时显示输出频率值,显示当前步进值,显示频率的单位都为Hz。*/基本功能全部实现;2011/8/9#include reg52.h /调用头文件(单片机内部的寄存器定义)#include intrins.h#define uchar unsigned char#define uint unsigned int/*本段为硬件I/O口定义*/sbit LCD_E = P27;/定义1602液晶的使能管脚;sbit LCD_RW = P26;/定义1602液晶的读写管脚; sbit LCD_RS = P25;/定义1602液晶的选通管脚; sbit reset = P20; /ad9850的复位引脚;sbit w_clk = P21; /ad9850的时钟引脚;sbit fqud = P22; /ad9850的输出更新引脚;sbit bit_data= P30;#define LCD_DATA P0 /向1602液晶传送数据的端口,这里用的是P1口;#define LCD_BUSY 0x80 / 用于检测LCD的忙标识(本程序中用的是延时,未检测) /LCD显示内容,定义到代码段;unsigned char code LcdBuf1= FRQ: Hz;unsigned char code LcdBuf2= SETP:;/unsigned char code LcdBuf3=wei wen bo ;/unsigned char code LcdBuf4=15177684256;double Con_Word_1 = 0x00;/定义了一个浮点变量,用于计算控制字;double Con_Word_2 = 0x00;/定义了一个浮点变量,用于计算控制字;long uint control_word = 0x00;/用来存储控制字的数值;long uint Frequency_Out;/设置的频率值;uchar a,b,c,d,e,f,g,h; /为了向1602写入频率值,首先将频率值拆分存于这8个变量中;sbit Light = P32; /程序状态指示灯,它与单片机对9850控制无关,只是调试程序的时候使用!/*定义按键;2X3矩阵键盘;sbit P1_0 = P10;sbit P1_1 = P11;sbit P1_2 = P12;sbit P1_3 = P13;sbit P1_4 = P14;sbit P1_5 = P15;sbit P1_6 = P16;sbit P1_7 = P17;*/ uchar dat = 0;/键盘子程序处理过程中使用的中间变量;uchar keyzhi = 0x00;/键值;键盘扫描子程序的返回值存于该变量中;/函数声明void lcd_init(void);/1602液晶初始化子程序;void display_string(unsigned char x,unsigned char y,unsigned char *s);/显示字符子程序;x、y是坐标;x:从左边数起第几个字符:y:是第一行还是第二行; /* 函数名称: delay* 入口参数:z(int型)* 出口参数:无* 功能描述: 延时,使用11.0592晶体,1MS*/void delay(uint z) uint x,y; for(x=z;x0;x-) for(y=111;y0;y-);/* 函数名称: WriteDataLcd* 入口参数:wdata(unsigned char型)* 出口参数:无* 功能描述: 写数据到LCD*/void WriteDataLcd(uchar date)/向1602液晶写入数据; LCD_RS=1; LCD_RW=0; LCD_E=0; LCD_E=1; LCD_DATA=date; delay(2); /短暂延时,代替检测忙状态 LCD_E=0;/* 函数名称: WriteCommandLcd* 入口参数:wdata(unsigned char型)* 出口参数:无* 功能描述: 写命令到LCD*/void WriteCommandLcd(uchar com)/向1602液晶写入命令; LCD_RS=0; LCD_RW=0; LCD_E=0; LCD_E=1; LCD_DATA=com; delay(2); /短暂延时,代替检测忙状态 LCD_E=0; /LCD初始化void lcd_init(void) LCD_DATA = 0; delay(10); WriteCommandLcd(0x38); delay(5); WriteCommandLcd(0x38); /显示模式设置 delay(5); WriteCommandLcd(0x38); /显示模式设置 delay(5); WriteCommandLcd(0x01); /关闭显示 WriteCommandLcd(0x08); /显示清屏 WriteCommandLcd(0x0c); /光标不显示 WriteCommandLcd(0x06); /显示开及光标移动设置 /WriteCommandLcd(0x1c); /屏幕左移 /* 函数名称: display_xy* 入口参数:x(unsigned char型),y(unsigned char型)* 出口参数:无* 功能描述: 设置光标位置, x是行号,y是列号*/void display_xy(unsigned char x,unsigned char y) if(y=0x01) x = x + 0x40 + 0x80; else x = x+0x80; WriteCommandLcd(x);/* 函数名称: display_string* 入口参数:x(unsigned char型),y(unsigned char型),s(指针型)* 出口参数:无* 功能描述: 在具体位置显示字符串,以/0结束,x是列号,y是行号*/void display_string(unsigned char x,unsigned char y,unsigned char *s) display_xy(x,y); while(*s) WriteDataLcd(*s); s+; Qu_Chu_Shu_Ma_Ge_Wei() /取出要显示的每一位数据; a = Frequency_Out % 10; b = (Frequency_Out % 100)/10; c = (Frequency_Out % 1000)/100; d = (Frequency_Out % 10000)/1000; e = (Frequency_Out % 100000)/10000; f = (Frequency_Out % 1000000)/100000; g = (Frequency_Out % 10000000)/1000000; h = (Frequency_Out % 100000000)/10000000; display_data() /显示数据子程序Qu_Chu_Shu_Ma_Ge_Wei();/取出要显示的每一位数据;display_string(1,0,LcdBuf1);/显示第一行,从第2个位置开始WriteCommandLcd(0x85);/显示数值的话,用其真实的地址,如0x83等,WriteDataLcd(0x30+h); /如果要显示字符的话,暂时用x、y坐标的方式WriteDataLcd(0x30+g);/以下都是送显示数据;WriteDataLcd(0x30+f);WriteDataLcd(0x30+e);WriteDataLcd(0x30+d);WriteDataLcd(0x30+c);WriteDataLcd(0x30+b);WriteDataLcd(0x30+a); scan_KEY(void) /键值处理子程序 uchar key; key=P1; switch(key) case 0xee: keyzhi=1;break; / 1110 1110 case 0xde: keyzhi=2;break; / 1101 1110 case 0xbe: keyzhi=3;break; / 1011 1110 case 0x7e:keyzhi=4;break; / 0111 1110 case 0xed: keyzhi=5;break; / 1110 1101 case 0xdd: keyzhi=6;break; / 1101 1101 case 0xbd: keyzhi=7;break; / 1011 1101 case 0x7d:keyzhi=8;break; / 0111 1101 case 0xeb: keyzhi=9;break; / 1110 1011 case 0xdb: keyzhi=10;break; / 1101 1011 case 0xbb: keyzhi=11;break; / 1011 1011 case 0x7b:keyzhi=12;break; / 0111 1011 case 0xe7: keyzhi=13;break; / 1110 0111 case 0xd7:keyzhi=14;break; / 1101 0111 case 0xb7: keyzhi=15;break; / 1011 0111 case 0x77:keyzhi=16;break; / 0111 0111 default:keyzhi=0;break; return (keyzhi);keychuli()/键盘扫描子程序 uchar row,col; P1=0xf0; if(P1&0xf0)!=0xf0) /判断有无按下 delay(10); if(P1&0xf0)!=0xf0) /再次判断 row=0xfe; /得到行 dat = scan_KEY(); while(row&0x10)!=0) /用来判断是否移位过头 P1=row; if(P1&0xf0)!=0xf0) col=(P1&0xf0)|0x0f; /得到列 dat = scan_KEY(); return(row&col); /得出列(高四位)行(低四位) else row=row1|0x01; /移位用于判断在哪行 else return 0; void ad9850_reset_serial() /复位AD9850w_clk=0;fqud=0;/reset信号reset=0;reset=1;reset=0;/w_clk信号w_clk=0;w_clk=1;w_clk=0;/f_qud信号fqud=0;fqud=1;fqud=0;Calculate_control_word(long uint Frequency_Out) Con_Word_1 = Frequency_Out * 34; /125M FSW=fo*232/fc Con_Word_2 = Frequency_Out *0.35973836; /小数部分 / Con_Word_1 = Frequency_Out * 42;/100M / Con_Word_2 = Frequency_Out *0.94967296; Con_Word_2 = Con_Word_2 + 0.5;/小数部分四舍五入; Con_Word_1 = Con_Word_1 + Con_Word_2; /根据设定的频率以浮点形式计算控制字 control_word = Con_Word_1 / 1;/将控制字换算成整数形式 void write_control_word(long uint control_word ) uchar i; fqud = 0; w_clk = 0; for(i=0;i 1; fqud = 1; w_clk = 0; delay(20); fqud = 0; main() uchar i = 0x00; uint Step_Bian_Liang = 0;/步进变量; long uint Step_Data = 100;/默认为100Hz; long unsigned int Step_Data_Xian_Shi = 0x00; ad9850_reset_serial(); /复位AD9850; delay(10); lcd_init(); /初始化子程序; Frequency_Out = 100;/开机默认的频率输出值为100; Calculate_control_word(Frequency_Out);/根据设置的频率换算成将要送入AD9850中的整数值; write_control_word(control_word); /向AD9850送出频率控制字; display_data();/显示数据; display_string(0,1,LcdBuf2); /显示第二行,从第0个位置开始; WriteCommandLcd(0xc5);/从第二行第六个开始显示数据; WriteDataLcd(0x30+(Step_Data/1000);/送出显示数据; WriteDataLcd(0x30+(Step_Data/100)%10);/送出显示数据; WriteDataLcd(0x30+(Step_Data/10)%10);/送出显示数据; WriteDataLcd(0x30+(Step_Data%10);/送出显示数据; display_string(9,1,Hz);/显示Hz; while(1) keychuli();/键处理子程序 if(dat = 1)/键值为1;步进加 dat = 0;delay(50); Frequency_Out = Frequency_Out + Step_Data; if(Frequency_Out 10000000) Frequency_Out = Frequency_Out - Step_Data; Light =Light; display_data(); ad9850_reset_serial(); /复位AD9850; delay(5); /使AD9850进入正常的工作状态; Calculate_control_word(Frequency_Out);/根据设置的频率换算成将要送入AD9850中的整数值;write_control_word(control_word); /向AD9850送出频率控制字; if(dat = 4)/键值为4;步进减 dat = 0;delay(50); if(Frequency_Out = Step_Data) Frequency_Out = Frequency_Out - Step_Data; Light =Light; display_data(); ad9850_reset_serial(); /复位AD9850; delay(10); Calculate_control_word(Frequency_Out);/根据设置的频率换算成将要送入AD9850中的整数值; write_control_word(control_word); /向AD9850写入频率控制字; if(dat = 6)/步进选择;这里有三种选择 dat = 0;delay(50);Light =Light; Step_Bian_Liang+; Step_Bian_Liang = Step_Bian_Liang%7; if(Step_Bian_Liang = 0) Step_Data = 1;/步进1; if(Step_Bian_Liang = 1) Step_Data = 10;/步进10; if(Step_Bian_Liang = 2) Step_Data = 50; if(Step_Bian_Liang = 3) Step_Data = 100; if(Step_Bian_Liang = 4) Step_Data = 500; if(Step_Bian_Liang = 5) Step_Data = 1000; if(Step_Bian_Liang = 6) Step_Data = 10000; if(Step_Data=1000) WriteCommandLcd(0xc5);/参考上面类似的部分 WriteDataLcd(0x30+(Step_Data/1000); WriteDataLcd(0x30+(Step_Data/100)%10); WriteDataLcd(0x30+(Step_Data/10)%10); WriteDataLcd(0x30+(Step_Data%10); display_string(9,1,Hz ); else Step_Data_Xian_Shi = Step_Data/1000; WriteCommandLcd(0xc5);/参考上面类似的部分 WriteDataLcd(0x30+(Step_Data_Xian_Shi/1000); WriteDataLcd(0x30+(Step_Data_Xian_Shi/100)%10); WriteDataLcd(0x30+(Step_Data_Xian_Shi/10)%10); WriteDataLcd(0x30+(Step_Data_Xian_Shi%10); display_string(9,1,kHz); delay(10); if(dat=5) dat=0;delay(50);Light=Light;break;
展开阅读全文