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

📄 m16_rectctrl.c

📁 通信电源中
💻 C
📖 第 1 页 / 共 2 页
字号:
        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;
    }
    pwm_vol_set=i;
  }
}

void  calc_cur_lmt_pwm(void)   				//计算限流输出
{
	ulong cur_chg=0;
	
	cur_lmt=(cur_chr<=cur_out)?cur_chr:cur_out;	//采用充电限流值或输出限流值
	
	cur_chg=(ulong)51465*cur_lmt;				//将命令限流值换算成PWM设置值,cur_chg=(ulong)1725*12*cur_lmt*10/4			
 	cur_chg=(cur_chg/100-1299)/100;			//限流值在保证准确的前提下,低一点为宜!
 	cur_lmt=(uint)cur_chg; 	
 	
	pwm_cur_lmt=cur_lmt;								//无修正,按照设定数值输出(原因:限流精度要求不高,正负0.1足矣)
}

void set_pwm_out(void)
{
	CLI();															//禁止所有中断
	OCR1A=pwm_vol_set;									//设置PWM调压值
	OCR1B=pwm_cur_lmt;									//设置PWM限流值
	SEI();															//使能所有中断
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//USART initialisation
// desired baud rate: 19200
// char size: 9 bit
// parity: Disabled
void usart_init(void)
{
 	UCSRB = 0x00;		//disable while setting baud rate
 	UCSRA = 0x00;
 	UCSRC|=(1<<UCSZ1)|(1<<UCSZ0);				//19200 BPS
 	UBRRH = 0x00; 	//set baud rate hi:此两个寄存器初始化的顺序不能颠倒!!
 	UBRRL = 25;	 		//set baud rate lo
 	UCSRB|=(1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN)|(1<<UCSZ2);
}

//USART Receive Frame
uchar check_rx_frame(void)						//检查接收帧是否完整
{
	uchar i=0;
	uint sum=0;
	
	for(i=0;i<=3;i++) 									//检验加法和
		sum+=sio_rx_buf[i];
	if(sum!=sio_rx_buf[4]*256+sio_rx_buf[5])							
 		return 0;
 		
 	id_addr=(bittest(PINA,PINA4))?0x41:0x47;	//获得模块组地址
 	
 	return 1;
}

uchar process_rx_frame(void)					//接收帧处理
{
	rct_addr=sio_rx_buf[0];
	
	if(rct_addr==0b01000000)						//若是广播地址(不应答)
	{
		switch(sio_rx_buf[1])
		{
			case 0x80:											//模块充电限流值
			{
				cur_chr=sio_rx_buf[2]*256+sio_rx_buf[3];
      	return 0;
			}
			case 0x81:											//模块全开机
			{
				rct_pow=0;
				return 0;
			}
			case 0x82:											//模块全关机
			{
				rct_pow=0x3F;
				return 0;
			}
			case 0x83:											//模块浮冲命令
			{
				flag_rct=0;
				return 0;
			}
			case 0x84:											//模块均冲命令
			{
				flag_rct=1;
				return 0;
			}
			case 0x90:											//模块浮冲电压值
			{
				vol_flt=sio_rx_buf[2]*256+sio_rx_buf[3];
				return 0;
			}
			case 0x91:											//模块均充电压值
			{
				vol_ave=sio_rx_buf[2]*256+sio_rx_buf[3];
				return 0;
			}
			case 0x92:											//直流输出过压保护值
			{
				return 0;
			}
			case 0x93:											//直流输出欠压保护值
			{
				return 0;
			}
			case 0x94:											//交流输入过压保护值
			{
				return 0;
			}
			case 0x95:											//交流输入欠压保护值
			{
				return 0;
			}
			case 0x96:											//模块输出限流值
			{
				cur_out=sio_rx_buf[2]*256+sio_rx_buf[3];
				return 0;
			}
			case 0x97:											//模块过温保护值
			{
				return 0;
			}
		}
	}
	else																										//若不是广播
	{
		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]/256;		//模块电流和温度
					sio_tx_buf[3]=rct_cur[rct_addr-id_addr]%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 0x81:																					//模块开机
			{
				if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5))	//若是本组模块地址
					rct_pow&=~(1<<(rct_addr-id_addr));							//则相应位清0
				return 0;
			}
			case 0x82:																					//模块关机
			{	
				if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5))	//若是本组模块地址
					rct_pow|=(1<<(rct_addr-id_addr));								//则相应位置1
				return 0;
			}
		}
	}
	return 0;
}

//USART Tramsmit Frame
void send_tx_frame(void)						//发送返回信息帧
{
	uchar i=0;
	uint	sum=0;

 	//构造发送信息帧
 	sio_tx_buf[0]=rct_addr;
 	sio_tx_buf[6]=0;
 	sio_tx_buf[7]=0;
 	if((rct_addr-id_addr>=0)&&(rct_addr-id_addr<=5))	//若是本组模块地址
 		sio_tx_buf[7]|=((bittest(rct_warn,rct_addr-id_addr))<<7);
 	
 	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;
  //构造完毕

 	YELON;														//发送RS485通道开启,接收通道关闭,PB6=0,黄灯亮
 	sio_tx_num=0;

	UCSRB|=(1<<TXB8);									//发送第8位————地址为1
	UDR=sio_tx_buf[0];								//发送第0个字节,发送完毕中断响应

	sio_rx_num=0;											//重启接收	
}

#pragma interrupt_handler usart_rx_isr:12
void usart_rx_isr(void) 
{
	//usart has received a character in UDR
 	uchar sum=0,status,resh,img_RxUDR;

	status=UCSRA;
	resh=UCSRB;
 	img_RxUDR=UDR;
 	if(status&((1<<DOR)|(1<<PE)))			//若接收帧有错误
 		return;
 	
 	resh=(resh>>1)&0x01;							//过滤第8位数据
 	
	if(sio_rx_num)
	{
		sio_rx_buf[sio_rx_num]=img_RxUDR;
 		sio_rx_num++;
 		if(sio_rx_num>=SIO_RX_LEN)		//若已经接收到尾字节
 		{
 			if(check_rx_frame())				//若接收帧正确
 			{
 				if(process_rx_frame())		//若帧处理完毕,有应答
					send_tx_frame();				//则停止接收,开始发送
 				else
 					sio_rx_num=0;						//无应答,重新接收
 			}
 			else
				sio_rx_num=0;							//否则重新接收
 		}
	}
	else
	{
		if(resh)												//若接收帧是地址
 		{
 			if(img_RxUDR&0b01000000)			//若符合帧头字节
 			{
 				sio_rx_buf[0]=img_RxUDR;
 				sio_rx_num=1;
 			}
		}
	}
}

#pragma interrupt_handler usart_tx_isr:14
void usart_tx_isr(void)
{
 	//character has been transmitted
 	sio_tx_num++;
 
  if(sio_tx_num<SIO_TX_LEN)					//若未发送完成到尾字节
  {
  	UCSRB&=~(1<<TXB8);							//发送第8位————数据为0
 	  UDR=sio_tx_buf[sio_tx_num];			//则继续发送
 	}
 	if(sio_tx_num>=SIO_TX_LEN)			  //若此次发送完成的是尾字节
	  YELOFF;													//则黄灯灭,发送通道关闭,接收通道开启
	if(sio_tx_num>SIO_TX_LEN)					//若发送计数器超过10
 	  sio_tx_num=SIO_TX_LEN+1;				//则发送计数器保持为11,空转
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//call this routine to initialise all peripherals
void init_devices(void)
{
 	//stop errant interrupts until set up
 	CLI(); 														//disable all interrupts
 	port_init();
	watchdog_init();
 	usart_init();
 	timer1_init();
	adc_init();

	vol_ave = 5520;										//设置均充电压默认值为55.20V
	vol_flt = 5360;										//设置浮冲电压默认值为53.60V
 	pwm_vol_set = 5360;				
 	cur_chr = 150;										//满载电流值
 	cur_out	= 160;										//输出电流最大值
 	pwm_cur_lmt = 150;								
 	set_pwm_out();										//PWM初值
	
	rct_pow	=	0x3F;										//模块全开机

 	delay_us(100);										//延时,使控制信号稳定

 	sio_rx_num = 0;
 	YELOFF;														//使能USART接收

 	MCUCR = 0x00;
 	GICR  = 0x00;
 	TIMSK = 0x00; 										//timer interrupt sources
 	SEI(); 														//re-enable interrupts

 	PORTB|=(1<<PB7);									//继电器闭合(信号稳定,输出)
 	//all peripherals are now initialised
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void main(void)
{
  uint register clr;
	
	for(clr=0;clr<1024;clr++)					//将内部SRAM清零
	  DBYTE[clr+0x60]=0;
	
	init_devices();
	while(1)
	{
		rct_measure();									//测量模拟量
		pow_process();									//处理关机
  	get_warn_status();							//测量模块状态

  	calc_vol_set_pwm();							//计算调压值
    calc_cur_lmt_pwm();							//计算限流值
    delay_us(1);
    set_pwm_out();									//调整PWM输出

		WDR();
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -