📄 mega88.c
字号:
#include <iom88v.h>
#include <macros.h>
#include <math.h>
//PWM由A口输出
//PWM频率40K,相位与频率修正方式,模式8
//将调整PWM放到TOV1溢出中
//外部16M晶振
//输出电压值OUT_V(通道0:0x40) 输入电压值IN_V(通道1:0x41) 输入电流值OUT_I(通道2:0x42)
//分两档:轻档恒流加限输出电压 重档恒电压
//增量法
//******PID参数*****************
//快速恒压参数
#define A_V 0.31
#define B_V 0.01
//正常恒流参数
#define A_I 0.56
#define B_I 0.07
//****************************************
#define OCR1AL_MAX 0xBE //占空比上限95%
#define OCR1AL_MIN 0x0A //占空比上限5%
#define OCR1AL_U 0x14 //占空比变化最大值10%
#define OCR1AL_I 0x14 //占空比变化最大值10%
//****************************************
unsigned int OUT_Voltage[12]; //输出电压
unsigned int OUT_V;
unsigned char OUT_V_Loop;
unsigned int OUT_Current[12]; //输出电流
unsigned int OUT_I;
unsigned char OUT_I_Loop;
float Ek_I,Ek_I_Before,Uk_I,Uk_I_Before;
float Ek_V,Ek_V_Before,Uk_V,Uk_V_Before;
//******************************************************/
void adc_init(void)
{
OUT_I_Loop = 0;
OUT_V_Loop = 0;
ADCSRA = 0x00;
ACSR = (1<<ACD);
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
//****************************************************/
#pragma interrupt_handler timer1_capt_isr:11
void timer1_capt_isr(void)
{
unsigned int temp;
unsigned char i;
//------输出电压-------------
ADMUX = 0x40;
ADCSRA |= (1<<ADSC);
while((ADCSRA&0x10) != 0x10)
WDR();
ADCSRA |= (1<<ADIF);
OUT_Voltage[OUT_V_Loop] = ADC & 0x03FF;
OUT_V_Loop ++;
if(OUT_V_Loop == 12)
OUT_V_Loop = 0;
temp = 0;
for(i=0;i<12;i++)
temp = temp + OUT_Voltage[i];
OUT_V = temp / 12;
//-----输出电流---------------
ADMUX = 0x43;
ADCSRA |= (1<<ADSC);
while((ADCSRA&0x10) != 0x10)
WDR();
ADCSRA |= (1<<ADIF);
OUT_Current[OUT_I_Loop] = ADC & 0x03FF;
OUT_I_Loop ++;
if(OUT_I_Loop == 12)
OUT_I_Loop = 0;
temp = 0;
for(i=0;i<12;i++)
temp = temp + OUT_Current[i];
OUT_I = temp / 12;
//--------PID处理-------------
//快速充电恒压 低电平
if(!(PIND & 0x01))
{
Ek_V = 14.2 - OUT_V * 0.0244;
Uk_V = A_V * (Ek_V - Ek_V_Before) + B_V * Ek_V + Uk_V_Before;
if(Uk_V < 0)
Uk_V = 0;
if(Uk_V > OCR1AL_MAX)
Uk_V = OCR1AL_MAX;
Uk_V_Before = Uk_V;
Ek_V_Before = Ek_V;
if((Uk_V - OCR1AL) > OCR1AL_U)
OCR1AL = OCR1AL + OCR1AL_U;
else if((OCR1AL - Uk_V) > OCR1AL_U)
OCR1AL = OCR1AL - OCR1AL_U;
else
OCR1AL = (unsigned char)(Uk_V);
}
//正常充电 恒流加恒压 高电平
if(PIND & 0x01)
{
if(OUT_I < 32)
{
OCR1AL = 0x64;
}
else
{
Ek_I = 2 - OUT_I * 0.005;
Uk_I = A_I * (Ek_I - Ek_I_Before) + B_I * Ek_I + Uk_I_Before;
if(Uk_I < 0)
Uk_I = 0;
if(Uk_I > OCR1AL_MAX)
Uk_I = OCR1AL_MAX;
Uk_I_Before = Uk_I;
Ek_I_Before = Ek_I;
if((Uk_I - OCR1AL) > OCR1AL_I)
OCR1AL = OCR1AL + OCR1AL_I;
else if((OCR1AL - Uk_I) > OCR1AL_I)
OCR1AL = OCR1AL - OCR1AL_I;
else
OCR1AL = (unsigned char)(Uk_I);
}
}
}
//****************************************************
void timer1_init(void)
{
DDRB |= (1<<PB2);
DDRB |= (1<<PB1);
TCCR1B = 0x00;
TCNT1H = 0xFF;
TCNT1L = 0x38;
OCR1AH = 0x00;
OCR1AL = 0x0f;
OCR1BH = 0x00;
OCR1BL = 0x0b;
ICR1H = 0x00;
ICR1L = 0xC8;
TCCR1A = (1<<COM1A1)|(1<<COM1B1);
TCCR1B = (1<<WGM13)|(1<<CS10);
TIMSK1 = 0x20;
}
//*************************************************/
void main(void)
{
WDR();
WDTCSR = 0x1F;
WDTCSR = 0x0F;
WDR();
PORTD |= (1<<PD0);
CLI();
timer1_init();
adc_init();
SEI();
Ek_V_Before = 0x00;
Uk_V_Before = 0x00;
Ek_I_Before = 0x00;
Uk_I_Before = 0x00;
while(1)
{
WDR();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -