📄 pic2448.c
字号:
void ini_hardware(void) // 硬件初始化,相应设置值用英文说明,不明请参考数据手册
{
TRISA =0b00111111; /* PORT_A as input */
TRISB =0b11001000; /* PORT_B as output(except PGD/C/M) */
TRISC =0b11000000; /* PORT_C as output(except TX,RX) */
TRISD =0b11111111; /* PORT_D as input */
TRISE =0b00000111; /* PORT_E as input */
OPTION = 0b11010111; /* TMR0 source CLKOUT, PSA=1:256 assigned to TMR0 */
TMR0 = 0; /* Clear TMR0 & Prescaler */
OPTION = 0b11011111; /* PSA=1:128 assigned to WDT */
CLRWDT(); /* Clears WDT */
OPTION = 0b10001111; /* PORT_B disable pull_ups, TMR0 source CLKOUT, PSA=1:128 assigned to WDT */
T1CON = 0b00110000; /* 1:8 Prescale,internal Fosc/4 clock, stop TMR1 */
TMR1L = (uint)(-17280)%256; /* 11.059M Fosc and 1:8 Prescale, T=50 ms / 2.8935708472737137173342978569491 us */
TMR1H = (uint)(-17280)/256;
TMR1ON = 1; /* restart TMR1 */
T2CON = 0b00000100; /* set 1:1 Prescaler,1:1 Postscale,Timer2 is on */
PR2 = 0xFF;
CCP1CON = 0b00001111; /* ENABLE PWM */
CCP2CON = 0b00001111;
SPBRG=0x08; /* set bps 19200 , 11.059M OSC and low BRG */
TXSTA=0b01000001;
RCSTA=0b11011000;
INTCON = 0b01000000; /* disable GIE,enable PE INT */
PIE1 =0b00100001; /* enable rx,T1 INT, disable tx INT,prevent TXREG empty cause TXIF interrupt */
PIE2 =0b00000000;
ADDEN=1;
TXEN=1;
}
uchar check_rx_frame() // 检查接收帧是否完整
{
uchar i=0;
uint sum=0;
for(i=0;i<=3;i++) //检验加法和
sum+=sio_rx_buf[i];
id_addr=ADR_ID?0x41:0x47; //获得模块组地址
if(sum!=(sio_rx_buf[4]*256+sio_rx_buf[5]))
return 0;
return 1;
}
uchar process_rx_frame() // 接收帧处理,相关命令参照通信协议说明
{
rct_addr=sio_rx_buf[0];
cpu3=sio_rx_buf[2]*256+sio_rx_buf[3];
switch(sio_rx_buf[1])
{
case 0x11: // 查询
{
sio_tx_buf[1]=0x11;
if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5)) //若是本组模块地址
{
sio_tx_buf[2]=(rct_cur[rct_addr-id_addr]*10)/256; //模块电流和温度
sio_tx_buf[3]=(rct_cur[rct_addr-id_addr]*10)%256;
sio_tx_buf[4]=0;
sio_tx_buf[5]=0;
return 1; //进入应答分支
}
else
return 0;
}
case 0x12: // 查询
{
sio_tx_buf[1]=0x12;
if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5)) //若是本组模块地址
{
sio_tx_buf[2]=0; //交流输入电压和模块电压
sio_tx_buf[3]=0;
sio_tx_buf[4]=0;
sio_tx_buf[5]=0;
return 1; //进入应答分支
}
else
return 0;
}
case 0x80: // 设限流 模块充电限流值(2字节)
{
if(rct_addr==0x40)
{
switch (cur_type)
{
case 15: // 15Bor10D
{
cur_pc = (cpu3*1023) / CUR_MAX_15B; // 转换成PWM值
break;
}
case 20: // 20D
{
cur_pc = (cpu3*1023) / CUR_MAX_20D; // 转换成PWM值
break;
}
case 25: // 25D
{
cur_pc = (cpu3*1023) / CUR_MAX_25D; // 转换成PWM值
break;
}
case 30: // 30Dor40D
{
cur_pc = (cpu3*1023) / CUR_MAX_30D; // 转换成PWM值
break;
}
default: // 若模块配置未完成,则充电限流值采用默认值
break;
}// end of switch (rct_type)
cur_lmt=(cur_pc<=cur_nc)?cur_pc:cur_nc;
}
return 0;
}
case 0x81:// 整流器开机 // 设开关机
{
if(rct_addr==0x40)
{
if((sio_rx_buf[2]==0x0f)&&(sio_rx_buf[3]==0x0f))rct_pow=0xff;
}
else
{
if((sio_rx_buf[2]==0x0f)&&(sio_rx_buf[3]==0x0f))
{
if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5)) //若是本组模块地址
rct_pow|=(1<<(rct_addr-id_addr));
}
}
return 0;
}
case 0x82:// 整流器关机 // 设开关机
{
if(rct_addr==0x40)
{
if((sio_rx_buf[2]==0xf0)&&(sio_rx_buf[3]==0xf0))rct_pow=0x00;
}
else
{
if((sio_rx_buf[2]==0xf0)&&(sio_rx_buf[3]==0xf0))
{
if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5)) //若是本组模块地址
rct_pow&=~(1<<(rct_addr-id_addr));
}
}
return 0;
}
case 0x83: // 整流器浮充
{
if(rct_addr==0x40)
{
if((sio_rx_buf[2]==0x0f)&&(sio_rx_buf[3]==0x0f))
change=0;
}
return 0;
}
case 0x84: // 整流器均充
{
if(rct_addr==0x40)
{
if((sio_rx_buf[2]==0xf0)&&(sio_rx_buf[3]==0xf0))
change=1;
}
return 0;
}
case 0x90: //模块浮充电压设置值
{
if (cpu3 <= DCV_MID) // 若为24V系统
DC_F = (cpu3*1023) / DCV_MAX_24V; // 转换成PWM值
else // 若为48V系统
DC_F = (cpu3*1023) / DCV_MAX_48V;
vol_set=change?DC_J:DC_F;
return 0;
}
case 0x91: //模块均充电压设置值
{
if (cpu3 <= DCV_MID) // 若为24V系统
DC_J = (cpu3*1023) / DCV_MAX_24V; // 转换成PWM值
else // 若为48V系统
DC_J = (cpu3*1023) / DCV_MAX_48V;
vol_set=change?DC_J:DC_F;
return 0;
}
case 0x96: // 设限流 模块充电限流值(2字节)最大
{
if(rct_addr==0x40)
{
flag_cfg = 1; // 模块类型配置完成
if(cpu3 <= 1600)cur_type = 15; // 配置模块电流值类型
else if(cpu3 <= 2100)cur_type = 20;
else if(cpu3 <= 2600)cur_type = 25;
else cur_type = 30;
switch (cur_type)
{
case 15: // 15Bor10B
{
cur_nc = (cpu3*1023) / CUR_MAX_15B;
break;
}
case 20: // 20D
{
cur_nc = (cpu3*1023) / CUR_MAX_20D;
break;
}
case 25: // 25D
{
cur_nc = (cpu3*1023) / CUR_MAX_25D;
break;
}
case 30: // 30Dor40D
{
cur_nc = (cpu3*1023) / CUR_MAX_30D;
break;
}
default:
{
flag_cfg = 0; // 需重新配置模块类型
break;
}
}
cur_lmt=(cur_pc<=cur_nc)?cur_pc:cur_nc;
}
return 0;
}
default:
{
return 0;
}
}
}
void send_tx_frame() // 发送返回信息帧
{
uchar i=0;
uint sum=0;
if(bittest(rct_no,rct_addr-id_addr)==0x00)
return ;
//构造发送信息帧
sio_tx_buf[0]=rct_addr;
sio_tx_buf[6]=0;
sio_tx_buf[6]|= ((flag_cfg == 0) || (cur_lmt > 1023)) ? 0x40 : 0x00; // 若需要配置模块类型, 或者模块输出电流超界, 则发送设置值bit=1
//if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5)) //若是本组模块地址
sio_tx_buf[6]|=((bittest(~rct_pow,rct_addr-id_addr))<<0);
sio_tx_buf[6]|=(cur_nc>=1023)?0x40:0x00;
sio_tx_buf[7]=0;
//if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5)) //若是本组模块地址
//sio_tx_buf[7]|=(rct_cur[rct_addr-id_addr]<5)?0x80:0x00;
sio_tx_buf[7]|=((bittest(rct_warn,rct_addr-id_addr))<<7);
if(bittest(~rct_pow,(rct_addr-id_addr)))sio_tx_buf[7]=0;
for(i=0;i<SIO_TX_LEN-2;i++) //校验和
sum+=sio_tx_buf[i];
sio_tx_buf[8]=sum/256;
sio_tx_buf[9]=sum%256;
//构造完毕
EN485 = 0;
sio_tx_num = 0;
TX9D=1;
TXIE = 1;
TXREG = sio_tx_buf[0]; //start send frame 启动发送
sio_rx_num = 0; //restart receive 重启接收
}
void interrupt IntService(void) //中断处理子程序
{
if(TMR1IF) //50 ms 中断处理
{
TMR1IF=0;
TMR1ON=0;
TMR1L = (uint)(-17280)%256; //11.059M Fosc and 1:8 Prescale, T=50 ms / 2.8935708472737137173342978569491 us
TMR1H = (uint)(-17280)/256;
TMR1ON=1;
ticks++;
if(ticks > 19)
{
ticks = 0;
secs++;
norx_secs++;
if(norx_secs > 250)
norx_secs = 250;
if(secs>=59)
{
secs=0;
}
}
}
if((!EN485) && TXIF) //发送中断处理
{
sio_tx_num++;
TX9D=0;
if(sio_tx_num <SIO_TX_LEN+1) //send 1 more invalid byte <<echo_info.sio_tx_buf[SIO_TX_LEN]>>
//insure last TSR send over
{
TXREG = sio_tx_buf[sio_tx_num];
}
else
{
sio_tx_num=SIO_TX_LEN+1;
TXIE = 0;
EN485 = 1;
}
}
while(RCIF) //接收中断处理
{
img_RCSTA = RCSTA;
img_RCREG = RCREG;
if(img_RCSTA & 0x04) //frame error
{
continue;
}
if(img_RCSTA & 0x02) //receive over_run error
{
CREN = 0;
_NOP_;
CREN = 1; //reset CREN
continue;
}
if(sio_rx_num) // 已经开始接收
{
sio_rx_buf[sio_rx_num] = img_RCREG;
sio_rx_num++;
if(sio_rx_num >= SIO_RX_LEN)
{ADDEN=1;
sio_rx_num = 0;
if(check_rx_frame())
{
norx_secs = 0;
if(process_rx_frame())
{
send_tx_frame();
}
}
}
}
else // 未开始接收
{
if((img_RCREG&0xC0)==0x40) // 收到“头“标志
{
sio_rx_buf[0] =img_RCREG;
sio_rx_num = 1;
ADDEN=0;
}
}
}
return;
}
void main()
{
//uchar t;
//uint i,j;
static uchar turn_ticks;
//get_warn_status();
di();
ini_hardware();
EN485 = 1; // set 485 receive
RLSW = 0; // RELAY OFF 继电器脱开,(信号不稳定前,不输出)
rct_pow = 0xff;
pow_process(); // all rect power on 全开机
vol_set = 750;
pwm_vol_set = 750; // out vol 46V 设输出46V
cur_lmt = 1023;
pwm_cur_lmt = 1023; // no out cur limit 无限流
set_pwm_out();
delay(100); // 延时,使控制信号稳定
ticks = 0;
secs = 0;
norx_secs = 0;
sio_rx_num = 0;
sio_tx_num = SIO_TX_LEN + 1;
ei();
RLSW = 1; // RELAY ON 继电器闭合,(信号稳定,输出)
while(1) // 主循环
{
CLRWDT(); // 清看门狗
start_measure(); // 测量模拟量
pow_process(); // 处理关机
get_warn_status(); // 测量模块状态
if(norx_secs > 10) // 无通信超过10秒,继电器脱开,模块电压,电流均不控
RLSW = 0; // RELAY OFF
else
RLSW = 1; // RELAY ON
if(norx_secs >= 240)
{
vol_set=900;
cur_lmt=1023;
rct_pow=0xff;
}
if(turn_ticks != ticks) // 每过50ms
{
turn_ticks = ticks;
calcu_vol_set_pwm(); // 计算调压值
calcu_cur_lmt_pwm();
_NOP_;
set_pwm_out(); // 调整PWM输出
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -