⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pic2448.c

📁 PWM控制输出电压由于该程序所需完成的功能比较简单
💻 C
📖 第 1 页 / 共 2 页
字号:


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 + -