?? ctr_pi.txt
字號:
//加定時器已完成 現在的采樣頻率為32Hz
//主體部分已經完成,Ka已經計算正確,給P2端口賦值能正確顯示,但通過Ka給P2傳遞
//增益時,P2輸出亦正確,調整PI算法已調整,振級表是使用自己編寫的一個,P0輸出
//正確了(實施辦法是將P0賦值位置提前就解決了)
///更改pI算法后的原程序
#include<stdio.h>
#include<aduc842.h>
#include<math.h>
#define KP 0.5//暫定Kp=5
#define KI 0.5//暫定Ki=5
sfr templ=0x86;
sfr temph=0x85;
void DELAY(int length);
void adc_chan(int chan);// 選擇通道
void adc_ini();
void adc_start();
void config();
void uart_ini();
void dac_ini();
void port_ini();
//void TIC_ini();
//void TIC_start();
void readval();//讀取AD轉換值并轉為10進制數子函數
void pi();//PI算法子程序
float Lookuptab(unsigned char voltab);//查表子程序
int K;
int Kout=0;//將K值進行翻轉準備輸出到P2口
int xdata num[8];//用作暫時存儲K值以便今后進行翻轉方便
int xdata i;
int Ka;
int tempval;
float code Table[6]={1.0,2.0,3.0,4.0,5.0,6.0};//自己暫定的振級表,可以根據實際值修改
float UDA;//UDA為DAC0輸出
float UIK=0;//UI的初值設為0
float xdata MK1;//該值為上一次采樣保存的電壓值
float xdata MK2;//該值為新采樣保存的電壓值
float RK;
float EK;
float UPK;
float UK;
int xdata level1;
int xdata level2;
void adc_int() interrupt 6 //ADC轉換完,進入中斷
{
I2CCON=0x0C8;//燈滅
DELAY(2000);
I2CCON=0x048;//燈亮
temph=ADCDATAH;
templ=ADCDATAL;//轉換值暫存到temp中
ADCI = 0;//可要可不要,如果不進入ADC中斷,則須用戶手動清零
return;
}
/*void TIC_int () interrupt 10
{
TIMECON=0x00;
I2CCON=0x048;
DELAY(2000);
printf("TIC finished\n");//去掉warning請注釋此句
IEIP2 = 0x00;//關TIC中斷
}
*/
void adc_chan(int chan)
{
ADCCON2 = chan;
}
void adc_ini()
{
ADCCON1 = 0x02C; // 暫停AD
EA = 0; // 中斷不使能
EADC = 0; // ADC中斷不使能
}
void adc_start()
{
ADCCON1 = 0x0AC; // 啟動AD,使用內部參考電壓
EA = 1; // 中斷使能
EADC = 1; // ADC中斷使能
}
void config()
{
CFG842 = 0x41; //暫定
PLLCON = 0x03; //工作頻率=2.097152 MHz
}
void uart_ini() //串口初始化
{
T3CON = 0x083;
T3FD = 0x02D;
SCON = 0x052;
}
void dac_ini()
{
DACCON = 0x0D;//DAC0 12位異步 0-Cref=5v
//DACCON = 0x2D;//DAC0 12位異步 0-Vdd
}
void port_ini()//根據需要設置AD7520增益值
{
P0&=0x00;//
P2|=0x00;
//P2|=0x64;//0110,0100
//P2|=0xC4;//1110,0101
}
/*void TIC_ini() //定時器初始化
{
TIMECON = 0x00;
INTVAL = 0x00;
HTHSEC=0x00;
}
void TIC_start() //定時器開始計時,中斷間隔為4*(1/128)=31.25ms,注意要在TCEN為低的時候給
{ //INTVAL和HTHSEC賦值,再開TIC中斷,全局中斷,最后置TCEN開始計時
TIMECON = 0x0A;//0000,1010
INTVAL = 0x04;
HTHSEC=0x00;
IEIP2 = 0xA4;//TIC中斷使能
EA = 1;
TIMECON|=0x01;//啟動TIC
}
*/
void readval()
{
tempval=(int)temph*256;//強制轉換為整形數
tempval+=(int)templ;//此時計算的是十進制的AD結果,比如若temph:templ=03ff,則對應于1023
}
float Lookuptab(unsigned char voltab)
{
return Table[voltab];
}
void pi()
{
//UDA=5;//UDA為方便計算設置的一個變量
//UK=UDA;//調試時先可直接把Uk=5v來計算,等到完成后在應用下面的PI算法
DELAY(500);
if(level2 == 0) {RK=Lookuptab(0);}
else if(level2 == 1) {RK=Lookuptab(1);}
else if(level2 == 2) {RK=Lookuptab(2);}
else if(level2 == 3) {RK=Lookuptab(3);}
else if(level2 == 4) {RK=Lookuptab(4);}
else {RK=Lookuptab(5);}//這段程序目的是查表確定振動的給定參考值以便與采集來的數據比較
while((RK-MK2)>0.1)
{
adc_start();
SCONV = 1; //開始一次轉換
DELAY(1000); //調延遲,等待轉換完畢
if (ADCI == 0) //中斷處理完畢標志,進行輸出
{
//printf("temph=%02BX,templ=%02BX\n",temph,templ);//串口輸出轉換值
//printf("UIK=%f\n",UIK);
readval();
DELAY(500);
MK2=(float)tempval*5/4096;//必須強制轉換為浮點數,否則結果不對
EK=RK-MK2;
UPK=KP*EK;
UIK=KI*EK+UIK;
UK=UPK+UIK;
K=(UK/UDA*1024);//現將()內表達式的值取整,此值處理后即為送往AD7520的增益值,
Ka=K>>2;//因為電路板上低兩位已拉高,所以只需要高8位
//Ka&=0x00FF;//只用了低八位
//Ka = 0x0064;//為測試方便
MK1 = MK2;
level1 = level2;
}
}
}
void main(void)//主程序開始
{
DELAY(100);
config();
adc_ini();
adc_chan(0);
uart_ini();
dac_ini();
port_ini();
//DELAY(2000);
//TIC_ini();
//DELAY(2000);
P0&=0x00;//如果要調整P0口增益值,則打開此句
printf("P0=%02BX\n",P0);
//DELAY(2000);
P0|=0xFF;//第一級AD7520增益先設為不放大,即放大倍數為(1023/1024)
//DELAY(2000);
printf("P0=%02BX\n",P0);
//printf("UIK=%f\n",UIK);
DAC0H=0x0F;
DAC0L=0xFF;//AC0輸出恒值5v
//i=0;
//adc_start();
//SCONV = 1; //啟動AD轉換
/////////////////初始化
for (i=0;i<8;i++)
{
num[i] = 1;
}
level1 = 1;//初始設定等級為等級1
MK1=1.1;//初始設定值為1.1v
RK=Lookuptab(1);//查等級為1的參考表,設定RK值
EK=RK-MK1;
UPK=KP*EK;
UIK=KI*EK+UIK;
UK=UPK+UIK;
UDA = 5.0;
K = UK/UDA*1024;
Ka = K>>2;
//Ka = 0x0064;//0110,0100 用于測試用,并不是實際值
//////////////////////////////初始化完成
while(1){ //連續進行AD轉換
//TIC_start();
adc_start();
SCONV = 1; //開始一次轉換
DELAY(1000); //調延遲,等待轉換完畢
if (ADCI == 0) //中斷處理完畢標志,進行輸出
{
printf("temph=%02BX,templ=%02BX\n",temph,templ);//串口輸出轉換值
printf("UIK=%f\n",UIK);
readval();
DELAY(500);
MK2=(float)tempval*5/4096;//必須強制轉換為浮點數,否則結果不對
if(0<MK2&MK2<=1) {level2 = 0;}
else if(1<MK2&MK2<=2) {level2 = 1;}
else if(2<MK2&MK2<=3) {level2 = 2;}
else if(3<MK2&MK2<=4) {level2 = 3;}
else if(4<MK2&MK2<=5) {level2 = 4;}
else {level2 = 5;}//這段程序目的是查表確定振動的給定參考值以便與采集來的數據比較
if (level2!=level1)
pi();
printf("MK1=%f\n",MK1);
printf("MK2=%f\n",MK2);
printf("RK=%f\n",RK);
printf("EK=%f\n",EK);
printf("UPK=%f\n",UPK);
printf("UIK=%f\n",UIK);
printf("UK=%f\n",UK);
printf("K=%04X\n",K);
printf("Ka=%04X\n",Ka);
printf("num[0]=%d\n",num[0]);
//printf("gkg %d\n",sizeof(K));
/////將Ka值進行翻轉并輸出到P2口
//方法一
num[0]=Ka&0x01;
num[1]=Ka&0x02;
num[2]=Ka&0x04;
num[3]=Ka&0x08;
num[4]=Ka&0x10;
num[5]=Ka&0x20;
num[6]=Ka&0x40;
num[7]=Ka&0x80;
for (i=0;i<8;i++)
{
if (num[i]==pow(2,i))
num[i]=1;
else num[i]=0;
}
//方法二
/*
for (i=0;i<8;i++)
{
Ka = Ka>>i;
num[i]=fmod(Ka,2);
}
*/
Kout = 0;
for (i=0;i<8;i++)
{
Kout +=pow(2,(7-i))*num[i];
}
P2 =Kout; //本應該為此句,再次利用下句做以簡單替代用于測試
//P2|=Ka;//正式給端口賦值,產生AD7520增益
//P2^=Ka;//正式給端口賦值,產生AD7520增益
DELAY(500);
printf("P2=%02BX\n",P2);//顯示P2口置位是否正確
printf("num[0]=%d\n",num[0]);
printf("num[1]=%d\n",num[1]);
printf("num[2]=%d\n",num[2]);
printf("num[3]=%d\n",num[3]);
printf("num[4]=%d\n",num[4]);
printf("num[5]=%d\n",num[5]);
printf("num[6]=%d\n",num[6]);
printf("num[7]=%d\n\n",num[7]);
DELAY(1000);
}
}
}
void DELAY(int length)//延遲函數
{
while (length >=0)
length--;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -