?? pic2448.c
字號(hào):
#include "pic1687x.h" //包含頭文件
#include "pic.h"
__IDLOC(15F0);
__CONFIG(HS&WDTDIS&LVPDIS&DUNPROT); //高速晶振,禁止低電壓編程,看門狗禁止,禁止代碼保護(hù)
//__CONFIG(HS&WDTEN&LVPDIS&DUNPROT); 高速晶振,禁止低電壓編程,看門狗允許,禁止代碼保護(hù)
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define bitset(var,bitno) ((var)|=1<<(bitno)) //位置位
#define bitclr(var,bitno) ((var)&=~(1<<(bitno))) //位清零
#define bitchk(var,bitno) (var&(0x01<<(bitno))) //位測試
#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit)) //取得位地址
#define bits_on(var,mask) ((var)|=(mask)) //置位對應(yīng)位
#define bits_off(var,mask) ((var)&=~0^(mask)) //清零對應(yīng)位
#define bittst_on(data,bitno) ((data>>bitno)&0x01)
#define hibyte(x) (unsigned char)(x>>8) //取高8位
#define lobyte(x) (unsigned char)(x & 0xFF) //取低8位
#define _NOP_ asm("NOP")
// 以下是口定義
#define ADR_ID RA4 // 地址編碼
#define SHUT0 RB0 // 模塊關(guān)機(jī)控制
#define SHUT1 RB1
#define SHUT2 RB2
#define SHUT4 RB4
#define SHUT5 RB5
#define SHUT3 RC0
#define VSET RC3 // 模塊狀態(tài)比較電壓控制
#define RLSW RC4 // 輸出繼電器控制
#define EN485 RC5 // 485 收發(fā)轉(zhuǎn)換
#define GIN1 RD6 // 通用輸入
#define GIN2 RD7
#define SIO_RX_LEN 6
#define SIO_TX_LEN 10
#define RCT_CUR_RANG 400 /* 1023 -- 40.0 A */
uchar ticks=0,secs=0,norx_secs=0;// 50ms,秒,無通信計(jì)時(shí)定義
uchar img_RCSTA; // 寄存器影像
uchar img_RCREG;
uchar sio_tx_num; // 發(fā)送字節(jié)數(shù)
uchar sio_rx_num; // 接收字節(jié)數(shù)
bank1 uchar sio_rx_buf[SIO_RX_LEN]; // 接收緩沖區(qū)
bank1 uchar sio_tx_buf[SIO_TX_LEN];
ulong cpu3;
uchar id_addr=0; //模塊組地址
uchar rct_addr=0; //模塊地址
uint ad_vol_set; // 調(diào)壓輸出測量值
uint pwm_vol_set; // PWM調(diào)壓輸出(0-1023)
uint pwm_cur_lmt; // PWM限流輸出(0-1023)
uint vol_set; // 調(diào)壓輸出設(shè)置值(0-1023)
uint cur_lmt; // 限流輸出設(shè)置值(0-1023)
uchar rct_pow; // 整流器關(guān)機(jī)
uchar rct_warn; // 整流器告警
uchar rct_no=0xff; // 整流器在位
bank1 uint rct_cur[6]; // 整流器電流
bank1 uint ibuf[9]; // AD采樣數(shù)組
#define CUR_MAX 4000
#define DCV_MAX 6062
uint cur_nc=1023;
uint cur_pc=1023;
uint DC_F=900;
uint DC_J=900;
bit change=0;
#define RCT_CUR_RANG_15B 200 // A/D 1023 -- 20A
#define RCT_CUR_RANG_20D 370 // A/D 1023 -- 37A
#define RCT_CUR_RANG_25D 400 // A/D 1023 -- 40A
#define RCT_CUR_RANG_30D 500 // A/D 1023 -- 50A
#define DCV_MAX_24V 3031 // D/A 24V
#define DCV_MAX_48V 6062 // D/A 48V
#define DCV_MID 3500 // 24V與48V的分界值:35V
#define CUR_MAX_15B 2000 // D/A 15Aor10A
#define CUR_MAX_20D 3700 // D/A 30Aor40A
#define CUR_MAX_25D 4000 // D/A 25A
#define CUR_MAX_30D 5000 // D/A 30Aor40A
uchar cur_type = 0; // 模塊電流類型
uchar flag_cfg = 0; // 0:需要配置模塊類型 1:模塊類型配置完成
void delay(uchar t) // 延時(shí)子程序
{
uchar s;
s = 0;
while(t--)
while(--s)
{
_NOP_;
_NOP_;
_NOP_;
_NOP_;
_NOP_;
_NOP_;
_NOP_;
_NOP_;
_NOP_;
CLRWDT();
}
}
uchar bittest(uchar var,uchar bitno) //位測試
{
if((var>>bitno)&0x01==1)
return 1;
else
return 0;
}
uchar bittest0(uchar var,uchar bitno) //位測試
{
if((var>>bitno)&0x01==1)
return 1;
else
return 0;
}
void delay_100us(uchar times) // 延時(shí)100us
{
TMR0 = 1;
T0IF = 0;
while(times--)
{
while(!T0IF);
T0IF = 0;
}
}
void wr_eeprom(uchar addr,uchar val) // 內(nèi)部EEPROM寫入(地址,數(shù)值)
{
EECON1=0;
while(WR);
EEADRH=0;
EEADR=addr;
EEDATA=val;
EEPGD=0;
WREN=1;
di();
EECON2=0X55;
EECON2=0XAA;
WR=1;
while(WR);
WREN=0;
ei();
}
uchar rd_eeprom(uchar addr) // 內(nèi)部EEPROM讀出(地址),返回?cái)?shù)據(jù)
{
uchar val;
EECON1=0;
EEADRH=0;
EEADR=addr;
EEPGD=0;
RD=1;
asm("NOP");
val=EEDATA;
return val;
}
uint start_ad(uchar chn) // 啟動(dòng)指定通道的AD轉(zhuǎn)換,換回AD數(shù)值
{
uint adres;
ADCON1 = 0x81; /* Result Right_justified, 7 A/D channels, Vref = RA3 - VSS */
chn &= 7;
chn <<= 3;
chn |= 0b10000001; /* set Fosc/32 clock, AD channel,AD operating on */
ADCON0 = chn;
delay_100us(1);
ADGO = 1; /* Start AD */
while(ADGO);
asm("NOP");
asm("NOP");
adres=ADRESH*256+ADRESL;
return adres;
}
uint start_channel(uchar ad_chn) // 對指定通道進(jìn)行AD轉(zhuǎn)換,換回AD數(shù)值(內(nèi)含數(shù)值濾波)
{
uchar t;
uint sum;
uint ad_max,ad_min;
for(t=0;t<9;t++) // 采樣9次(大約20ms)
{
ibuf[t] = start_ad(ad_chn);
delay_100us(20);
}
ad_max = ad_min = ibuf[0]; // 求出9次采樣最大值,最小值
for(t=1;t<9;t++)
{
if(ibuf[t] < ad_min)
ad_min = ibuf[t];
else if(ibuf[t] > ad_max)
ad_max = ibuf[t];
}
for(t=0,sum=0;t<9;t++) // 求排除最大值,最小值之外的7個(gè)數(shù)的平均值
sum += ibuf[t];
sum -= ad_max;
sum -= ad_min;
sum /= 7;
return sum;
}
void start_measure()
{
static uchar rct_cur_channel;
ulong ad_result;
rct_cur_channel++; // 開始:測量一路模塊電流(一次只測一次)
rct_cur_channel %= 6;
if(rct_cur_channel<3)
ad_result = start_channel(rct_cur_channel);
else
ad_result = start_channel(rct_cur_channel+1);
switch (cur_type)
{
case 15: // 15Bor10D
{
ad_result *= RCT_CUR_RANG_15B;
ad_result>>= 10;
if (ad_result > RCT_CUR_RANG_15B) // 防止超界
ad_result = 0;
break;
}
case 20: // 20D
{
ad_result *= RCT_CUR_RANG_20D;
ad_result>>= 10;
if (ad_result > RCT_CUR_RANG_20D) // 防止超界
ad_result = 0;
break;
}
case 25: // 25D
{
ad_result *= RCT_CUR_RANG_25D;
ad_result>>= 10;
if (ad_result > RCT_CUR_RANG_25D) // 防止超界
ad_result = 0;
break;
}
case 30: // 30Dor40D
{
ad_result *= RCT_CUR_RANG_30D;
ad_result>>= 10;
if (ad_result > RCT_CUR_RANG_30D) // 防止超界
ad_result = 0;
break;
}
default: // 若未配置模塊類型
{
ad_result = 0; // 則AD轉(zhuǎn)換結(jié)果=0
break;
}
}
//l *= RCT_CUR_RANG;
//l /= 1024;
di();
rct_cur[rct_cur_channel] = (uint)ad_result;
ei(); // 結(jié)束:測量一路模塊電流
ad_result = start_channel(7); // 測量電壓控制輸出值
di();
ad_vol_set = (uint)ad_result;
ei();
}
uint uiabs_sub(uint i, uint j) // 無符號(hào)整數(shù)絕對值減法
{
if(i>j)
return i-j;
else
return j-i;
}
uchar ucabs_sub(uchar i, uchar j)// 無符號(hào)字節(jié)絕對值減法
{
if(i>j)
return i-j;
else
return j-i;
}
/**************************************************************
重要提示:
下面函數(shù)計(jì)算與調(diào)整輸出電壓
目的:消除7805供電電壓,16F877與運(yùn)放等電路產(chǎn)生的輸出誤差
此函數(shù)很重要:因?yàn)榭刂齐妷盒盘?hào)與模塊輸出電壓有12倍增益關(guān)系,
不同模控板之間0.1V的輸出壓差將造成不均流現(xiàn)象。
函數(shù)對設(shè)定值的設(shè)定調(diào)整范圍:正負(fù)50(實(shí)際試驗(yàn)正負(fù)10)
***************************************************************/
#define DIF_ZERO 128
#define MAX_DIF_ERR 25
#define MAX_ITG_ERR 51
void calcu_vol_set_pwm() // 計(jì)算與調(diào)整輸出電壓
{
static uchar err_itg; // 電壓控制信號(hào)
uchar t;
uint i;
if(uiabs_sub(vol_set,ad_vol_set) > 2*MAX_DIF_ERR)// 計(jì)算設(shè)定于采樣的誤差是否大于50
{
err_itg = DIF_ZERO; // 誤差積分清0
if(ad_vol_set < vol_set) // PWM數(shù)值步進(jìn)MAX_DIF_ERR調(diào)整
pwm_vol_set = (pwm_vol_set > 1023-MAX_DIF_ERR)?1023:pwm_vol_set+MAX_DIF_ERR;
else
pwm_vol_set = (pwm_vol_set < MAX_DIF_ERR)?0:pwm_vol_set-MAX_DIF_ERR;
}
else // 計(jì)算誤差積分
{
err_itg = (err_itg > DIF_ZERO+2*MAX_DIF_ERR)?DIF_ZERO+2*MAX_DIF_ERR:err_itg;
err_itg = (err_itg < DIF_ZERO-2*MAX_DIF_ERR)?DIF_ZERO-2*MAX_DIF_ERR:err_itg;
if(ad_vol_set < vol_set)
err_itg -= (uchar)(vol_set - ad_vol_set);
else
err_itg += (uchar)(ad_vol_set - vol_set);
t = ucabs_sub(DIF_ZERO,err_itg)/MAX_ITG_ERR;// 計(jì)算積分誤差調(diào)整值,增益1/25(經(jīng)驗(yàn)數(shù)值,
// 此值過大,過小都引起系統(tǒng)輸出電壓震蕩,)
if(t) // 根據(jù)調(diào)正量修正PWM輸出
{
if(err_itg < DIF_ZERO)
pwm_vol_set = (pwm_vol_set>1023-t)?1023:pwm_vol_set+t;
else
pwm_vol_set = (pwm_vol_set<t)?0:pwm_vol_set-t;
}
}
if(uiabs_sub(vol_set,pwm_vol_set) > 2*MAX_DIF_ERR)// 修正范圍超出50,按照最大正負(fù)50調(diào)整
{
if(vol_set > pwm_vol_set)
{
if(vol_set < 2*MAX_DIF_ERR)
i = 0;
else
i = vol_set - 2*MAX_DIF_ERR;
}
else
{
if(vol_set > 1023 - 2*MAX_DIF_ERR)
i = 1023;
else
i = vol_set + 2*MAX_DIF_ERR;
}
di();
pwm_vol_set = i;
ei();
}
}
void calcu_cur_lmt_pwm() // 計(jì)算限流輸出
{
di();
pwm_cur_lmt = cur_lmt; // 無修正,按照設(shè)定數(shù)值輸出(原因:限流精度要求不高,正負(fù)0.1足以)
ei();
}
void set_pwm_out() // 設(shè)定PWM輸出
{
CCP1X = (pwm_vol_set&0x02)?1:0;
CCP1Y = (pwm_vol_set&0x01)?1:0;
CCPR1L = pwm_vol_set/4;
CCP2X = (pwm_cur_lmt&0x02)?1:0;
CCP2Y = (pwm_cur_lmt&0x01)?1:0;
CCPR2L = pwm_cur_lmt/4;
}
void pow_process() // 關(guān)機(jī)處理
{
if(rct_pow&0x01) SHUT0 = 1;
else SHUT0 = 0;
if(rct_pow&0x02) SHUT1 = 1;
else SHUT1 = 0;
if(rct_pow&0x04) SHUT2 = 1;
else SHUT2 = 0;
if(rct_pow&0x08) SHUT3 = 1;
else SHUT3 = 0;
if(rct_pow&0x10) SHUT4 = 1;
else SHUT4 = 0;
if(rct_pow&0x20) SHUT5 = 1;
else SHUT5 = 0;
}
void get_warn_status() // 獲得模塊狀態(tài)
{
uchar t;
//di();
VSET = 0; // 設(shè)模塊狀態(tài)比較值1.67V
TRISD =0b11111111; /* PORT_D as input */
_NOP_;
_NOP_;
_NOP_;
_NOP_;
delay(1);
t = PORTD; // 獲模塊在位信號(hào)
if((t&1)==0)
rct_cur[0] = 0;
if((t&2)==0)
rct_cur[1] = 0;
if((t&4)==0)
rct_cur[2] = 0;
if((t&8)==0)
rct_cur[3] = 0;
if((t&16)==0)
rct_cur[4] = 0;
if((t&32)==0)
rct_cur[5] = 0;
rct_no=t&0x3F; // 獲模塊在位信號(hào)
VSET = 1; // 設(shè)模塊狀態(tài)比較值3.3V
TRISD =0b11111111; /* PORT_D as input */
_NOP_;
_NOP_;
_NOP_;
_NOP_;
delay(1);
t = PORTD;
rct_warn = t&0x3F; // 獲模塊告警信號(hào)
_NOP_;
_NOP_;
//ei();
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -