📄 yuanma.c
字号:
//===================================================================================
// 基于单片机的DDS频率综合器
//
//===================================================================================
#include <AT89X52.h>
#define LCM_RW P3_0 //定义LCD引脚
#define LCM_RS P3_1
#define LCM_E P3_2
#define LCM_Data P0
#define Key_Data P3_4 //定义Keyboard引脚
#define Key_CLK P3_3
#define DDS_Word P1 //定义DDS控制字接口
#define RESET_9851 P2_2
#define W_CLK P2_1
#define FQ_UD P2_0
#define predefine 131 //2^32除以DDS晶振频率(32.768MHz)
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void Decode(unsigned char ScanCode);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM);
void UpdateData(void);
void UpdateScale(void);
void UpdateLCM(void);
void UpdateDDS(void);
unsigned char code num[] = {"0123456789"};
unsigned char disp_freq[16];
static unsigned char IntNum = 0; //中断次数计数
static unsigned char KeyV; //键值
static unsigned char BF=0; //标识是否有字符被收到
static unsigned long freq=0;
static unsigned long word=0;
int i;
/*----------------------------------主程序-------------------------------*/
void main()
{
Delay400Ms(); //启动等待,等LCM讲入工作状态
LCMInit(); //LCM初始化
LCMInit();
LCMInit();
DisplayListChar(0,0,"Xiang Fei");
Delay5Ms(); //延时
// InitDDS(); //向DDS送入初设值
IT1 = 0; //设外部中断1为低电平触发
EA = 1;
EX1 = 1; //开中断
i=0;
while(1)
{
do
{
if (BF)
{
if (i==0)
{
WriteCommandLCM(0x01); //清屏
break;
}
else break;
}
}while(1);
EA=0;
UpdateData();
if ((KeyV==0x42) || (KeyV==0x3A) || (KeyV==0x5A)) //按下"K","M","Enter"更新频率
{
UpdateScale();
word=predefine*freq; //计算频率控制字
UpdateDDS(); //更新DDS function to be completed
freq=0; //清空数据缓冲区
i=0;
}
else
{
i++;
UpdateLCM(); //更新LCD显示
}
BF=0; //按键标志归零
EA=1; //重新开中断
}
}
/*---------------------------------函数-----------------------------------*/
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高可以在这后加小的延时
Delay5Ms();
LCM_E = 0; //延时
LCM_E = 1;
}
//写指令
void WriteCommandLCM(unsigned char WCLCM)
{
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
Delay5Ms();
LCM_E = 0;
LCM_E = 1;
}
void LCMInit(void) //LCM初始化
{
LCM_Data=0;
WriteCommandLCM(0x38); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38);
Delay5Ms();
WriteCommandLCM(0x38);
Delay5Ms();
WriteCommandLCM(0x38); //显示模式设置,开始要求每次检测忙信号
Delay5Ms();
WriteCommandLCM(0x08); //关闭显示
Delay5Ms();
WriteCommandLCM(0x01); //显示清屏
Delay5Ms();
WriteCommandLCM(0x06); // 显示光标移动设置
Delay5Ms();
WriteCommandLCM(0x0C); // 显示开及光标设置
Delay5Ms();
}
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y&=0x1;
X&=0xF; //限制X不能大于15,Y不能大于1
if (Y) X|=0x40; //当要显示第二行时地址码+0x40;
X|=0x80; //算出指令码
WriteCommandLCM(X); //发命令字
WriteDataLCM(DData); //发数据
}
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;
ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x19) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}
//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
}
}
void Keyboard_out(void) interrupt 2
{
if ((IntNum > 0) && (IntNum < 9))
{
KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位
if (Key_Data) KeyV = KeyV | 0x80; //当键盘数据线为1时为1到最高位
}
IntNum++;
while (!Key_CLK); //等待PS/2CLK拉高
if (IntNum > 10)
{
IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
BF = 1; //标识有字符输入完了
EA = 0; //关中断等显示完后再开中断
}
}
void UpdateData(void)
{
switch (KeyV)
{
case 0x45: // 按下"0"
freq=freq*10+0;
disp_freq[i]='0';
break;
case 0x16: // 按下"1"
freq=freq*10+1;
disp_freq[i]='1';
break;
case 0x1E: // 按下"2"
freq=freq*10+2;
disp_freq[i]='2';
break;
case 0x26: // 按下"3"
freq=freq*10+3;
disp_freq[i]='3';
break;
case 0x25: // 按下"4"
freq=freq*10+4;
disp_freq[i]='4';
break;
case 0x2E: // 按下"5"
freq=freq*10+5;
disp_freq[i]='5';
break;
case 0x36: // 按下"6"
freq=freq*10+6;
disp_freq[i]='6';
break;
case 0x3D: // 按下"7"
freq=freq*10+7;
disp_freq[i]='7';
break;
case 0x3E: // 按下"8"
freq=freq*10+8;
disp_freq[i]='8';
break;
case 0x46: // 按下"9"
freq=freq*10+9;
disp_freq[i]='9';
break;
case 0x42: // 按下"K"
freq=freq*1000;
break;
case 0x3A: // 按下"M"
freq=freq*1000000;
break;
}
}
void UpdateScale(void)
{
DisplayOneChar(14,0,'H');
DisplayOneChar(15,0,'z');
switch (KeyV)
{
case 0x42:
DisplayOneChar(13,0,'K');
break;
case 0x3A:
DisplayOneChar(13,0,'M');
break;
case 0x5A:
break;
}
}
void UpdateLCM(void)
{
int j;
for(j=0;j<i;j++)
{
DisplayOneChar(16-i+j,1,disp_freq[j]);
}
}
void UpdateDDS(void)
{
int j;
unsigned char CON[5];
RESET_9851=0;
RESET_9851=1;
RESET_9851=0;
FQ_UD=0;
CON[0]=0x00;
for(j=4;j>0;j--)
{
CON[j]=word;
word=word>>8;
}
for(j=0;j<5;j++)
{
W_CLK=0;
DDS_Word=CON[j];
W_CLK=1;
}
FQ_UD=1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -