高级会员
主题
帖子
积分3383
阅读权限30
注册时间2012-12-18
最后登录1970-1-1
在线时间 小时
|
最好电池没有电的时候进行涓流充电会好些,就如楼上3楼所说,
可以参考一下下面的帖子看一下:
http://bbs.elecfans.com/forum.php?mod=viewthread&tid=270784
下面是采用STC AD PWM做的充电源码
- //---------------------------------------------------------------------
- //#include <REG52.H>
- #include <intrins.H>
- #include "NEW_8051.H"
- //WDT_CONTR //狗
- //---------------------------------------------------------------------
- typedef unsigned char INT8U;
- typedef unsigned int INT16U;
- //定义常量
- //pulse_width_MAX = pulse_width_MIN 时, 输出脉冲宽度不变。
- #define pulse_width_MAX 0x65 //PWM 脉宽最大值, 占空比 =75%
- #define pulse_width_MIN 0x45 //PWM 脉宽最小值, 占空比 =25%
- //#define step 0x38 //PWM 脉宽变化步长
- #define pulse_width 0x30H
- #define ADC_Power_On_Speed_Channel_0 0xE0 //P1.0 作为 A/D 输入
- #define ADC_Power_On_Speed_Channel_1 0xE1 //P1.1 作为 A/D 输入
- #define ADC_Power_On_Speed_Channel_2 0xE2 //P1.2 作为 A/D 输入
- #define ADC_Power_On_Speed_Channel_3 0xE3 //P1.3 作为 A/D 输入
- #define ADC_Power_On_Speed_Channel_4 0xE4 //P1.4 作为 A/D 输入
- #define ADC_Power_On_Speed_Channel_5 0xE5 //P1.5 作为 A/D 输入
- #define ADC_Power_On_Speed_Channel_6 0xE6 //P1.6 作为 A/D 输入
- #define ADC_Power_On_Speed_Channel_7 0xE7 //P1.7 作为 A/D 输入
- sbit B_LED = P3^4;//
- sbit B_LED2 = P1^4;
- sbit B_ON = P3^5;
- sbit B_PW = P3^7;
- INT8U con_state,ADC_Channel_2_Result_date,T_N;
- INT16U AD_date,S_N;
-
- //#define ADC_YUCHONGDIAN 0x39 //1.12V,6V
- //#define ADC_YUCHONGDIAN_0 0x3E //1.21,6.4V
- //#define ADC_JIESHU 0x51 //1.58,8.4V
- //#define ADC_YUCHONGDIAN 0x4D //1.51V,8V
- //#define ADC_YUCHONGDIAN_0 0x55 //1.65,8.8V
- //#define ADC_JIESHU 0x74 //2.26,12V
- //#define ADC_KONG 0x8D //2.82,15V
- //#define ADC_DUANLU 0x30
- //#define ADC_YUCHONGDIAN 0x40 //1.12V,6V
- //#define ADC_YUCHONGDIAN_0 0x44 //1.21,6.4V
- //#define ADC_JIESHU 0x58 //1.58,8.4V
- #define ADC_21 0x89 //21V
- #define ADC_24 0x9c //24V
- #define ADC_27 0xB0 //27V
- #define ADC_28 0xB7 //28V
- #define ADC_KONG 0xC8 //2.82,15V
- #define ADC_DUANLU 0x30
- #define ADC_135 0x58 //21V
- #define ADC_13 0x54 //0.153,21V
- /***********************
- init port
- ***********************/
- void INITAL_port(void)
- {
- P0=0xff;
- P1=0xff;
- P2=0xff;
- P3=0xff;
- }
- /***********************
- init PCA
- ************************/
- void initiate_pca (void);
- void delay(INT8U delay_time) // 延时函数
- {
- INT16U n;
- while(delay_time--)
- {
- n = 6000;
- while(--n);
- }
- }
- /***********************
- init AD
- ************************/
- //--------------------------------------------------------------
- void ADC_Power_On(void)
- {
-
- ADC_CONTR|=0x80; //开 A/D 转换电源
-
- delay(20); //开 A/D 转换电源后要加延时,1mS 以内就足够了
- }
-
- void Set_P12_Open_Drain(void) //设置 P1.2,设置 A/D 通道所在的 I/O 为开漏模式
- {
-
- P1M0|= 0x4;
- P1M1|= 0x4;
- }
- void Set_ADC_Channel_2(void)
- {
- ADC_CONTR=ADC_Power_On_Speed_Channel_2;
- //选择 P1.2 作为 A/D 转换通道
- //更换 A/D 转换通道后要适当延时, 使输入电压稳定
- //以后如果不更换 A/D 转换通道的话, 不需要加延时
- delay(5); //切换 A/D 转换通道,加延时 20uS~200uS 就可以了,与输入电压源的内阻有关
- //如果输入电压信号源的内阻在 10K 以下,可不加延时
-
- }
- void initiate_AD (void)
- {
- ADC_Power_On (); //开 ADC 电源, 第一次使用时要打开内部模拟电源 ;开 ADC 电源, 可适当加延时,1mS 以内就足够了
- Set_P12_Open_Drain (); //设置 P1.2 为开漏
- Set_ADC_Channel_2(); //设置 P1.2 作为 A/D 转换通道
- }
- //----------------------------------------------------------
- INT8U Get_AD_Result(void)
- {
-
- ADC_DATA=0;
- //ADC_CONTR = AD_SPEED;
- //ADC_CONTR = 0xE0; //1110,0000 清 ADC_FLAG, ADC_START 位和低 3 位
- //ADC_CONTR |= channel; //选择 A/D 当前通道
- Set_ADC_Channel_2();
- delay(1);
-
- ADC_CONTR|= 0x08; //启动 AD 转换
- //判断 AD 转换是否完成
- while (1) //等待A/D转换结束
- {
- if (ADC_CONTR & 0x10) //0001,0000 测试A/D转换结束否
- { break; }
- }
-
- ADC_CONTR&=0xE7; //清 0 ADC_FLAG, ADC_START 位, 停止 A/D 转换
- return ADC_DATA;
-
- }
-
- //---------------------------------------------------------------------
- void Send_Byte(INT8U one_byte) //发送一个字节
- {
- TI = 0; //清零串口发送中断标志
- SBUF = one_byte;
- while (TI == 0);
- TI = 0; //清零串口发送中断标志
- }
- //------------------------------------------------------------
- void timer_start(void)
- {
- ET0 =1;
- TR0 =1;
- }
- void timer_stop(void)
- {
- ET0 =0;
- TR0 =0;
- }
- //------------------------------------------------------------
- void PWM (INT8U width)
- {
-
-
- CCAP0H=width; // 示例程序核心语句
- PCA_PWM0=0x00 ; //示例程序核心语句P3.7
- PCA_PWM1=0x03;
- delay(5);
- }
- void pwm_stop(void)
- {
- PCA_PWM0=0x03 ;//释放本行注释,PWM输出就一直是0,无脉冲;-------------------------
- PCA_PWM1=0x03 ;
- delay(250);
- }
- //------------------------------------------------------------
- void initiate_RS232 (void) //串口初始化
- {
-
- SCON = 0x50; //可变波特率. 8位无奇偶校验
- TMOD = 0x21;
- TH1 = 0xe7;//5.8mhz 600/s
- TL1 = 0xe7;
- AUXR &= 0xBF;
- TR1 =1;
- ES = 0; //禁止串口中断
- }
- //---------------------------------------------------------------------
- void initiate_pca (void)
- {
- CMOD=0x82;
- //PCA 在空闲模式下停止 PCA 计数器工作 ;PCA 时钟模式为fosc/12
- //禁止 PCA 计数器溢出中断
- CCON=0x00; //禁止 PCA 计数器工作, 清除中断标志、计数器溢出标志
- CL =0x00; //清 0 计数器
- CH =0x00;
-
- //设置模块 0 为 8 位 PWM 输出模式, PWM 无需中断支持。脉冲在 P3.7(第 11 脚)输出
- CCAPM0 =0x42; //示例程序核心语句 0100,0010
- //PCA_PWM0=0x00H; //示例程序核心语句P3.7;
- PCA_PWM0=0x03; //释放本行注释,PWM输出就一直是0,无脉冲;-------------------------
-
- //设置模块 1 为 8 位 PWM 输出模式, PWM 无需中断支持。脉冲在 P3.5(第 9 脚)输出
- //CCAPM1=0x42; //示例程序核心语句 0100,0010
- //PCA_PWM1=0x00; //示例程序核心语句 P3.5
- //PCA_PWM1=0x03; //释放本行注释, PWM 输出就一直是 0, 无脉冲。
- //B_MO_1=0;
- EPCA_LVD=1; //开pca中断
- EA=1;
- CR=1; //将 PCA 计数器打开
- }
- //---------------------------------------------------------------------
- //**********************************************
- void Initial_T0(void)
- {
- TH0=0x4C ;//设置定时器0 自动重装数 11M
- TL0=0x00 ;//500uS
-
- //AUXR&=0xBF; //定时器1 工作在12T 模式,与普通的8051 相同
- ET0=0;
- TR0=0; //启动定时器1
- }
- void timer_init(void)
- {
- TH0=0x4C ;//设置定时器0 自动重装数 11M
- TL0=0x00 ;//50MS
- ET0=1;
- TR0=1;
- }
- //---------------------------------------
- void con (void)
- {
- AD_date=AD_date+Get_AD_Result();
- AD_date=AD_date>>1;
- if (AD_date<ADC_DUANLU)
- {
-
- con_state=4;
- }
- switch(con_state)
- {
- case 0:
-
- if (AD_date < ADC_21)
- {
- S_N=60000;
-
- PWM(pulse_width_MAX) ;//为输出脉冲宽度设置初值。
- timer_init();
- con_state=1;
- }
- else
- {
- if (AD_date<ADC_28)
- con_state=2;
- }
-
- break;
- case 1:
-
- if (AD_date>ADC_21)
- {
-
- con_state=2;
- }
- if (S_N==0)
- {
-
- con_state=2;
- }
-
- break;
-
- case 2:
- S_N=60000;
-
-
- PWM(pulse_width_MAX) ;//为输出脉冲宽度设置初值。
- timer_init();
- con_state=3;
- break;
- case 3:
- if(AD_date>ADC_28)
- {
-
-
- con_state=4;
- }
- if (S_N==0)
- {
-
- con_state=4;
- }
- break;
- case 4: //如果没有电池或者在很长一段时间后重新启动初始化
-
- pwm_stop();
- TR0=0;
- ET0=0;
-
- con_state=5;
- B_LED=0;
- B_LED2=0;
-
- break;
- case 5: //如果没有电池或者在很长一段时间后重新启动初始化
-
- if (AD_date>ADC_KONG )
- {
- con_state=0;
- B_LED=1;
- B_LED2=1;
- }
- break;
-
-
- default:
-
- break;
- }
-
- }
- //---------------------------------------
- void timer0(void) interrupt 1
- {
- INT8U ACC_temp;
- ACC_temp= ACC;
- TR0=0;
- if(S_N!=0)
- {
- S_N--;
- }
- if(T_N==0&con_state!=5)
- {
- B_LED=~B_LED;
- B_LED2=~B_LED2;
- T_N=10;
- }
- T_N--;
- timer_init();
- ACC= ACC_temp;
- }
- //------------------------------------------------------------
- void serial()interrupt 4
- { INT8U ACC_temp;
- if(RI==0)
- TI=0;
- else
- {
- RI=0;
- ES=0;
- ACC_temp=ACC ;
-
- //RS_do(SBUF);
- ACC=ACC_temp ;
- ES=1;
- }
- }
-
- //---------------------------------------------------------------------
- void main()
- { INT8U n;
- INITAL_port();
- T_N=0;
- B_PW= 0 ;
- n=0;
-
-
- initiate_pca();
- initiate_RS232(); //波特率 = 600
-
- initial_T0();
- //Send_Byte(0xAA); //为便于观察, 发送 2 个 0xAA
-
- B_LED=0;
- B_LED2=0;
-
- delay(0x250);
- B_LED=1;
- B_LED2=1;
- initiate_AD();
- ES=1;
- con_state=0;
- AD_date=Get_AD_Result();
-
- //Send_Byte(AD_date);
- while(1)
- {
- con();
- WDT_CONTR=0x3f; //看门狗
- if(n>10)
- {
- Send_Byte(AD_date);
- n=0;
- }
- n++;
-
- }
- }
复制代码 |
|