单片机源程序如下:
//晶振1M
#include
#include
/********************************************************************
数据类型定义
*********************************************************************/
#define uchar unsigned char
#define uint unsigned int
#define LED1_K PORTB|=BIT(0)
#define LED1_G PORTB&=~BIT(0)
#define LED2_K PORTB|=BIT(1)
#define LED2_G PORTB&=~BIT(1)
#define PWM_1 PORTD|=BIT(0)
#define PWM_2 PORTD|=BIT(1)
#define PWM_1G PORTD&=~BIT(0)
#define PWM_2G PORTD&=~BIT(1)
uint pwm1=100;
uint CNT=0;
/**********************************************************************
延时函数
**********************************************************************/
void DelayMs(uint i) //0.25ms
{uchar j;
for(;i!=0;i--)
{for(j=250;j!=0;j--) {;}}
}
/**********************************************************************
电压值处理函数
**********************************************************************/
uint ADC_Convert(void)
{uint temp1,temp2;
temp1=(uint)ADCL;//先读ADCL
temp2=(uint)ADCH;//再读ADCH
temp2=(temp2<<8)+temp1;//求值
temp2=temp2*49/10;//求显示的电压值(0~5.12)V
return(temp2);
}
/**********************************************************************
初始化I/O口
**********************************************************************/
void Init_IO(void) //初始化I/O口
{
DDRC=0x00; //设置C口为推挽1输出
PORTC=0x00;
DDRB=0xff;
PORTB=0xff;
DDRD=0xff; //设置D口为推挽1输出
PORTD=0xff;
}
/**********************************************************************
主函数
**********************************************************************/
void main(void)
{uchar Load;
uint i,K,M;
uint u1,u2;
Init_IO(); //初始化I/O口
TCCR1A=0X00;
TCCR1B=0X01; //
TCNT1=65036;//500u
TIMSK1=0X01;
SEI();
DelayMs(300); //延时待系统稳定;
while(1)
{
if(M<=150)
{
ADMUX=0x01; //选择第二通道;
ADCSRA=0xe0; //500K转换速率,自由转换模式;启动AD转换器;
u1=ADC_Convert();
u1=u1*4;//蓄电池电压
}
else
{
ADMUX=0x00; //选择第一通道;
ADCSRA=0xe0; //500K转换速率,自由转换模式;启动AD转换器;
u2=ADC_Convert();
u2=u2*6;//太阳电池电压
}
if(u2>=30000)//太阳电池过压保护
{
LED1_G;
LED2_G;
CLI();//关中断
}
else //没有过压 正常工作
{
if(u1>=14500)//停止充电
{
LED1_K;
LED2_K;
PWM_1G;//pwm引脚置低电平;停止充电
CLI();//关中断
PWM_2;//pwm引脚置高电平;允许放电
}
else if(u1>=12000&&u1<=14500)//pwm充电
{
LED1_K;
LED2_G;
SEI(); //开中断
pwm1=80;// 占空比为80% pwm充电
PWM_2;//pwm引脚置高电平;允许放电
}
else if(u1>=10800&&u1<=12000)//快速充电
{
LED1_K;
LED2_G;
PWM_1;//pwm引脚置高电平 快速充电
PWM_2;//pwm引脚置高电平;允许放电
CLI();//关中断
}
else//停止放电
{
LED1_G;
LED2_K;
pwm1=50;// 占空比为50% pwm充电
PWM_2G;//pwm引脚置低电平 停止放电
SEI(); //开中断
}
}
if(M++>=160)
{ M=0;}
}
}
//********************T/C1中断服务函数500us进入一次,周期50ms********************//
#pragma interrupt_handler Timer1:14
void Timer1(void)
{
TCNT1=65036;
if(CNT++>=100) //中断次数累加
{
CNT=0;
}
if(CNT<=(pwm1)) //pwm1=1时,占空比为1%
{
PWM_1;//pwm引脚置高电平;
}
else
{
PWM_1G;//pwm引脚置低电平
}
}
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』