/***************************************/ //2008/05/25 cs5463 collect . // alarm 电池电压 /***************************************/ #include #define uchar unsigned char #define uint unsigned int #define SYSCLK 22118400 #define BAUDRATE 2400 #define SAMPLERATE0 50000 //ADC0采样频率 #define VREF0 2908 //VERF电压(mV) #define PWM_MIN 0x0a00 #define PWM_MAX 0xb000 #define VOL_MAX 3000 //电压报警 #define VOL_MIN 1600 #define FRE_MAX 600 //频率报警 #define FRE_MIN 400 #define BAT_MIN 1000 //电池电压报警<=10V static uchar data txcount = 0x00; /*发送字数20*/ static uchar idata rs232tran[20]; static uint data time_count = 0x0000; /*定时*/ static uint data t0high = 0x0000; /*T0液位加1*/ static uchar data cycle = 0x02; static uint xdata frequency = 0x0000; static uint xdata frequencyp = 0x0000; static uint xdata fr_lo = 0x0000; static uint xdata fr_hi = 0x0000; static uchar data int_time; static uint data stop_count = 0x0000; static uint data vol_count = 0x0000; //发电机电压报警 static uint data fre_count = 0x0000; //频率报警 static uint data bat_count = 0x0000; //电池电压报警 static uint data pre_count = 0x0000; //压力报警 static uint data count_tspeed = 0; //开机检测转速,如果超过2400r/min,5秒后进入主程序 static long xdata result[1]; /*传感器输出结果*/ static uint xdata cresult[1]; /*运算输出结果*/ static uchar data num_samples0 = 0; static uchar data num_samples1 = 0; static uint xdata csamples0[20]; static uint xdata csamples1[20]; static long xdata voltage; static uint xdata disp_resultp = 0x00; static uchar data keydata1; static uchar data keydata2; static uchar data keydata3; static uchar data keydata4; static uchar data count5463 = 0; //1.5秒钟内读不到CS5463数据,复位CS5463 static uchar idata cs5463rw[3]={0,0,0}; //cs5463读写寄存器 static uchar idata cs5463tm[3]={0,0,0}; //cs5463读出状态 static long xdata aresult[2]; //cs5463传感器输出结果 static uint xdata acresult[2]; //cs5463运算输出结果,0:voltage 1:current static uint xdata ac_vresult[40]; static uint xdata ac_iresult[40]; static uchar data vi_count = 0; static uchar bdata alm_in = 0x01; /*各种报警信号*/ /***************PID运算*****************/ /***ui = ui1+a0*ei-a1*ei1+a2*ei2*增量式*/ static uint data con_a0; //用内部寄存器 static uint data con_a1; static uint data con_a2; static uint data con_ei; static uint data con_ei1; static uint data con_ei2; static long data con_temp; static long data con_temp1; static uint data con_yk; //static uint data con_givexz; //static uint data disp_vxz; static uint data con_ui1; static uint data con_give; static uint data con_time; //定时100ms输出一次 static uint xdata PWM; /***************************************/ //-------------------------------- sfr16 TMR2RL = 0xca; /*定时器2重载值*/ sfr16 TMR2 = 0xcc; /*定时器2计数值*/ sfr16 TMR3RL = 0x92; /*定时器3重载值*/ sfr16 TMR3 = 0x94; /*定时器3计数值*/ sfr16 ADC0 = 0xbd; /*ADC0数据*/ //--------------------------------- bit right_acb = 0; //right vaule bit stop_mb=0; /*切断发动机点火标志*/ bit stop_mbs=0; /*切断完发动机标志0:没有1:有*/ bit a0_b=0; /*0正 1负*/ bit a1_b=0; bit a2_b=0; sbit alm_in0=alm_in^0; //1:工作正常开始计时 sbit alm_in1=alm_in^1; //机油压力报警 sbit alm_in2=alm_in^2; //电压高报警 sbit alm_in3=alm_in^3; //电压低报警 sbit alm_in4=alm_in^4; //频率高报警 sbit alm_in5=alm_in^5; //频率低报警 sbit alm_in6=alm_in^6; //电池电压报警 sbit alm_in7=alm_in^7; // sbit PWM_OUT = P0^7; /*输出端口引脚*/ sbit oil_pre=P2^0; /*油压报警*/ sbit close_oil=P1^5; sbit reset_5463=P2^3; sbit cs_5463=P2^4; sbit sdi_5463=P2^5; sbit sdo_5463=P2^6; sbit sclk_5463=P2^7; sbit stop_m=P1^6; void SYSCLK_Init (void); void delay1ms(int count); void PORT_Init (void); void PCA_Init(void); void UART0_Init(void); void ADC0_Init(void); void Int0_Init(void); void Timer0_Init(void); void Timer2_Init(void); void Timer3_Init(int counts); void pid_INI(void); void UART0_ISR(void); void ADC0_ISR (void); void Timer0_ISR(void); void Timer2_ISR(void); void Int0_ISR(void); void PCA_ISR(void); void measure_pulsef(void); void measure(void); void pid_control(void); void Hex2Bcd3(uint value); void comm_pro(void); //通讯数据处理 void alarm_symbol(void); void alarm_battery(void); /***********************/ void nop_1us(void); void send_5463(uchar send_data); void write_5463(uchar *pbuf,uchar command); void read_5463(uchar *pbuf,uchar command); void init_5463(void); void drdy_pro(void); //采样程序 /***********************/ void main(void) { pid_INI(); con_yk=1105; while(1) { pid_control(); --con_yk; } PORT_Init (); SYSCLK_Init (); PCA_Init(); UART0_Init(); ADC0_Init(); Int0_Init(); Timer0_Init(); Timer2_Init(); Timer3_Init(SYSCLK/SAMPLERATE0); /*****************/ alm_in = 0x01; acresult[0] = 0x00; acresult[1] = 0x00; restart: right_acb = 0; stop_mb=0; /*切断发动机点火标志*/ stop_mbs=0; /*切断完发动机标志0:没有1:有*/ a0_b=0; /*0正 1负*/ a1_b=0; a2_b=0; close_oil = 1; stop_m = 1; EA = 1; pid_INI(); init_5463(); /****************/ while(!((frequencyp > 400)&&(acresult[0] >= VOL_MIN))) //speed > 2400r/min {drdy_pro();measure();alarm_battery();} count_tspeed = 0; while(!(count_tspeed>500)) //5s {drdy_pro();measure();alarm_battery();} /****************/ while(1) { drdy_pro(); measure(); alarm_symbol(); alarm_battery(); while(stop_mb) //关闭发动机后等待仪表复位 { count_tspeed = 0; while(!(count_tspeed>2000)) //5s { drdy_pro(); measure(); alarm_battery(); } goto restart; } } } void SYSCLK_Init(void) { PSCTL &= 0x00; P0 &= 0xf3; PCA0MD &= ~0x40; OSCXCN = 0x67; //启动外部震荡器22.1184MHZ delay1ms(5); while(!(OSCXCN & 0x80)); CLKSEL = 0x01; } /*延时1ms乘以count*/ void delay1ms(int count) { int j,k; while(count-- != 0) { for(j=0;j<9;j++) for(k=0;k<152;k++) ; } } void PORT_Init (void) { XBR0 = 0x01; /* UART TX0---P0.4 RX0----P0.5*/ XBR1 = 0x41; /* Enable crossbar and weak pull-ups*/ P0SKIP = 0x4f; P1SKIP = 0xff; P2SKIP = 0xff; P0MDIN = 0xf3; P0MDOUT = 0x90; P1MDIN = 0xfe; //p1.0 = ain0.0 P1MDOUT = 0x00; //p1.5 p1.6 out P2MDIN = 0xff; P2MDOUT = 0xfe; P3MDIN = 0x1f; P3MDOUT |= 0x0e; /* enable LED as a push-pull output*/ P3MDOUT &= 0xef; } void PCA_Init(void) { /****看门狗设置****/ PCA0MD &= ~0x40; PCA0MD = 0x08; /*系统时钟*/ PCA0CPL4 = 0x5e; PCA0MD |= 0x40; PCA0CPH4 = 0x00; /*看门狗清零1ms*/ /********************/ //PCA0MD = 0x08; /*08=系统时钟,02=系统时钟/4*/ /********************/ PCA0CPL0 = (0xff & PWM); PCA0CPH0 = (0xff & (PWM >> 8)); PCA0CPM0 = 0x4d; /*CCM0为高速输出方式*/ PCA0CN = 0x40; /*允许PCA计数器*/ EIE1 |= 0x10; /*允许PCA中断*/ } void UART0_Init(void) { rs232tran[0] = 'B'; /*B.b.空格*/ rs232tran[1] = 'b'; rs232tran[19] = 0x0d; SCON0 = 0x50; /*mode0,波特率可编程的8位UART*/ TMOD |= 0x20; /*T0=16为定时。T1=自动重载的8位定时器*/ CKCON |= 0x06; /*T1=SYSCLK/48 T0=SYSCLK*/ CKCON &=~0x80; TH1 = -(SYSCLK/BAUDRATE/96); TL1 = -(SYSCLK/BAUDRATE/96); TR1 = 1; IE |= 0x10; /*start uart0*/ } void ADC0_Init(void) { ADC0CN = 0xc5; REF0CN = 0x02; /*VREF输入引脚作为电压基准*/ ADC0CF = (SYSCLK/2500000)<<3; ADC0CF |= 0x04; /*数据左对齐*/ AMX0N = 0x1f; /*工作在单端方式*/ AMX0P = 0x00; /*以AIN0为ADC多路输出*/ EIE1 |= 0x08; /*允许ADC中断*/ } void Int0_Init(void) { IE |= 0x01; /*启动INT0,边沿*/ TCON |=0x01; IT01CF = 0xf1; /*INT0---P0.1 */ cycle = 0x02; PX0 = 1; } void Timer0_Init(void) { TMOD |=0x01; /*T0=16为定时*/ TR0 = 0; TH0 =0x00; TL0 =0x00; IE |= 0x02; /*启动T0*/ } void Timer2_Init(void) { TMR2CN = 0x04; TMR2 = -(SYSCLK/1200); TMR2RL = -(SYSCLK/1200); IE |= 0x20; /*启动T2=SYSCLK/12 10ms一次中断*/ } void Timer3_Init(int counts) { TMR3CN = 0x00; CKCON |= 0xc0; /*以SYSCLK作为时基*/ TMR3RL = -counts; TMR3 = 0xffff; EIE1 &= ~0x80; TMR3CN |= 0x04; } void pid_INI(void) { con_a0 = 40; //40 con_a1 = 38; //38 con_a2 = 00; //20 con_ei = 0; con_ei1 = 0; con_ei2 = 0; con_yk = 0; con_ui1 = PWM_MIN; con_give = 2205; con_temp = 0; con_temp1 = 0; con_time = 0; PWM = 0xffff-PWM_MIN; } void UART0_ISR(void) interrupt 4 /*串口通信*/ { if (TI0) { TI0 = 0; ++txcount; if(txcount < 20) { SBUF0 = rs232tran[txcount]; } else { txcount = 0x00; } } else{RI0 = 0;} } void ADC0_ISR (void) interrupt 10 { static uchar channel = 0; PCA0CPH4 = 0x00; /*看门狗清零1ms*/ AD0INT = 0; result[channel] = ADC0; AMX0P = channel; } void Timer0_ISR(void) interrupt 1 { t0high += 1; } void Timer2_ISR(void) interrupt 5 { TF2H = 0; //------------------- count5463 += 1; count_tspeed += 1; //------------------- if(!stop_mbs) { if(stop_mb) /*切断点火十五秒*/ { PWM = PWM_MIN; stop_count++; stop_m = 0; if(stop_count == 1500) {stop_count = 0x0000;stop_m = 1;stop_mbs = 1;} } } //------------------- con_time += 1; //------------------- ++vol_count; ++fre_count; ++bat_count; ++pre_count; //-------------------- ++int_time; if(int_time >= 30) //if 300ms no int. display result and control result is zero { int_time = 0x00; frequencyp = 0x00; right_acb = 0; TR0 = 0; cycle = 0x02; t0high = 0x0000; TL0 = 0x00; TH0 = 0x00; } //-------------------- time_count += 1; if(time_count >= 50) { time_count = 0x00; comm_pro(); /*500ms/times to send data*/ txcount = 0x00; SBUF0 = rs232tran[0]; } //-------------------- TMR2 = -(SYSCLK/1200); TMR2RL = -(SYSCLK/1200); } void Int0_ISR(void) interrupt 0 { int_time = 0x00; TR0 = 1; --cycle; if(cycle == 0) { cycle = 2; TR0 = 0; right_acb = 1; /**************************/ fr_lo = TH0*0x100+TL0; fr_hi = t0high; /**************************/ } IE0 = 0; /*避免重复中断*/ } void PCA_ISR (void) interrupt 11 { if (CCF0) { CCF0 = 0; //清除比较标志 if (PWM_OUT){ //处理上升沿 PCA0CPL0 = (0xff & PWM); PCA0CPH0 = (0xff & (PWM >> 8)); } else{ //处理下降沿 PCA0CPL0 = 0; PCA0CPH0 = 0; } } else if (CCF1) { CCF1 = 0; } else if (CCF2) { CCF2 = 0; } else if (CCF3) { CCF3 = 0; } else if (CCF4) { CCF4 = 0; } else if (CF) { CF = 0; } } void measure_pulsef(void) //f<75hz { long xdata high_low; high_low = fr_hi*0x10000+fr_lo; if(high_low > 294912) { frequency = SYSCLK*10/high_low; /*频率有一位小数点*/ } } void measure(void) { long ac_temp0; static uchar n; /**********************************/ voltage = result[0]; voltage = voltage*VREF0; voltage = voltage>>16; /**********************************/ csamples0[num_samples0] = voltage; num_samples0++; if(num_samples0 == 20) { num_samples0 = 0; ac_temp0 = 0; for(n=0;n<20;n++) { ac_temp0 += csamples0[n]; } disp_resultp = ac_temp0/20; } /**********************************/ /*******************************************/ if(right_acb) { EX0 = 0; /***********************/ TH0 = 0; TL0 = 0; t0high = 0; measure_pulsef(); /**********************************/ csamples1[num_samples1] = frequency; num_samples1++; if(num_samples1 == 20) { num_samples1 = 0; ac_temp0 = 0; for(n=0;n<20;n++) { ac_temp0 += csamples1[n]; } frequencyp = ac_temp0/20; } /**********************************/ right_acb = 0; EX0 = 1; } /*******************************************/ } /**********cs5463**********/ /**********cs5463**********/ void send_5463(uchar send_data) //发一个命令字节cs5463 { uchar i; sclk_5463 = 1; for(i = 0;i < 8;i++) { if(send_data & 0x80) sdi_5463 = 1; else sdi_5463 = 0; sclk_5463 = 0; send_data <<= 1; nop_1us(); sclk_5463 = 1; } } void write_5463(uchar *pbuf,uchar command) //*pbuf = h_byte *(pbuf+1) = m_byte *(pbuf+2) = l_byte { uchar j,k; send_5463(command); for(j = 0;j < 3;j++) { sclk_5463 = 1; for(k = 0;k < 8;k++) { if(*pbuf&0x80) sdi_5463 = 1; else sdi_5463 = 0; sclk_5463 = 0; *pbuf <<= 1; nop_1us(); sclk_5463 = 1; } pbuf += 1; } } void read_5463(uchar *pbuf,uchar command) //*pbuf = h_byte *(pbuf+1) = m_byte *(pbuf+2) = l_byte { uchar j,k,const_fe; send_5463(command); for(j = 0;j < 3;j++) { *pbuf = 0x00; const_fe = 0xfe; for(k = 0;k < 8;k++) { sclk_5463 = 0; *pbuf <<= 1; if(sdo_5463) *pbuf |= 0x01; if(const_fe&0x80) sdi_5463 = 1; else sdi_5463 = 0; const_fe <<= 1; nop_1us(); sclk_5463 = 1; } pbuf += 1; } } void init_5463(void) { uchar *temp; sdi_5463 = 0; sclk_5463 = 0; nop_1us(); cs_5463 = 0; reset_5463 = 0; delay1ms(6); reset_5463 = 1; nop_1us(); send_5463(0xff); send_5463(0xff); send_5463(0xff); send_5463(0xff); send_5463(0xff); send_5463(0xff); nop_1us(); send_5463(0xfe); cs5463rw[0] = 0x00; //0X001001 K=1,下降沿,电流放大十倍 cs5463rw[1] = 0x10; cs5463rw[2] = 0x01; temp = &cs5463rw[0]; write_5463(temp,0x40); delay1ms(1); cs5463rw[0] = 0x00; //0X000FA0 N=160 t=40ms cs5463rw[1] = 0x00; cs5463rw[2] = 0x50; temp = &cs5463rw[0]; write_5463(temp,0x4a); delay1ms(1); cs5463rw[0] = 0x00; //0X000061 在线频率测量 cs5463rw[1] = 0x00; cs5463rw[2] = 0x69; temp = &cs5463rw[0]; write_5463(temp,0x64); delay1ms(1); cs5463rw[0] = 0x00; //0X800200 写中断 cs5463rw[1] = 0x00; cs5463rw[2] = 0x00; temp = &cs5463rw[0]; write_5463(temp,0x74); delay1ms(1); cs5463rw[0] = 0x00; //控制 cs5463rw[1] = 0x00; cs5463rw[2] = 0x00; temp = &cs5463rw[0]; write_5463(temp,0x78); delay1ms(1); cs5463rw[0] = 0xff; //清除状态位 cs5463rw[1] = 0xff; cs5463rw[2] = 0xff; temp = &cs5463rw[0]; write_5463(temp,0x5e); delay1ms(1); send_5463(0xe8); //连续测量 } void drdy_pro(void) { uchar *temp; uchar ac_n; temp = &cs5463rw[0]; read_5463(temp,0x1e); //读状态 cs5463tm[0] = cs5463rw[0]; cs5463tm[1] = cs5463rw[1]; cs5463tm[2] = cs5463rw[2]; if(cs5463rw[0]&0x80) { temp = &cs5463rw[0]; read_5463(temp,0x18); //read voltage if(cs5463rw[0]||cs5463rw[1]||cs5463rw[2]) { count5463 = 0; aresult[0] = cs5463rw[0]*0x10000+cs5463rw[1]*0x100+cs5463rw[2]; temp = &cs5463rw[0]; read_5463(temp,0x16); //read current aresult[1] = cs5463rw[0]*0x10000+cs5463rw[1]*0x100+cs5463rw[2]; /********************************/ con_yk = aresult[0]/0x0a7c; //control use ac_vresult[vi_count] = con_yk; if((con_time >= 2)&&(close_oil)&&(!stop_mb)) {con_time = 0;pid_control();} /********************************/ vi_count += 1; if(vi_count == 40) { vi_count = 0; aresult[0] = 0; for(ac_n=0;ac_n<40;ac_n++) { aresult[0] += ac_vresult[ac_n]; } acresult[0] = aresult[0]/40; } } } { cs5463rw[0] = cs5463tm[0]; //清除状态位 cs5463rw[1] = cs5463tm[1]; cs5463rw[2] = cs5463tm[2]; temp = &cs5463rw[0]; write_5463(temp,0x5e); } if(count5463 > 150) //大于1.5s ,reset 5463 { init_5463(); count5463 = 0; } } //---- void nop_1us(void) //1us { uchar i; for(i = 0;i < 3;i++); } /**********cs5463**********/ /**********cs5463**********/ void Hex2Bcd3(uint value) { uchar number1,number2,number3,number4; number4 = value/1000; number3 = (value-=number4*1000)/100; number2 = (value-=number3*100)/10; number1 = (value-=number2*10); keydata4 = number4|0x30; keydata3 = number3|0x30; keydata2 = number2|0x30; keydata1 = number1|0x30; } void comm_pro(void) { if(acresult[0] >0350) //发电机输出电压大于5伏显示,否则显示零电压 { Hex2Bcd3(acresult[0]); /*机组电压*/ rs232tran[2] = keydata4; rs232tran[3] = keydata3; rs232tran[4] = keydata2; rs232tran[5] = keydata1; } else { rs232tran[2] = 0x30; rs232tran[3] = 0x30; rs232tran[4] = 0x30; rs232tran[5] = 0x30; } Hex2Bcd3(frequencyp); /*输出频率*/ rs232tran[6] = keydata3; rs232tran[7] = keydata2; rs232tran[8] = keydata1; Hex2Bcd3(disp_resultp); /*输出电池电压*/ rs232tran[9] = keydata4; rs232tran[10] = keydata3; rs232tran[11] = keydata2; if(alm_in2) {rs232tran[12] = '1';} else {rs232tran[12] = '0';} if(alm_in3) {rs232tran[13] = '1';} else {rs232tran[13] = '0';} if(alm_in4) {rs232tran[14] = '1';} else {rs232tran[14] = '0';} if(alm_in5) {rs232tran[15] = '1';} else {rs232tran[15] = '0';} if(alm_in6) {rs232tran[16] = '1';} else {rs232tran[16] = '0';} if(alm_in1) {rs232tran[17] = '1';} else {rs232tran[17] = '0';} if(alm_in0) {rs232tran[18] = '1';} else {rs232tran[18] = '0';} } void alarm_symbol(void) /*该报警应在机组正常工作时处理*/ { if((acresult[0] <= VOL_MAX)&&(acresult[0] >= VOL_MIN)) {vol_count = 0;alm_in2 = 0;alm_in3 = 0;} if((vol_count >= 300)&&(acresult[0] > VOL_MAX)) {alm_in2 = 1;vol_count = 300;} if((vol_count >= 300)&&(acresult[0] < VOL_MIN)) {alm_in3 = 1;vol_count = 300;} if((frequencyp <= FRE_MAX)&&(frequencyp >= FRE_MIN)) {fre_count = 0;alm_in4 = 0;alm_in5 = 0;} if((fre_count >= 300)&&(frequencyp > FRE_MAX)) {alm_in4 = 1;fre_count = 300;} if((fre_count >= 300)&&(frequencyp < FRE_MIN)) {alm_in5 = 1;fre_count = 300;} if(!oil_pre) {pre_count = 0;} if(!alm_in5&&(pre_count >= 300)) {alm_in1 = 1;pre_count = 300;} else {alm_in1 = 0;} if(alm_in2||alm_in3||alm_in4||alm_in5||alm_in1) {PWM = PWM_MIN;close_oil = 0;stop_mb = 1;alm_in0 = 1;} else {close_oil = 1;stop_mb = 0;alm_in0 = 0;} } void alarm_battery(void) { if(disp_resultp >= BAT_MIN) {bat_count = 0;alm_in6 = 0;} if((bat_count >= 300)&&(disp_resultp < BAT_MIN)) {alm_in6 = 1;bat_count = 300;} } /**************************/ void pid_control(void) { con_temp = con_ui1; con_temp1 =0; if(con_yk <= con_give) { con_ei = con_give-con_yk; if(con_ei > 1105) {con_ei = 1105;} /*************************/ if(con_ei > 155) { con_a0 = 100; //40 con_a1 = 00; //38 con_a2 = 00; //20 } else { con_a0 = 40; //40 con_a1 = 38; //38 con_a2 = 00; //20 } /*************************/ a0_b=0; con_temp += con_a0*con_ei; if(!a1_b) {con_temp1 += con_a1*con_ei1;} else {con_temp +=con_a1*con_ei1;} if(!a2_b) {con_temp +=con_a2*con_ei2;} else {con_temp1 += con_a2*con_ei2;} if(con_temp >= con_temp1) { con_temp = con_temp-con_temp1; } else { //con_temp = con_temp1-con_temp; con_temp = PWM_MIN; } } else { con_ei = con_yk-con_give; if(con_ei > 1105) {con_ei = 1105;} /*************************/ if(con_ei > 125) { con_a0 = 150; //40 con_a1 = 00; //38 con_a2 = 00; //20 } else { con_a0 = 40; //40 con_a1 = 38; //38 con_a2 = 00; //20 } /*************************/ a0_b=1; con_temp1 = con_a0*con_ei; if(!a1_b) {con_temp1 += con_a1*con_ei1;} else {con_temp += con_a1*con_ei1;} if(!a2_b) {con_temp +=con_a2*con_ei2;} else {con_temp1 += con_a2*con_ei2;} if(con_temp >= con_temp1) { con_temp = con_temp-con_temp1; } else { //con_temp = con_temp1-con_temp; con_temp = PWM_MIN; } } if(con_tempPWM_MAX) {con_temp = PWM_MAX;} else{con_temp = con_temp;} con_ui1 = con_temp; con_ei2 = con_ei1; /*参数传递及电机输出*/ con_ei1 = con_ei; a2_b=a1_b; a1_b=a0_b; PWM = con_temp; }