📄 测量显示.c
字号:
#include<reg51.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <intrins.h>
#include <stdlib.h>
#include "C:\Documents and Settings\www1\桌面\ouyw\ts128647921chuank\src\TS128647921chuank.h"
#include "C:\Documents and Settings\www1\桌面\ouyw\delaycomm\src\delaycomm.h"
#define uint8 unsigned char
#define int16 int
#define uint16 unsigned int
#define uint32 unsigned long int
#define DELAY1US_M _nop_()
#define _port 0x01 //模似信号输入口
sbit RESET=P3^4; /*复位,高电平有效*/ //AD9851所用端口
sbit wclk=P3^7; /*字输入时钟,上升沿有效*/
sbit fqud=P3^6; /*频率更新端,上升沿将40位控制字送入芯片内*/
#define DATA P2 /*数据端口*/
sbit jian_shuju=P1^2; //串口键盘所用端口
sbit jian_shizhong=P1^1;
sbit yiwei_zhiru=P1^0;
//#define io_janp P1 //行列式键盘所用端口
#define jidianq P0 /*从高到低档用其P1.0,P1.2,P1.3控制继电器换档,高电平有效*/ //档位调节
sbit CLOCK=P1^4; /*2543时钟*/ //AD TCL2543所用端口
sbit D_IN=P1^5; /*2543输入*/
sbit D_OUT=P1^6; /*2543输出*/
sbit _CS=P1^7; /*2543片选*/
sbit xingwjx=P3^1; /*相位极性判断*/ //测相位大小极性所用端口
sbit xiangwsy=P3^2; /*相位大小判断*/
sbit io_LCDsid = P3^0; /*串行数据输入端 */ //液晶显示所用端口
sbit io_LCDsclk = P3^5; /*串行同步时钟端 */
float _Y,_G,_B; //导纳模,电导,电纳
int16 pingl,xiangweij; //频率,向位角
int16 xshu; //辅助显示数据
uint8 dianx; //辅助显示小数点
uint8 o; //辅助测量周期
float hudu; //辅助计算电导G,电纳B
bit b_pduan=1; //判断有无键按下
//ad9851 ini AD9851并口置数函数
/***********************************************************
功能:用来辅助测量周期
说明:
*************************************************************/
void TIMER(void) interrupt 0
{
TR0=~TR0; //下降沿中断计数,第二次中断则关计数器
++o;
}
/***********************************************************
功能:控制AD9851输出波形的相位及频率
说明:输入存有5个字节控制字的首地址,依次对应控制字为W0,W1,W2,W3,W4.
*************************************************************/
void v_DDSkongz_f(uint8 data *u8c_xiansyh_p)
{
uint8 i;
wclk=0; /*先将wclk清零,以便置高时获得上升沿*/
fqud=0; /*将fqud清零*/
DELAY1US_M; /*延时*/
//fqud=1; /*fqud上升沿控制40位控制字进入DDS核心,因为前面没有输入控制字,所以此上升沿的目的是将地址指针指向第一个输入寄存器*/
//DELAY1US_M; /*延时*/
//fqud=0; /*将fqud清零*/
for(i=0;i<5;i++) /*发送40位控制字数据,由w_clk控制进入输入寄存器*/
{
DATA=u8c_xiansyh_p[i]; /*发送一个控制字数据*/
DELAY1US_M; /*延时*/
wclk=1; /*w_clk置高,上升沿使得控制字进入输入寄存器*/
DELAY1US_M; /*延时*/
wclk=0; /*w_clk清零*/
DELAY1US_M; /*延时*/
}
fqud=1; /*fqud置高,上升沿使得40位控制字进入DDS核心*/
DELAY1US_M; /*延时*/
DELAY1US_M;
fqud=0; /*将fqud清零*/
}
/******************************
math DATA
功能:将输入的频率值转换到w[1]~w[4]控制字中
说明:输入频率值
*********************************/
uint32 math_phase(uint32 FIN)
{
float datafloat;
//datafloat=((float)FIN)*4294967296/132710400;
datafloat=((float)FIN)*65536/2025; //外部晶振22.1184MHz,开启6倍频
return (uint32)datafloat;
}
/*****************************************************
dujsj
功能:串口键盘扫描并返回键值
说明:有键按下时返回键值无键按下时返回255
********************************************************/
uint8 dujsj(uint8 xinpian) //读键数据
{
uint8 dizhi[5],i,j,fan;
yiwei_zhiru = 0;
yiwei_zhiru = 1; //锁存端口数据
if(jian_shuju == 0) i=0;
else
{
for(i=1;i<8;i++)
{
jian_shizhong = 0;
jian_shizhong = 1;
if(jian_shuju == 0)break;
}
}
dizhi[0] = i; //读入第一块芯片数据
for(j=1;j<xinpian;j++)
{
for(i=0;i<8;i++)
{
jian_shizhong = 0;
jian_shizhong = 1;
if(jian_shuju==0) break;
}
dizhi[j] = i;
}
for(j=0;j<xinpian;j++)
{
if(dizhi[j] != 8)
{
fan = dizhi[j]+j*8;break;
}
fan=0xff;
}
return fan;
}
/********************************************************************
anjiansz_f
功能:设定各按键功能
说明:
*************************************************************************/
void anjiansz_f(unsigned char key)
{
switch(key)
{
case 0:pingl=100;break; //100Hz
case 1:pingl=300;break; //300Hz
case 2:pingl=1000;break; //1KHz
case 3:pingl=3000;break; //3KHz
case 4:pingl=10000;break; //10KHz
case 5:pingl+=100;break; //以100Hz步进
case 6:pingl-=100;break; //以100Hz步减
case 7:break;
case 8:break;
case 9:break;
case 10:break;
case 11:break;
case 12:break;
case 13:break;
case 14:break;
case 15:break;
}
}
/*******************************************
功能:输入要显示的导纳模,或电导,电纳值转换为可显示的值
说明:shuju范围:0.01~100之间
数据以mS为单位
*********************************************/
//int16 xshu; //辅助显示用
//uint8 dianx;
void shujuxs_f(float shuju)
{
if(shuju<0.09) {xshu=(int16)(1000*shuju);dianx=3;}
else
{xshu=(int16)(100*shuju);dianx=2;}
}
/*******************************************
功能:输入要显示的频率,相位,导纳模,电导,电纳值将其显示出来
说明:范围:频率范围:0Hz~32767Hz
相位-90度~90度
导纳0.01~100之间以mS为单位
*********************************************/
void xianYReIm_f(int16 pl,int16 xiangw,float Y,float Re,float Im)
{
v_LcdWriteNumber_f(0x03,5,pl);
v_LcdWriteChar_f(0x00,"f=");
v_LcdWriteNumber_f(0x07,5,xiangw);
v_LcdWriteChar_f(0x04,"Hz");
v_LcdWriteChar_f(0x05,"φ");
if(xiangw<=-10) v_LcdWriteChar_f(0x06,"=-");
else v_LcdWriteChar_f(0x06,"= ");
shujuxs_f(Y);
v_LcdWriteCharOneLine_f(0x90,"导纳模: mS");
v_LcdWriteNumber_f(0x16,dianx,xshu);
v_LcdWriteChar_f(0x13,": ");
shujuxs_f(Re);
v_LcdWriteCharOneLine_f(0x88," 电导: mS");
v_LcdWriteNumber_f(0x26,dianx,xshu);
v_LcdWriteChar_f(0x23,": ");
shujuxs_f(Im);
v_LcdWriteCharOneLine_f(0x98," 电纳: mS");
v_LcdWriteNumber_f(0x36,dianx,xshu);
v_LcdWriteChar_f(0x33,": ");
}
/**************************************
名称:read2543
功能:TLC2543驱动模块
输入参数:port通道号
输出参数:返回上次ad转换好的值
注意:第一次转换的数据为随机一般无意义
*************************************/
int16 read2543_f()
{
uint8 port=_port;
int16 ad=0;
uint16 i;
CLOCK=0;
_CS=1;
DELAY1US_M;
_CS=0;
port<<=4;
for(i=0;i<12;i++)
{
ad<<=1;
if(D_OUT) ad|=0x01;
D_IN=(bit)(port&0x80);
CLOCK=1;
DELAY1US_M;
CLOCK=0;
DELAY1US_M;
port<<=1;
}
_CS=1;
return(ad);
}
/**************************************************
功能:自动调节测量档位
说明:输入使用A/D TLC2543测量电路的port通道号
返回所造档位值,1,2,3,4
1为最高大档
4为最小档
***************************************************/
uint8 dangwkz_f()
{
uint8 i,j;
int16 jieshouAD;
jidianq&=0x10; //断开四个继电器
jidianq|=0x01; //接通第一个继电器(最大档)
i=10;
while(--i)
jieshouAD=read2543_f();//延时并且刷新A/D值
if(jieshouAD>=409&&jieshouAD<=4095) j=1;
else
{
jidianq&=0x10; jidianq|=0x02; //接通第二档
i=10;
while(--i)
jieshouAD=read2543_f();//延时并且刷新A/D值
if(jieshouAD>=409&&jieshouAD<4095) j=2;
else
{
jidianq&=0x10; jidianq|=0x04; //接通第三档
i=10;
while(--i)
jieshouAD=read2543_f();//延时并且刷新A/D值
if(jieshouAD>=409&&jieshouAD<4095) j=3;
else
{
jidianq&=0x10; jidianq|=0x08; //接通第四档
i=10;
while(--i)
jieshouAD=read2543_f();//延时并且刷新A/D值
if(jieshouAD>=409&&jieshouAD<4095) j=4;
}
}
}
return(j);
}
/*************************************************************
功能:计算导纳模|Y|
说明:输入使用A/D TLC2543测量电路的port通道号与档位号j
返回计算后的导纳模值|Y|
**************************************************************/
float daonaY_f(uint8 j)
{
int16 code R[4]={27,270,2700,27000};
float y;
int16 jieshouAD;
jieshouAD=read2543_f(); //A/D转换后的结果
// y=(float)jieshouAD*2*(2.7/4096)*1.414/R[j]/1; //Ipp=2*1.414*jieshouAD*(2.7/4096)/R[j] ,Upp=1V
// y=(float)jieshouAD*(2.7/4096)*1.414*2/R[j];
y=(float)jieshouAD*0.001864441/R[j];
return(y);
}
/**************************************************
功能:测量相位角
说明:用的是T0带选通控制位,返回相位角
*****************************************************/
void xiangweicl_f(void)
{
uint16 tim,zhouqi;
int16 i=1;
/**********测相位************/
IE=0x00; //关中断
TCON=0x00;
TMOD=0x09; //INT0=1且TR0=1时计时工作方式1(16位计数)
TH0=0x00;
TL0=0x00;
while(INT0);
TR0=1; //准备计时
while(!INT0);
while(INT0);
TR0=0; //停止计数
if(xingwjx==0) i=-1; //判断频率的正负值
tim=TH0; //取相位差
tim<<=8;
tim+=TL0;
/**********测周期************/
o=0;
TH0=0x00;
TL0=0x00;
TCON=0x01;
TMOD=0x01; //TR0=1时计时工作方式1(16位计数)
IE=0x81; //开外部中断
while(o!=2);
IE=0x00;
zhouqi=TH0;//取周期值
zhouqi<<=8;
zhouqi+=TL0;
hudu=(float)tim*3.14159265/zhouqi*i; //相位角弧度制表示
xiangweij=(int16)(tim*180.0/zhouqi)*i;//相位角度数
}
/******************************************************************
功能:求相位角,导纳,电导与电纳
分别存入全局变量xiangweij,_Y,_G,_B中
*******************************************************************/
void qiuGB_f(void)
{
_Y=daonaY_f(dangwkz_f());
xiangweicl_f(); //测量相位角
_G=_Y*cos(hudu);
_B=_Y*sin(hudu);
}
/*******************************************************************
主函数
********************************************************************/
main()
{
uint8 data *p;
uint32 q,fin;
uint8 j,key=255,shong=0;
uint8 w[5];
const uint8 code kaicjm1[][16]={" 欢迎进入 ","网络导纳测试仪! "," ^-^ **** ^-^ "," 按任意键进入 "};
const uint8 code kaicjm[][16]={"0:100 1:300 ","2:1K 3:3K 4:10K ","5:+100 6:-100 ","7:设置频率值(Hz)"};
v_LcdWriteCharIni_f();//对12864初始化
DELAY1US_M;
v_LcdWriteCharScreen_f(kaicjm1);
do{key=dujsj(2);} while(key==255);
v_LcdWriteCharScreen_f(kaicjm); //输出介面,请求输入频率
do{key=dujsj(2);} while(key!=255);
do
{
while(key!=7)
{
do{key=dujsj(2);} while(key==255);
anjiansz_f(key);
v_WriteIns_f(0x01); //清屏
v_LcdWriteCharOneLine_f(0x80,"频率为: ");
v_LcdWriteNumber_f(0x06,5,pingl); //显示设定频率值
v_LcdWriteChar_f(0x07,"Hz");
v_LcdWriteCharOneLine_f(0x88,"设定完成请按07键");
v_DelayX10ms_f(30);
//do{shong=dujsj(2);} while(shong!=255); //松键确认
}
// v_LcdWriteCharOneLine_f(0x88," 频率设定完成 ");
//控制DDS输出设定的频率
fin=(uint32)pingl;
q=math_phase(fin);
p=&q;
w[0]=1;
for(j=1;j<5;j++)
w[j]=*p++;
RESET=1; //使AD9851复位
v_DelayX10ms_f(1); // 延时10ms
RESET=0; // RESET清零
v_DDSkongz_f(&w); // 调用写入5个字节控制字子程序
v_DelayX10ms_f(1); //延时10ms
v_LcdWriteCharOneLine_f(0x88," 频率已送输出 ");
//***************************************
// qiuGB_f(); //求相位角,导纳,电导与电纳分别存入全局变量xiangweij,_Y,_G,_B
// v_WriteIns_f(0x01); //清屏
// xianYReIm_f(pingl,xiangweij,_Y,_G,_B); //显示
// v_LcdWriteCharOneLine_f(0x88," 测量完成 ");
//xianYReIm_f(220,-90,0.012,0.12,100); //显示
do{key=dujsj(2);} while(key==255); //判断有无按键,重新设置频率进行测量
}
while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -