找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 687|回复: 3
打印 上一主题 下一主题
收起左侧

铅酸蓄电池放电容量测试仪电路及软件设计求指点

[复制链接]
跳转到指定楼层
楼主
电路采用改变PWM占空比达到恒流放电,软件是很简单的算法。PROTEUS已仿真(非常卡顿且要过好一阵虚拟示波器才能出波形)。因水平有限电路及软件这样设计不知是否正确,寻求意见,若能完善再DIY.
以下是源代码
#include <reg51.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
/**********1602************/
sbit RS=P1^5;
sbit EN=P1^4;
sbit LCD_D4=P1^3;
sbit LCD_D5=P1^2;
sbit LCD_D6=P1^1;
sbit LCD_D7=P1^0;

sbit SW=P3^2;
sbit PWM_OUT=P3^3;
sbit FMQ=P3^7;
/*********ADC0832**********/
sbit  CS  = P3^4;
sbit  CLK = P3^5;
sbit  DI0 = P3^1;
sbit  WCS  = P3^0;
sbit  WCLK = P1^6;
sbit  WDI0 = P1^7;
//---------------------------
unsigned char Data[8];
unsigned char Table[]="0123456789";
unsigned char hour=0;//小时
unsigned char min=0;//分钟
unsigned char miao=0;//秒
unsigned char mstn=0;//50ms计数
bit ptt=0;//秒闪烁标志
unsigned long AH=0;
unsigned int num=0;
/********以下是函数声明********/
void LCD_en_write(void);//液晶使能
void LCD_by(uchar abc);//写字节
void LCD_set_xy(uchar x, uchar y);//写地址
void LCD_write_str(uchar X,uchar Y,uchar *s);//写字符串
void LCD_init(void);//液晶初始化
void del_ms(uint n);//ms延时函数
void delay_5us(void);//5us延时函数
void delay_nus(uint n);//N us延时函数
void process_3(unsigned long i,unsigned char *p) ;
void display_AH(unsigned char x, unsigned char y, unsigned char *p);
void Timer0_Init(void);
void Timer1_Init(void);
void display_SJ(uchar x,uchar y,uchar hour,uchar min);//时间显示函数
void display_V(unsigned char x, unsigned char y, uchar *p);
void display_A(unsigned char x, unsigned char y, uchar *p);
uchar V_A();//电压/电流采集函数
uchar SET_A();//电流调节采集函数
//-----------------------------------------
uchar V_A(bit CH)//电压/电流采集函数
{
  uchar i,dat,dat2;
  CS=0;
  _nop_();
  DI0=1;
  CLK=1;
  _nop_();
  CLK=0;
  _nop_();
   DI0=1;
  CLK=1;
  _nop_();
  CLK=0;
  _nop_();
        if(CH==0)
        {
         DI0=0;//V
        }
        if(CH==1)
        {
         DI0=1;//A
        }
  CLK=1;
  _nop_();
  CLK=0;
  DI0=1;
  dat=0;
  for(i=0;i<8;i++)
     {
       dat<<=1;
       CLK=1;
       _nop_();
       CLK=0;
       _nop_();
       dat|=DI0;
     }
     dat2=0;
   if(DI0==1)
     dat2=0x80;
   for(i=0;i<7;i++)
      {
        dat2>>=1;
        CLK=1;
        _nop_();
        CLK=0;
        _nop_();
        if(DI0==1)
        dat2|=0x80;
      }
    CS=1;
    CLK=0;
    DI0=1;
    if(dat==dat2)
    return(dat);
    else
    return 0;
}
//--------------------------
uchar SET_A()//电流调节采集函数
{
  uchar i,dat,dat2;
  WCS=0;
  _nop_();
  WDI0=1;
  WCLK=1;
  _nop_();
  WCLK=0;
  _nop_();
  WDI0=1;
  WCLK=1;
  _nop_();
  WCLK=0;
  _nop_();
  WDI0=0;//
  WCLK=1;
  _nop_();
  WCLK=0;
  WDI0=1;
  dat=0;
  for(i=0;i<8;i++)
     {
       dat<<=1;
       WCLK=1;
       _nop_();
       WCLK=0;
       _nop_();
       dat|=WDI0;
     }
     dat2=0;
   if(WDI0==1)
     dat2=0x80;
   for(i=0;i<7;i++)
      {
        dat2>>=1;
        WCLK=1;
        _nop_();
        WCLK=0;
        _nop_();
        if(WDI0==1)
        dat2|=0x80;
      }
    WCS=1;
    WCLK=0;
    WDI0=1;
    if(dat==dat2)
    return(dat);
    else
    return 0;
}
//--------------------------
void display_SJ(uchar x,uchar y,uchar hour,uchar min)
{
  unsigned char q[2];
  unsigned char w[2];
  q[0]=hour/10;
  q[1]=hour%10;
  w[0]=min/10;
  w[1]=min%10;
  LCD_set_xy( x, y );
  RS=1;            
  LCD_by(Table[q[0]]);
  LCD_by(Table[q[1]]);
  if(ptt==1||SW==1)
    {  
      LCD_write_str(13,0,":");//秒闪烁
    }
    else
    {
      LCD_write_str(13,0," ");
    }
  LCD_by(Table[w[0]]);
  LCD_by(Table[w[1]]);
}
//-----------------------------------------
void process_3(unsigned long i,uchar *p)
{
  p[0]=i/100%10;
  p[1]=i/10%10;
  p[2]=i%10;
}
//--------------------------------------------------------
void display_AH(unsigned char x, unsigned char y, uchar *p)
{
  unsigned char i;
  LCD_set_xy( x, y );
  RS=1;         
  for(i=0;i<3;i++)
  {
    if(i==2)
    {
      LCD_write_str(12,1,".");
    }
      LCD_by(Table[p[i]]);
  }
}
//---------------------------------------------
void display_V(unsigned char x, unsigned char y, uchar *p)
{
  unsigned char i;
  LCD_set_xy( x, y );
  RS=1;         
  for(i=0;i<3;i++)
  {
    if(i==2)
    {
      LCD_write_str(3,0,".");
    }
      LCD_by(Table[p[i]]);
  }
}
//---------------------------------------------
void display_A(unsigned char x, unsigned char y, uchar *p)
{
  unsigned char i;
  LCD_set_xy( x, y );
  RS=1;         
  for(i=0;i<3;i++)
  {
    if(i==2)
    {
      LCD_write_str(3,1,".");
    }
      LCD_by(Table[p[i]]);
  }
}
//---------------------------------------------
void LCD_en_write(void)
{
     delay_5us();
     EN=1;        
     delay_5us();
     EN=0;        
}
//---------------------------------------
void LCD_by(uchar abc)
{
    delay_nus(500);
    if(((abc<<0)&0x80)==0)     
     LCD_D7=0;            
     else LCD_D7=1;         
    if(((abc<<1)&0x80)==0)     
     LCD_D6=0;              
     else LCD_D6=1;        
    if(((abc<<2)&0x80)==0)     
     LCD_D5=0;              
     else LCD_D5=1;        
    if(((abc<<3)&0x80)==0)     
     LCD_D4=0;              
     else LCD_D4=1;        
    LCD_en_write();

    if(((abc<<4)&0x80)==0)     
     LCD_D7=0;              
     else LCD_D7=1;         
    if(((abc<<5)&0x80)==0)     
     LCD_D6=0;              
     else LCD_D6=1;         
    if(((abc<<6)&0x80)==0)     
     LCD_D5=0;              
     else LCD_D5=1;         
    if(((abc<<7)&0x80)==0)     
     LCD_D4=0;              
     else LCD_D4=1;         
    LCD_en_write();
}
//----------------------------------------------
void LCD_set_xy( uchar x, uchar y )
  {
    uchar address;
    if (y == 0) address = 0x80 + x;
    else
    address = 0xc0 + x;
    RS=0;           
    LCD_by(address);
  }
//---------------------------------------------
void LCD_write_str(uchar X,uchar Y,uchar *s)
  {
    LCD_set_xy(X,Y);
    RS=1;
    while(*s)
    {
       LCD_by(*s);
       s++;
    }
  }
//------------------------------------
void LCD_init(void)     
{
    RS=0;            
    del_ms(500);

    LCD_by(0x30);
    del_ms(60);
    LCD_by(0x30);
    del_ms(10);
    LCD_by(0x30);
    del_ms(10);
    LCD_by(0x02);
    del_ms(10);
    LCD_by(0x28);
    del_ms(10);
    LCD_by(0x08);
    del_ms(10);
    LCD_by(0x01);
    del_ms(10);
    LCD_by(0x06);
    del_ms(10);
    LCD_by(0x0C);
    del_ms(100);
}
//----------------------------------------------
void delay_nus(uint n)//N us延时函数
  {
   uint i=0;
   for (i=0;i<n;i++){;}
  }
//------------------------------
void delay_5us(void)//@12.000MHz//5us延时函数
{
   unsigned char data i;

   _nop_();
   _nop_();
   i = 12;
   while (--i);
}

//------------------------------
void del_ms(uint n)//ms延时函数
{
   uchar j;
   while(n--)
  {for(j=0;j<125;j++);}
}
//------------------------------
void Timer1_Init(void)                //50毫秒@12.000MHz
{
        TMOD &= 0x0F;                       
        TL1 = 0xB0;                               
        TH1 = 0x3C;                               
        TF1 = 0;                               
}
//-------------------------------
void Timer0_Init(void)                //4微秒@12.000MHz
{
        TMOD &= 0xF0;                       
        TL0 = 0xFC;                               
        TH0 = 0xFF;                               
        TF0 = 0;                               
}
//-------------------------------
void timer1(void) interrupt 3
{
      TL1 = 0xB0;                               
      TH1 = 0x3C;                               
      TF1 = 0;                       
      mstn++;     
      if(mstn==20)
        {
          mstn=0;
          miao++;
          ptt=~ptt;
          if(miao==60)
            {
               miao=0;
               min++;
               if(min==60)
                 {
                   min=0;
                   hour++;
                   if(hour==100)
                     {
                       hour=100;
                     }
                 }
            }
        }
}
//-------------------------------
void timer0(void) interrupt 1
{
     static unsigned char count=0;
     TL0 = 0xFC;                //4us               
     TH0 = 0xFF;                               
     TF0=0;
     count++;
     if(count>=255)count=0;//4us*255=1020us
     if(count>=num)PWM_OUT=1;//改变占空比
     else PWM_OUT=0;//调整电流
}
//-------------------------------
void main(void)
{
         uchar Set_A=0;
         uchar Batt_A=0;
         uchar Batt_V=0;
         uchar A_A=0;
         uchar V_V=0;
         ulong AH=0;
       
         LCD_init();
         del_ms(10);
         Timer0_Init();
         del_ms(10);
         Timer1_Init();
         del_ms(10);
         FMQ=1;
         PWM_OUT=1;
         ET0=1;
         ET1=1;
         EA=1;
       
         while(1)
         {
                  Set_A=SET_A();//电流调节
                  V_V=V_A(0);
                  Batt_V=V_V*200./255;//电池电压
                  A_A=V_A(1);
                  Batt_A=A_A*200./255;//放电电流
                 
                  if(SW==1)//停止
                  {
                          TR0=0;
                          TR1=0;
                          PWM_OUT=1;//放电MOS管截止
                  }
                  if(SW==0)//开始
                  {
                          TR0=1;
                          TR1=1;
                          num=num+(Set_A-A_A)/2;//恒流放电
                  }
                    
                    if(V_V<=108)//12V电池放电截止
                                {
                          //        while(1)//加上这段仿真会停止
                                //        {
                                //          TR0=0;
                                //          TR1=0;
                                //          PWM_OUT=1;
                                //          FMQ=0;//蜂鸣器响
                                //        }   
                                }   
                 
                                AH=hour*60+min;//放电容量计算
                                AH*=Batt_A;
                                AH/=60;
                 
                           display_SJ(11,0,hour,min);//时间

                          process_3(AH,Data);
                          display_AH(10,1,Data);//容量
                          LCD_write_str(14,1,"AH");
                 
                          process_3(Batt_V,Data);
                          display_V(1,0,Data);//电压
                          LCD_write_str(5,0,"V");
                 
                          process_3(Batt_A,Data);
                          display_A(1,1,Data);//电流
                          LCD_write_str(5,1,"A");
         }
}

2345截图20250203132158.png (145.58 KB, 下载次数: 0)

2345截图20250203132158.png

2345截图20250203130927.png (43.32 KB, 下载次数: 0)

2345截图20250203130927.png

铅酸蓄电池放电容量测试仪.zip

167.08 KB, 下载次数: 0, 下载积分: 黑币 -5

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:469589 发表于 2025-2-8 13:54 | 只看该作者
R5、R9对于12V不构成短路吗???
回复

使用道具 举报

板凳
ID:1136941 发表于 2025-2-9 11:07 | 只看该作者
GlenXu 发表于 2025-2-8 13:54
R5、R9对于12V不构成短路吗???

12V/R5+R9约等于24A(峰值),1ms周期内改变占空比就可改变平均电流,我是这样考虑的,不知道对不对。
回复

使用道具 举报

无效楼层,该帖已经被删除
5#
ID:1136941 发表于 2025-2-10 10:37 | 只看该作者
GlenXu 发表于 2025-2-8 13:54
R5、R9对于12V不构成短路吗???

12V/R5+R9=24A(峰值电流),改变占空比也就改变了平均电流,我是这样考虑的,不知道对不对。
回复

使用道具 举报

6#
无效楼层,该帖已经被删除
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表