📄 ad.c
字号:
// 该程序用于进行A/D转换的演示,A/D转换的结果存于数足ADRESULT[16]中,
// 寄存器cesi用于测试每个A/D转换的结果
#include "register.h"
int i=0X00,ADIa[32],ADUa[32];
//#pragma DATA_SECTION(ADUa,".stack");
//int ADUa[32]={611,707,796,873,937,984,1013,1023,1013,984,937,873,796,707,611,512,412,
// 316,227,150,86,39,10,0,10,39,86,150,227,316,412,512};
int ADIa[32]={707,796,873,937,984,1013,1023,1013,984,937,873,796,707,611,512,412,
316,227,150,86,39,10,0,10,39,86,150,227,316,412,512,611};
//int ADUa1[16]={512,708,874,985,1023,985,874,708,512,316,150,39,0,39,150,316};
//int ADIa1[16]={512,708,874,985,1023,985,874,708,512,316,150,39,0,39,150,316};
unsigned int Iaxzh=710,Uaxzh=665,IaAv,UaAv,UaAv1,UbAv,Ubxzh=665;
unsigned int Ua_d,Ua3,Ua5,Uaxsh=938,Iaxsh=997,Ua1,Ia1,bianyaqi=75; //对fft计算结果的校验系数;
int adpoint=0;
long P,Q,S,P1,Q1,S1;
unsigned int Factor;
int output1[64],output2[64];
/******************和FFT计算,调用有关的参数及常数列表*****************/
#define N 32
extern void fft(void);
extern void resave();
extern int nom; /*when nom=1, FFT implement normalization*/
extern int input[64]; /*input data */
int indati[32]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int indatr[32];/*={0,6807,10755,10947,8838,6838,6368,7039,
499,7039,6368,6838,8838,10947,10755,6807,
0,-6807,-10755,-10947,-8838,-6838,-6368,-7039,
-7499,-7039,-6368,-6838,-8838,-10947,-10755,-6807
};*/
/*={ 17500,15354,10915,4887,1767,1139,1517,1251,
0,-1251,-1517,-1139,-1767,-4887,-10915,-15354,
-17500, -15354,-10915,-4887,-1767,-1139,-1517,-1251,
0,1251,1517,1139,1767,4887,10195,15354}; */
int sintab[N]={ 0x7FFF,0x0000,0x7D89,0xE708,0x7640,0xCF05,0x6A6C,0xB8E4,
0x5A81,0xA57F,0x471C,0x9594,0x30FB,0x89C0,0x18F8,0x8277,
0x0000,0x8001,0xE708,0x8277,0xCF05,0x89C0,0xB8E4,0x9594,
0xA57F,0xA57F,0x9594,0xB8E4,0x89C0,0xCF05,0x8277,0xE708,
};
/*****************************************************************
** 函数名: Xiebo()
** 功能描述:根据fft计算结果计算各相电压3次、5次谐波的模值
** 作 者:严利平
** 日 期:2003年1月12日
****************************************************************/
void Xiebo()
{ unsigned int i;
unsigned long data;
for(i=0;i<=63;i++)
input[i]=0;
for(i=0;i<32;i++)
indatr[i]=ADUa[i]-0x01FF;
resave();
fft();
for(i=0;i<=63;i++)
output1[i]=input[i];
for(i=0;i<=63;i++)
input[i]=0;
for(i=0;i<32;i++)
indatr[i]=ADIa[i]-0x01ff;
resave();
fft();
data=input[2]*input[2]+input[3]*input[3]; //计算基波
data=qsqrt(data);
Ia1=(unsigned int)((data*Iaxsh)>>9);
for(i=0;i<=63;i++)
input[i]=0;
for(i=0;i<32;i++)
indatr[i]=ADIa[i];
resave();
fft();
for(i=0;i<=63;i++)
output2[i]=input[i];
P1=(output1[2])*(output2[2])+(output1[3])*(output2[3]);
Q1=(output1[3])*(output2[2])-(output1[2])*(output2[3]);
P1=(P1*Iaxsh)>>7;
P1=(P1*Uaxsh)>>6;
P1=P1/100;
Q1=(Q1*Iaxsh)>>7;
Q1=(Q1*Uaxsh)>>6;
Q1=Q1/100;
asm(" nop");
return;
}
// 屏蔽中断子程序
void inline disable()
{
asm(" setc INTM");
}
// 开总中断子程序
void inline enable()
{
asm(" clrc INTM");
}
// 系统初始化子程序
void initial()
{
asm(" setc SXM"); // 符号位扩展有效
asm(" clrc OVM");//累加器中结果正常溢出
asm(" clrc CNF"); // B0被配置为数据存储空间
SCSR1=0x83FE; // CLKIN=10M,CLKOUT=4*CLKIN=40M
WDCR=0x0E8; // 不使能看门狗,因为SCSR2中的WDOVERRIDE
// 即WD保护位复位后的缺省值为1,故可以用
// 软件禁止看门狗
IMR=0x0001; // 允许INT1中断
IFR=0x0FFFF; // 清除全部中断标志,"写1清0"
PBDATDIR=0x0FF00; // IOPB端口设置为输出方式
PADATDIR=PADATDIR&0x0FFEF; // IOPA4=0
PADATDIR=PADATDIR|0x1010; // IOPA4 设置为输出方式,且IOPA4=1
PADATDIR=PADATDIR&0x0FFEF; // IOPA4=0
}
// AD初始化子程序
void ADINIT()
{
T4CNT=0X0000; // T4计数器清0
T4CON=0X170C; // T4为连续增计数模式,128分频,且选用内部时钟源
T4PR=0X59; // 设置T4的周期寄存器 ,0.625ms中断一次
GPTCONB=0X400; // T4周期中断标志触发AD转换
EVBIFRB=0X0FFFF; // 清除EVB中断标志,写"1"清0
ADCTRL1=0X10; // 采样时间窗口预定标位ACQ PS3-ACQ PS0为0,
// 转换时间预定标位CPS为0,AD为启动/停止模式,排
// 序器为级连工作方式,且禁止特殊的两种工作模式
ADCTRL2=0X8405; // 可以用EVB的一个事件信号触发AD转换,
// 且用中断模式1
MAXCONV=0X0F; // 16通道
CHSELSEQ1=0X3210;
CHSELSEQ2=0X7654;
CHSELSEQ3=0X0BA98;
CHSELSEQ4=0X0FEDC; // 转换通道是0-15
}
// 启动AD转换子程序(通过启动定时器4的方式间接启动)
void ADSOC()
{
T4CON=T4CON|0X40; // 启动定时器4
}
// 若是其它中断则直接返回子程序
void interrupt nothing()
{
return;
}
/*****************************************************************
** 函数名: Youxiaozhi()
** 功能描述:根据32点采样值计算测量电压、电流有效值
** 作 者:严利平
** 日 期:2003年1月13日
****************************************************************/
void Youxiaozhi()
{ unsigned int j;
unsigned long data,data1,b0,b1,b2,b3,b4,b5,b6,b7;
b0=0; // 求Ua (Uab)的有效值
b1=0;
b2=0;
b3=0;
b4=0;
b5=0;
b6=0;
b7=0;
for(j=0;j<4;j++)
{ b0=b0+(ADUa[j]-0x01FF)*(ADUa[j]-0x01FF);
b1=b1+(ADUa[j+4]-0x01FF)*(ADUa[j+4]-0x01FF);
b2=b2+(ADUa[j+8]-0x01FF)*(ADUa[j+8]-0x01FF);
b3=b3+(ADUa[j+12]-0x01FF)*(ADUa[j+12]-0x01FF);
b4=b4+(ADUa[j+16]-0x01FF)*(ADUa[j+16]-0x01FF);
b5=b5+(ADUa[j+20]-0x01FF)*(ADUa[j+20]-0x01FF);
b6=b6+(ADUa[j+24]-0x01FF)*(ADUa[j+24]-0x01FF);
b7=b7+(ADUa[j+28]-0x01FF)*(ADUa[j+28]-0x01FF);
}
data=((b0>>3)+(b1>>3)+(b2>>3)+(b3>>3))>>2;
data1=((b4>>3)+(b5>>3)+(b6>>3)+(b7>>3))>>2;
data=qsqrt(data+data1);
UaAv=(unsigned int)((data*Uaxzh)>>4);
// UaAv=UaAv*7.33;
b0=0; // 求Ia的有效值
b1=0;
b2=0;
b3=0;
for(j=0;j<8;j++)
{ b0=b0+(ADIa[j]-0x01FF)*(ADIa[j]-0x01FF);
b1=b1+(ADIa[j+8]-0x01FF)*(ADIa[j+8]-0x01FF);
b2=b2+(ADIa[j+16]-0x01FF)*(ADIa[j+16]-0x01FF);
b3=b3+(ADIa[j+24]-0x01FF)*(ADIa[j+24]-0x01FF);
}
data=((b0>>3)+(b1>>3)+(b2>>3)+(b3>>3))>>2;
data=qsqrt(data);
IaAv=(unsigned int)((data*Iaxzh)>>9);
return;
}
/**************************************************************************/
void PowerY()
{ int i,k,k1;
long a0,a1,a2,a3,a4,a5,a6,a7,data;
a0=0; /* 计算Ua*Ia */
a1=0;
a2=0;
a3=0;
a4=0;
a5=0;
a6=0;
a7=0;
for(i=0;i<4;i++)
{
a0=a0+(ADUa[i]-0x01FF)*(ADIa[i]-0x01FF);
a1=a1+(ADUa[i+4]-0x01FF)*(ADIa[i+4]-0x01FF);
a2=a2+(ADUa[i+8]-0x01FF)*(ADIa[i+8]-0x01FF);
a3=a3+(ADUa[i+12]-0x01FF)*(ADIa[i+12]-0x01FF);
a4=a4+(ADUa[i+16]-0x01FF)*(ADIa[i+16]-0x01FF);
a5=a5+(ADUa[i+20]-0x01FF)*(ADIa[i+20]-0x01FF);
a6=a6+(ADUa[i+24]-0x01FF)*(ADIa[i+24]-0x01FF);
a7=a7+(ADUa[i+28]-0x01FF)*(ADIa[i+28]-0x01FF);
}
data=((a0>>5)+(a1>>5)+(a2>>5)+(a3>>5)+(a4>>5)+(a5>>5)+(a6>>5)+(a7>>5));
data=(data*Iaxzh)>>7;
P=(data*Uaxzh)>>6;
// P=(P*bianyaqi)>>10;
P=P/100;
S=UaAv*IaAv;
S=S/100;
Factor=P*100/S;
Q=qsqrt(S*S-P*P); /* 对无符号型长整数开平方 */
a0=0;
k=32;
for(i=0;i<k;i++)
{
k1=k>>2;
if((i+k1)<k)
{
a0=a0+(ADUa[i]-0x01FF)*(ADIa[i+(k>>2)]-0x01FF);
}
else
{k1=(k*3)>>2;
a0=a0+(ADUa[i]-0x01FF)*(ADIa[i-((k*3)>>2)]-0x01FF);
}
}
Q1=(a0*Iaxzh)>>7;
Q1=(Q1*Uaxzh)>>10;
Q1=Q1/100;
S1=(qsqrt((P/100)*(P/100)+(Q1/100)*(Q1/100)))*100;
}
// AD中断服务子程序
void interrupt adINT()
{
asm(" clrc SXM");//抑制符号位扩展
if(adpoint<32)
{
// ADIa[adpoint]=RESULT0>>6;
ADUa[adpoint]=RESULT0>>6;
adpoint++;
}
else
{
Youxiaozhi();
Xiebo();
PowerY();
adpoint=0;
}
ADCTRL2=ADCTRL2|0X4200; // 复位SEQ1,且清除INT FLAG SEQ1标志写"1"清0
enable();//开总中断
return;
}
/************************************************************************/
/************************************************************************/
/*主程序*/
main()
{
disable(); // 禁止总中断
initial(); // 系统初始化
ADINIT(); // AD初始化子程序
enable(); // 开总中断
ADSOC(); // 启动AD转换
while(1)
{
;
} //死循环,在实际的工程应用中在此可以利用A/D转换的结果用于一些运算
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -