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

📄 m16_rectctrl.c

📁 通信电源中
💻 C
📖 第 1 页 / 共 2 页
字号:
// ATmega16_MCtrl_4.0 : 2005-02-24

//ICC-AVR application builder : 2004-12-8 11:04:46
// Target : M16
// Crystal: 8.0000Mhz

#include <iom16v.h>
#include <macros.h>
#include <slavr.h>

#define uchar unsigned char
#define uint 	unsigned int
#define ulong unsigned long

uchar  *DBYTE;	   								//DBYTE指针,指向字节地址

//Signal bit definitions
#define YELON		PORTB&=~(1<<PB6)	//黄灯亮,USART发送
#define	YELOFF	PORTB|=(1<<PB6)		//黄灯灭,USART接收

#define SIO_RX_LEN 6
#define SIO_TX_LEN 10

#define RCT_CUR_RANG 400 					//1023 -- 40A

//声明变量一定要赋初值!!
//UART Parameters
uchar sio_rx_num=0;								//接收字节数
uchar sio_tx_num=0;								//发送字节数
uchar sio_rx_buf[SIO_RX_LEN];			//接收帧缓冲区
uchar sio_tx_buf[SIO_TX_LEN];			//应答帧缓冲区

//Other Parameters

uchar rct_cur_channel=0;					//AD通道
uint 	adc_rel=0;									//AD转换结果

uint 	ibuf[9];										//AD采样数组

uchar	flag_rct=0;									//0:浮冲(默认)  1:均充
uint	vol_flt=0;									//模块浮冲电压
uint	vol_ave=0;									//模块均充电压
uint	cur_chr=0;									//模块充电限流
uint	cur_out=0;									//模块输出限流

uint  ad_vol_set=0;								//调压输出测量值
uint  pwm_vol_set=0;							//PWM调压输出(0-1023)
uint	pwm_cur_lmt=0;							//PWM调压输出(0-1023)
uint  vol_set=0;									//调压输出设置值(0-1023)
uint  cur_lmt=0;									//限流输出设置值(0-1023)

uchar id_addr=0;									//模块组地址
uchar rct_addr=0;									//模块地址
uchar rct_pow=0;									//模块关机————声明变量时一定要赋初值(编译器的Bug)!!
uchar rct_warn=0;									//模块告警
uint  rct_cur[6];									//模块电流

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

uchar bittest(uchar var,uchar bitno)	//位测试
{
	if((var>>bitno)&0x01==1)
		return 1;
 	else
 		return 0;
}

void port_init(void)
{
 	PORTA = 0b00000000;									//AD不要上拉电阻
 	DDRA  = 0b00000000;					
	PORTB = 0b11000000;									//模块全开机
 	DDRB  = 0b11111111;
 	PORTC = 0b11111111;
 	DDRC  = 0b01010000;
 	PORTD = 0b11111111;
 	DDRD  = 0b00110010;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Watchdog initialize
// prescale: 2048K
void watchdog_init(void)
{
 	WDR(); 					//看门狗计数清零 - this prevents a timout on enabling
 	WDTCR = 0x0F; 	//使能watchdog,并且,采用2048K分频,典型溢出时间5V时2.1S - dont forget to issue WDRs
}

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

void get_warn_status(void)						//获得模块状态
{
	uchar t=0,img_PINC=0,img_PIND=0;

  PORTC|=(1<<PC6);										//VSET=1,设置模块状态比较值3.3V
	delay_us(10);
	img_PINC=PINC;
	img_PIND=PIND;
	t=((img_PINC&0x02)>>1)|((img_PINC&0x01)<<1)|((img_PIND&0x80)>>5)|((img_PIND&0x40)>>3)|((img_PIND&0x08)<<1)|((img_PIND&0x04)<<3);

	rct_warn=t&0x3F;										//获得模块告警信号
}

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

void pow_process(void)								//关机处理(0为开机,1为关机)
{		
	if(bittest(rct_pow,0))							//开机0
		PORTB&=~(1<<PB0);
	else	 															//SHUT0
		PORTB|=(1<<PB0);
	if(bittest(rct_pow,1))							//开机1
		PORTB&=~(1<<PB1);
	else										 						//SHUT1
		PORTB|=(1<<PB1);
	if(bittest(rct_pow,2))							//开机2
		PORTB&=~(1<<PB2);
	else										 						//SHUT2
		PORTB|=(1<<PB2);
	if(bittest(rct_pow,3))							//开机3
		PORTB&=~(1<<PB3);
	else										 						//SHUT3
		PORTB|=(1<<PB3);
	if(bittest(rct_pow,4))							//开机4
		PORTB&=~(1<<PB4);
	else										 						//SHUT4
		PORTB|=(1<<PB4);
	if(bittest(rct_pow,5))							//开机5
		PORTB&=~(1<<PB5);
	else										 						//SHUT5
		PORTB|=(1<<PB5);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ADC initialize
// Conversion time: 208uS
void adc_init(void)
{
  ADCSRA= 0x00; //disable adc
  ADMUX = 0x1F; //select adc input GND
  ACSR  = 0x80;	//禁用模拟比较器
  ADCSRA|=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS2)|(1<<ADPS1);	//使能ADC,128预分频
}

void adc_start(uchar adc_chn)					//启动一次指定通道AD转换,返回转换结果
{
	ADMUX=adc_chn&0x07;									//指定通道
	delay_us(20);												//延时以使通道稳定!!
	ADCSRA|=(1<<ADSC);									//启动一次转换
	while(bittest(ADCSRA,ADSC));				//等待转换完毕
	adc_rel=ADC&0x3ff;									//转换完毕,立刻得到结果
}

uint adc_execute(uchar adc_chn)				//执行9次AD转换,对转换结果进行防脉冲干扰平均滤波
{
	uchar i=0;
	uint  sum=0;
	uint  ad_max=0,ad_min=0;

	for(i=0;i<9;i++)										//采样9次(约20ms)
	{
		adc_start(adc_chn);
		ibuf[i]=adc_rel;
	}

	ad_max=ad_min=ibuf[0];							//求出9次采样的最大值和最小值
	for(i=1;i<9;i++)
	{
		if(ibuf[i]<ad_min)
    	ad_min=ibuf[i];
  	if(ibuf[i]>ad_max)
    	ad_max=ibuf[i];
	}

	for(i=0;i<9;i++)										//求排除最大值、最小值之外的7个数的平均值
  	sum+=ibuf[i];
 	sum-=ad_max;
 	sum-=ad_min;
 	sum/=7;

	return sum&0x3ff;
}

void rct_measure(void)								//测量每一路电流(电压)值
{
	ulong ad_result=0;

	//开始测量一路模块电流(一次主循环只测一次电流值)
	switch(rct_cur_channel)
	{
		case 0:
		{
			ad_result=adc_execute(PA7);
			break;
		}
		case 1:
		{
			ad_result=adc_execute(PA6);
			break;
		}
		case 2:
		{
			ad_result=adc_execute(PA5);
			break;
		}
		case 3:
		{
			ad_result=adc_execute(PA3);
			break;
		}
		case 4:
		{
			ad_result=adc_execute(PA2);
			break;
		}
		case 5:
		{
			ad_result=adc_execute(PA1);
			break;
		}
	}

	ad_result*=RCT_CUR_RANG;
 	ad_result/=1024;
	
	if(ad_result>RCT_CUR_RANG)
	  ad_result=0;

 	rct_cur[rct_cur_channel]=(uint)ad_result;

	rct_cur_channel++;
 	rct_cur_channel%=6;
	//结束测量一路模块电流

	ad_result=adc_execute(PA0);					//测量电压控制输出(反馈)值
	ad_vol_set=(uint)ad_result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TIMER1 initialize - prescale:1
// WGM: 3) PWM 10bit phz correct, TOP=0x3FF
// desired value: 3.910KHz
// actual value:  3.910KHz (0.0%)
void timer1_init(void)
{
 	TCCR1B = 0x00; 			//stop
 	OCR1AH = 0x03;
 	OCR1AL = 0xFF;
 	OCR1BH = 0x03;
 	OCR1BL = 0xFF;
 	ICR1H  = 0x03;			//top value
 	ICR1L  = 0xFF;
 	TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11)|(1<<WGM10);
 	TCCR1B|=(1<<CS10); 	//start Timer
}

uint uint_abs_sub(uint i,uint j)			//无符号整数绝对值减法
{
	if(i>j)
  	return i-j;
 	else
	  return j-i;
 }

uchar uchar_abs_sub(uchar i,uchar j)	//无符号字节绝对值减法
{
	if(i>j)
  	return i-j;
 	else
   	return j-i;
}

/**************************************************************
 下面函数计算与调整输出电压

 目的:消除7805供电电压、ATmega16以及运放等电路产生的输出误差
 此函数很重要:因为控制电压信号与模块输出电压有12倍增益关系,
               不同模控板之间0.1V的输出压差将造成不均流现象。
               
 函数对设定值的设定调整范围:正负50(实际试验正负10)
***************************************************************/
#define DIF_ZERO    128
#define MAX_DIF_ERR 25
#define MAX_ITG_ERR 51

void  calc_vol_set_pwm(void)   				//计算与调整输出电压
{
	static uchar err_itg;								//电压控制信号
	uchar t;
 	uint 	i;
 	ulong vol_chg=0;
 
 	vol_set=(flag_rct==0)?vol_flt:vol_ave;	//采用浮冲电压或均冲电压
 	
 	vol_chg=(ulong)1729*vol_set;				//将命令电压值换算成PWM设置值。考虑到界限母排的电压降,此PWM值应比命令值略大!!
 	vol_chg=(vol_chg/100-1299)/100;
 	vol_set=(uint)vol_chg; 	
 	
 	if(uint_abs_sub(vol_set,ad_vol_set)>2*MAX_DIF_ERR)	//计算设定于采样的误差是否大于50
  {
  	err_itg=DIF_ZERO;									//误差积分清0
    if(ad_vol_set<vol_set) 						//PWM数值步进MAX_DIF_ERR调整 
    	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																//计算误差积分
  {
  	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=uchar_abs_sub(DIF_ZERO,err_itg)/MAX_ITG_ERR;	//计算积分误差调整值,增益1/25(经验数值,此值过大、过小都引起系统输出电压振荡) 
    
    if(t)															//根据调正量修正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(uint_abs_sub(vol_set,pwm_vol_set)>2*MAX_DIF_ERR)	//修正范围超出50,按照最大正负50调整
  {
  	if(vol_set>pwm_vol_set)
    {
    	if(vol_set<2*MAX_DIF_ERR)
      	i=0;
      else

⌨️ 快捷键说明

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