少占鱼-STC12C2052AD做的手机电池充电器

 
 /*******************
 C语言运算符优先级
 


   1级优先级 左结合   
  () 圆括号   [] 下标运算符   -> 指向结构体成员运算符   . 结构体成员运算符     
  
   2级优先级 右结合    
  ! 逻辑非运算符   ~ 按位取反运算符  ++ 自增运算符  -- 自减运算符  - 负号运算符 (类型) 类型转换运算符 * 指针运算符 & 地址与运算符 sizeof 长度运算符
          
   3级优先级 左结合    
  * 乘法运算符   / 除法运算符   % 取余运算符    
  
   4级优先级 左结合   
  + 加法运算符   - 减法运算符


   5级优先级 左结合    
  << 左移运算符   >> 右移运算符


   6级优先级 左结合   
  <、<=、>、>= 关系运算符


   7级优先级 左结合    (注意"等于"运算符== )
  == 等于运算符   != 不等于运算符
        
   8级优先级 左结合    
  & 按位与运算符


   9级优先级 左结合  
  ^ 按位异或运算符


   10级优先级 左结合 
  | 按位或运算符


   11级优先级 左结合   
  && 逻辑与运算符
  
   12级优先级 左结合 
  || 逻辑或运算符   
  
   13级优先级 右结合   
  ? : 条件运算符


   14级优先级 右结合 (赋值运算符)
  =+ =- =*   =/ =% =   >= < <=   &= ^= |= 全为赋值运算符


   15级优先级 左结合 
  , 逗号运算符
 *******************************/
#include <stc12c2052ad.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define AD_SPEED   0x60 //0110,0000   1      1     270个时钟周期转换一次,
//少占鱼制作  河北正定欢迎您   长沙航空职业技术学院  2010 年QQ:411656434
//
sbit M=P1^5; //过压指示灯
sbit N=P1^6; //欠压指示灯
sbit LED=P1^7; //充满 指示灯
sbit  REF=P1^0;
sbit PWM=P3^7;


bit START =0;


uchar timeL=0x90;
uchar timeH=0x90;
/****************************************************************/
void pwm();
void delayms(uint);          
void ADC();
void InitADC();
//void baohu();


float voltage=0.0;
const float Uref=2.500 ;


/***8**************************************************************/
 void main()

 
 PWM=1;
   delayms(700);
 START=0;
 PWM=0;
 LED=0;
 REF=0;
 delayms(9000);


 delayms(1000);
 M=0;
 N=0;
 LED=0;
  delayms(7000);
 M=1;
 N=1;
   LED=1;
    delayms(7000);
 PWM=1;
    delayms(1000);//延时 
  pwm();
    InitADC();
    delayms(6000);
    START=0;


   while(1)
   {
     ADC();


  if(START)
  {
  pwm();
  delayms(2000);
     }
   }
   
}
//
//
 void pwm()



   CR=0;
   START=0;


    //PCA模块工作于PWM模式 C程序  


   CMOD = 0x02; //用定时器0溢出做PCA脉冲    
   CL = 0x00; //PCA定时器低8位 地址:E9H   
   CH = 0x00; //PCA高8位 地址 F9H  
   CCON=0x00;


   CCAP0L = timeL; //PWM模式时他俩用来控制占空比  
   CCAP0H = timeH; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出)    


   CCAPM0 = 0x42; //0100,0010 Setup PCA module 0 in PWM mode
               // ECOM0=1使能比较 PWM0=1 使能CEX0脚用作脉宽调节输出
/*********************
PCA 模块工作模式设置 (CCAPMn 寄存器 n= 0-3四种)
 7     6        5        4       3       2     1      0
 -   ECOMn   CAPPn     CAPNn   MATn     TOGn   PWMn   ECCFn
选项: 0x00 无此操作
       0x20 16位捕捉模式,由 CEXn上升沿触发
       0x10 16位捕捉模式,由CEXn下降沿触发
       0x30 16位捕捉模式,由CEXn的跳变触发
       0x48 16位软件定时器
       0x4c 16位高速输出
       0x42  8位PWM输出
 每个PCA模块另外还对应两个寄存器:CCAPnH和CCAPnL 。  捕获或者比较时,它们用来
保存16位计数值,当工作于PWM模式时,用来控制占空比   
*******************************/     


   CR=1; //Start PCA Timer.


}



//AD转换初始化 ----打开ADC电源
void InitADC()
{
P1=0xff;
ADC_CONTR|=0x80;
delayms(3);
//这两个寄存器用来设置 P1口四种状态,每一位对应一个P1引脚 ,按状态组合操作


/*****************
 P1M0 和P1M1 寄存器位  7      6     5    4     3      2     1     0
                     P1.7  P1.6  P1.5  P1.4  P1.3  P1.2  P1.1  P1.0
 同理P3M0  P3M0 也是。因为STC12C2052AD只有两个P口,所以只有这俩组  STC12C5410AD还多P2M0 P1M0 有三组    
  P1M0   P1M1                 高
    0   0     普通I0口 (准双向)        P1寄存器位  7      6     5    4     3      2     1     0
 0      1     强推挽输出 (20MA电流 )尽量少用      P1.7  P1.6  P1.5  P1.4  P1.3  P1.2  P1.1  P1.0
 1  0     仅做输入  A/D转换时可用此模式     
 1      1    开漏 ,A/D转换时可用此模式
 


  例如:
  要设置P1.1为 AD 输入口
  则 P1M0=0X02 ;
     P1M1=0X02;   开漏即可
  当不用AD时,最好 关闭ADC电源 ,恢复为IO口状态
********************************/
P1M0=0x06;//这两个寄存器用来设置 P1口四种状态,每一位对应一个P1引脚 ,按状态组合操作
P1M1=0x06;//设置P1.1 P1.2开漏状态


 }


 


// AD转换程序
void  ADC()
{
    float V0,V1;


    ADC_DATA   = 0; //清除结果


    ADC_CONTR = 0x60;      //转换速度设置  0x60  最快速度


    ADC_CONTR = 0xE0;               //1110,0000 清 ADC_FLAG, ADC_START 位和低 3 位


    ADC_CONTR |= 0x01;           //选择 A/D 当前通道   P1.1
    delayms(1);                       //使输入电压达到稳定
   ADC_CONTR |= 0x08;              //0000,1000 令 ADCS = 1, 启动A/D转换, 


    while(!(ADC_CONTR & 0x10)); //!的优先级比&高太多了 
   //养成经常加括号的习惯 ,没坏处 。也不浪费速度
 /***************
 这里while 不能改成while(ADC_CONTR & 0x10==0) ;就错误了,因为优先级 ==比&高 ,所以要加括号
  while( (ADC_CONTR & 0x10)  ==0)    或者非一下  while(!(ADC_CONTR & 0x10)); //!的优先级比&高太多了 
    while( (ADC_CONTR & 0x10)  ==1)注意 if while这类判断逻辑真假的语句,用“==1”时 注意前面是否是后面的1,
 后面的1可是0x01啊,前面要是0x02===1,这是不会成立的。但是去掉后面的==1就可以用了。多此一举反而带来麻烦 
 *****************************/
    ADC_CONTR &= 0xE7;     //1111,0111 清 ADC_FLAG 位, 关闭A/D转换, 


    V0=  ADC_DATA; //返回 A/D 10 位转换结果



    ADC_DATA   = 0; //清除结果


    ADC_CONTR = 0x60;      //转换速度设置  0x60  最快速度


    ADC_CONTR = 0xe0;               //1110,0000 清 ADC_FLAG, ADC_START 位和低 3 位
   ADC_CONTR =0xe2;
   //  ADC_CONTR |= 0x02;           //选择 A/D 当前通道   P1.2
    delayms(1);                       //使输入电压达到稳定
    ADC_CONTR = 0xea;
   // ADC_CONTR |= 0x08;              //0000,1000 令 ADCS = 1, 启动A/D转换, 


    while(!(ADC_CONTR & 0x10)); //!的优先级比&高太多了 
   //养成经常加括号的习惯 ,没坏处 。也不浪费速度


 ADC_CONTR =0xe2;
    //ADC_CONTR &= 0xE7;     //1111,0111 清 ADC_FLAG 位, 关闭A/D转换, 
 V1=  ADC_DATA; //返回 A/D 10 位转换结果


 voltage=V1/V0*Uref*3.000;


  


   if( voltage>4.180)
    {
     M=0;//过压灯
     N=1;
     LED=1;
 timeL=timeL+0x08;
 timeH=timeH+0x08;
 START=1;
 LED=0;
    }
   if(voltage<3.601)
    {
    N=0;//欠压灯
 M=1;
 LED=1;
 timeL=timeL-0x01;
 timeH=timeH-0x01;
 START=1;
    }


 if(voltage>=3.601&&voltage<=4.155)
 {
  M=1;
  N=1;
  LED=1;
 } 
 
    if(voltage>=4.110&&voltage<=4.155)
   {
    timeL = 0xa2; //PWM模式时他俩用来控制占空比
    timeH = 0xa2; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出) 
    START=1;
 LED=0;
    }


     if(voltage>=4.155&&voltage<=4.180)
   {
    timeL = 0xb2; //PWM模式时他俩用来控制占空比
    timeH = 0xb2; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出) 
    START=1;
 LED=0;
    }


  /**************************
     if( voltage<3.772&&(timeL!=0xf0))
    {
   timeL = 0xf0; //PWM模式时他俩用来控制占空比
   timeH = 0xf0; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出)    
   START=1;
    }


   if( voltage<4.052&&voltage>3.772&&(timeL!=0xf2))
    {
   timeL = 0xf2; //PWM模式时他俩用来控制占空比
   timeH = 0xf2; //0xc0 64/256=25% 占空比(溢出) 高电平时间    
   START=1;
     M=1;
  N=1;
  LED=1;
    }
 
   if( voltage>4.052&&voltage<4.167&&(timeL!=0xfd))
    {
   timeL = 0xfd; //PWM模式时他俩用来控制占空比
   timeH = 0xfd; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出)    
   START=1;
     M=1;
  N=1;
  LED=1;
    }


    if( voltage>4.167&&voltage<4.208&&(timeL!=0x60))
   {
   timeL = 0x80; //PWM模式时他俩用来控制占空比
   timeH = 0x80; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出)    
   START=1;
     M=1;
  N=1;
  LED=1;
    }


   if(voltage>4.2050&&voltage<4.235)
   {
    timeL = 0x96; //PWM模式时他俩用来控制占空比
    timeH = 0x96; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出) 
    START=1;
 LED=0;
    }


   ****************************************************/


 


}



 /**********
// 保护函数
   void baohu()
   {
  
      if( voltage>4.231)
    {
     M=0;//过压灯
     N=1;
     LED=1;
    }
   if(voltage<3.501)
    {
    N=0;//欠压灯
 M=1;
 LED=1;
    }


     if( voltage<3.772&&(timeL!=0xcf))
    {
   timeL = 0xcf; //PWM模式时他俩用来控制占空比
   timeH = 0xcf; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出)    
   START=1;
    }


   if( voltage<4.052&&voltage>3.772&&(timeL!=0x60))
    {
   timeL = 0x60; //PWM模式时他俩用来控制占空比
   timeH = 0x60; //0xc0 64/256=25% 占空比(溢出) 高电平时间    
   START=1;
    }
 
   if( voltage>4.052&&voltage<4.167&&(timeL!=0xb0))
    {
   timeL = 0xb0; //PWM模式时他俩用来控制占空比
   timeH = 0xb0; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出)    
   START=1;
    }


   if( voltage>4.167&&voltage<4.218&&(timeL!=0xe0))
   {
   timeL = 0xe0; //PWM模式时他俩用来控制占空比
   timeH = 0xe0; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出)    
   START=1;
    }


   if(voltage>4.220&&(timeL!=0xf2))
   {
    timeL = 0xf2; //PWM模式时他俩用来控制占空比
    timeH = 0xf2; //0xff-0xc0=0x3f  64/256=25% 占空比(溢出) 
    START=1;
 LED=0;
    }


 



 }


***************************/


//延时函数
void delayms(uint k)
{
uint data i,j;
for(i=0;i<k;i++)
  {
    for(j=0;j<600;j++)
     {;}
   }
}


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值