找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 35|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

DIY車用鉛酸蓄電池智能充電機(jī)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1136941 發(fā)表于 2025-6-27 17:55 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
地處北方,冬季車輛易虧電啟動困難,需要補(bǔ)充充電。利用手頭的老物件AT89C4051,ADC0832制作控制電路,IO口有限使用了PFC8574T驅(qū)動1602顯示。兩個工作模式,三段自動充電模式(充足自動轉(zhuǎn)為浮充)和定時充電模式(恒流充電)。制作完成才發(fā)現(xiàn)PCF8574T驅(qū)動1602顯示刷新太慢了影響響應(yīng)速度,待充電主回路完成再聯(lián)調(diào)。
#include <reg51.h>
#include <intrins.h>

#define PCF_ADDR 0x4E  //PCF8574T地址
unsigned char Data[3];
unsigned char Table[]="0123456789";
unsigned int delay_time;

long z=0;
unsigned char j;
unsigned char k;
unsigned char h;
unsigned char f;
unsigned char Set_A;
unsigned char Batt_V;
unsigned char Batt_A;
unsigned char JD=0;
unsigned char IS=0;

char hour=1;
char min=0;
char miao=59;
char count=0;
bit  ptt=1;
sbit triac = P3^1;   // 可控硅控制引腳
sbit ON_OFF = P3^7;    //啟動停止開關(guān)
sbit MODE = P3^3;      //模式
sbit JIA = P3^4;       //加時間
sbit JIAN = P3^5;      //減時間
sbit FMQ = P3^0;       //蜂鳴器
sbit SCL = P1^1;     // I2C時鐘線
sbit SDA = P1^0;     // I2C數(shù)據(jù)線
sbit CS = P1^5;
sbit CLK = P1^6;
sbit DI0 = P1^7;
sbit WCS = P1^2;
sbit WCLK = P1^3;
sbit WDI0 = P1^4;
//----------函數(shù)聲明----------------------------
void process_3(unsigned int i,unsigned char *p) ;
void display(unsigned char *p);
void delay_us(unsigned int us);
void delay_ms(unsigned int ms);
void I2C_Start();
void I2C_Stop();
void I2C_WriteByte(unsigned char dat);
void PCF8574_Write(unsigned char dat);
void lcd_send_nibble(unsigned char nibble, unsigned char rs);
void lcd_send_byte(unsigned char dat, bit rs);
void lcd_init();
void lcd_set_cursor(unsigned char row, unsigned char col);
void lcd_write_string(char *str);
void init();
void display_SJ(unsigned char hour,unsigned char min);
unsigned char Current();
unsigned char V_SetA(bit CH);   
//---------------------------------------------
unsigned char V_SetA(bit CH)//
{
  unsigned char 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)//0通道/設(shè)置電流
{
   DI0=0;
}
if(CH==1)//1通道/電壓
{
   DI0=1;
}
  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;
}
//--------------------------
unsigned char Current()//0通道/電流
{
  unsigned char i,dat,dat2;
  WCS=0;
  _nop_();
  WDI0=1;
  WCLK=1;
  _nop_();
  WCLK=0;
  _nop_();
  WDI0=1;
  WCLK=1;
  _nop_();
  WCLK=0;
  _nop_();
  WDI0=0;//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 process_3(unsigned int i,unsigned char *p)
{
  p[0]=i/100%10;
  p[1]=i/10%10;
  p[2]=i%10;
}
//----------------------------
/*3位數(shù)顯示函數(shù)*/
void display(unsigned char *p)
{
  unsigned char i;
          
  for(i=0;i<3;i++)
  {
    if(i==2)
    {
        lcd_write_string(".");
    }
        lcd_send_byte(Table[p[i]], 1);
  }
}
//------------------------------
void delay_us(unsigned int us) {
    while (us--) {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
}
//------------------------------
void delay_ms(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 114; j++);
}
//------------------------------
void I2C_Start() {
    SDA = 1;
    SCL = 1;
    delay_us(5);
    SDA = 0;
    delay_us(5);
    SCL = 0;
}
//-----------------
void I2C_Stop() {
    SDA = 0;
    SCL = 1;
    delay_us(5);
    SDA = 1;
    delay_us(5);
}
//-------------------------------------
void I2C_WriteByte(unsigned char dat) {
    unsigned char i;
    for (i = 0; i < 8; i++) {
        SDA = (dat & 0x80) ? 1 : 0;
        dat <<= 1;
        SCL = 1;
        delay_us(5);
        SCL = 0;
        delay_us(5);
    }
    SDA = 1;  // 釋放總線等待ACK
    SCL = 1;
    delay_us(5);
    SCL = 0;
}
//------------------------------------
void PCF8574_Write(unsigned char dat) {
    I2C_Start();
    I2C_WriteByte(PCF_ADDR);
    I2C_WriteByte(dat);
    I2C_Stop();
}
//------------------------------------------------------------
void lcd_send_nibble(unsigned char nibble, unsigned char rs) {
    unsigned char data_pcf;
    // 數(shù)據(jù)位: P4-P7, RS: P0, E: P2, Backlight: P3 (開啟)
    data_pcf = (nibble << 4) | (rs << 0) | (1 << 3);
    // E下降沿
    PCF8574_Write(data_pcf & ~(1 << 2)); // E=0
    delay_us(1);
    PCF8574_Write(data_pcf | (1 << 2));  // E=1
    delay_us(1);
    PCF8574_Write(data_pcf & ~(1 << 2)); // E=0
    delay_us(100);
}
//---------------------------------------------
void lcd_send_byte(unsigned char dat, bit rs) {
    lcd_send_nibble(dat >> 4, rs); // 高四位
    lcd_send_nibble(dat & 0x0F, rs); // 低四位
}
//--------------------------
void lcd_init() {
    delay_ms(50);
    lcd_send_nibble(0x03, 0);
    delay_ms(5);
    lcd_send_nibble(0x03, 0);
    delay_ms(1);
    lcd_send_nibble(0x03, 0);
    delay_us(100);
    lcd_send_nibble(0x02, 0);
    delay_us(100);
    lcd_send_byte(0x28, 0); // 4位, 2行, 5x8
    delay_us(100);
    lcd_send_byte(0x0C, 0); // 顯示開, 光標(biāo)關(guān)
    delay_us(100);
    lcd_send_byte(0x06, 0); // 增量不移屏
    delay_us(100);
    lcd_send_byte(0x01, 0); // 清屏
    delay_ms(2);
}
//---------------------------------------------------------
void lcd_set_cursor(unsigned char col, unsigned char row) {
    unsigned char address = (row == 0) ? 0x80 : 0xC0;
    lcd_send_byte(address + col, 0);
}
//-----------------------------------
void lcd_write_string(char *str) {
    while (*str) {
        lcd_send_byte(*str++, 1);
    }
}
//--------------------------
void display_SJ(unsigned char hour,unsigned char min)//時間顯示
{
        unsigned int i;
  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_send_byte(Table[q[0]],1);
  lcd_send_byte(Table[q[1]],1);
  if(ptt==1||ON_OFF==1)
    {
      lcd_set_cursor( 13, 0 );
      lcd_write_string(":");//秒閃爍
    }
    else
    {
      lcd_write_string(" ");
    }
  lcd_send_byte(Table[w[0]],1);
  lcd_send_byte(Table[w[1]],1);
               
        if(hour==0&&min==0)//定時到
        {
                  TR1=0;
                  TR0=0;
                  ET1=0;
                  ET0=0;
                  EX0=0;
                  EA=0;
                  triac = 1;    // 關(guān)閉脈沖
                        for(i=0;i<400;i++)
                        {
                                FMQ=0;
                                delay_ms(120);
                                FMQ=1;
                               
                                lcd_set_cursor( 13, 0 );
                           lcd_write_string(":");
                               
                          j=V_SetA(0);//設(shè)置電流
                          Set_A=j*200./255;
                          k=V_SetA(1);//電壓
                          Batt_V=k*200./255;
                          h=Current();//電流
                          Batt_A=h*200./255;
                       
                          lcd_set_cursor(4, 0);
                          process_3(Set_A,Data);
                          display(Data);//設(shè)置電流
                       
                          lcd_set_cursor(0, 1);
                          process_3(Batt_V,Data);
                          display(Data);//電壓
                       
                          lcd_set_cursor(11, 1);
                          process_3(Batt_A,Data);
                          display(Data);//電流
                        }
                 while(1)
                        {
                                j=V_SetA(0);//設(shè)置電流
                          Set_A=j*200./255;
                          k=V_SetA(1);//電壓
                          Batt_V=k*200./255;
                          h=Current();//電流
                          Batt_A=h*200./255;
                       
                          lcd_set_cursor(4, 0);
                          process_3(Set_A,Data);
                          display(Data);//設(shè)置電流
                       
                          lcd_set_cursor(0, 1);
                          process_3(Batt_V,Data);
                          display(Data);//電壓
                       
                          lcd_set_cursor(11, 1);
                          process_3(Batt_A,Data);
                          display(Data);//電流
                        }
        }               
}
//-----------------------------------
void init() {
          IT0 = 1;         // INT0(P3.2)下降沿觸發(fā)模式
          EX0 = 1;         // 允許INT0中斷
       
          TMOD=0x11;
         
          ET0 = 1;         // 允許定時器0中斷

          TL1 = (65536-50000)%256;                               
          TH1 = (65536-50000)/256;

          ET1 = 1;
          TF1 = 0;
          EA = 0;
          //    EA = 1;          // 開啟總中斷
}

/* 主函數(shù) */
void main()
{   
          bit a=0;
          bit b=0;
          bit c=0;
          bit x=0;
          
          unsigned char i;
          unsigned char t;
       
          triac = 1;    // 關(guān)閉脈沖
          init();       
          lcd_init();
          
          lcd_set_cursor(4, 0);
          lcd_write_string("Hello!!!");
       
          for(i=0;i<5;i++)
                        {
                                FMQ=0;
                                delay_ms(250);
                                FMQ=1;
                                delay_ms(250);
                        }
       
          if(ON_OFF==0)//開關(guān)在啟動檔
                {
                        lcd_send_byte(0x01, 0); // 清屏
                        while(1)
                        {
                           FMQ=0;
                          lcd_set_cursor(3, 0);
                          lcd_write_string("Error!!!");
                        }
                }

                for(i=0;i<5;i++)
                        {
                          delay_ms(20);
                          k=V_SetA(1);
                        }
                Batt_V=k*200./255;
                if(Batt_V==0)//電池沒接或反接
                {
                        lcd_send_byte(0x01, 0); // 清屏
                        while(1)
                        {
                          FMQ=0;
                          lcd_set_cursor(3, 0);
                          lcd_write_string("Error!!!");
                        }
                }   
               
          lcd_send_byte(0x01, 0); // 清屏               
          lcd_set_cursor(0, 0);
          lcd_write_string("Set:");
          lcd_set_cursor(8, 0);
          lcd_write_string("A");//設(shè)置電流
          lcd_set_cursor(4, 1);
          lcd_write_string("V");//電壓
          lcd_set_cursor(15, 1);
          lcd_write_string("A");//電流
               
    while(1)
                {
                         lcd_set_cursor(4, 0);
                         process_3(Set_A,Data);
                         display(Data);//設(shè)置電流       
                       
                         lcd_set_cursor(0, 1);
                         process_3(Batt_V,Data);
                         display(Data);//電壓
                       
                         lcd_set_cursor(11, 1);
                         process_3(Batt_A,Data);
                         display(Data);//電流
                       
                         f=V_SetA(0);//設(shè)置電流
                         j=f;
                         if(JD==0)j=j;//第一階段恒流
                         if(JD==1)j=j/2;//第二階段恒流電流減半
                         if(JD==2);//第三階段恒壓
                         Set_A=j*200./255;
                         k=V_SetA(1);//電壓
                         Batt_V=k*300./255;
                         h=Current();//電流
                         Batt_A=h*200./255;
                         
                         if(k==0)//電池開路
                         {
                                 lcd_send_byte(0x01, 0); // 清屏
                           while(1)
                           {
                              TR0=0;
                              ET0=0;
                              EX0=0;
                              EA=0;
                              triac = 1;    // 關(guān)閉脈沖
                              FMQ=0;
                              lcd_set_cursor(3, 0);
                              lcd_write_string("Error!!!");
                           }
                   }     
                         
                         if(Batt_A>=200)//20.0A過流
                         {
                                FMQ=0;     
                         }
                         else
                         {
                                 FMQ=1;
                         }
                 
         if(ON_OFF==0)//啟動
                 {
                         if(x==0)
                         {
                                 FMQ=0;
                                 delay_ms(250);
                                 FMQ=1;
                                 x=1;
                         }
                   EA=1;
                 if(IS==0)//非定時
                 {
                         if((Batt_V<138)&&a==0)//第一階段恒流
                         {
                                 a=1;
                                 JD=0;
                         }
                         if(((Batt_V>=138)&&(Batt_V<143))&&b==0)//第二階段恒流
                         {
                                 b=1;
                                 JD=1;
                         }
                         if((Batt_V>=143)&&c==0)//第三階段恒壓14.3V
                         {
                                 c=1;
                                 JD=2;
                         }
                         
                   switch(JD)
                   {
                           case 0:
                                 z=z+(j-h)*2;//第一階段恒流
                                 if(z<100)z=100;
                                 if(z>8160)z=8160;
                                 delay_time=10000-z;
                           break;
                         
                           case 1:
                                 z=z+(j-h)*2;//第二階段恒流
                                 if(z<100)z=100;
                                 if(z>8160)z=8160;
                                 delay_time=10000-z;
                           break;
                         
                           case 2:
                                  z=z+(k-183)*2;//第三階段恒壓14.3V
                                 if(z<100)z=100;
                                 if(z>8160)z=8160;
                                 delay_time=10000-z;
                                 
                                 t++;
                                 if(t==10)FMQ=0;
                                 if(t==11)FMQ=1;
                                 if(t==120)t=0;
                                 
                           break;
                         
                           default:
                           break;
                   }
                  }
                  else  //定時
                        {
                                TR1=1;
                                z=z+(f-h)*2;//恒流
                                if(z<100)z=100;
                                if(z>8160)z=8160;//255*32=8160
                                delay_time=10000-z;
                        //        delay_time=10000-(f*32);
                        }
                }        

                 if(ON_OFF==1)//停止
                 {
                         t=0;
                         x=0;
                         EA=0;
                         triac = 1;    // 關(guān)閉脈沖
                         
                         if(IS==1)
                         {
                                 TR1=0;
                         }
                         
                         if(JIA==0)//定時加
       {
         FMQ=0;
         delay_ms(100);
         FMQ=1;
         if(JIA==0)
         {
           hour++;
           if(hour>99)
           {
             hour=99;
           }
          }
          while(JIA==0);
        }
        if(JIAN==0)//定時減
        {
          FMQ=0;
          delay_ms(100);
          FMQ=1;
          if(JIAN==0)
          {
            hour--;
            if(hour<1)
            {
              hour=1;
            }
           }
           while(JIAN==0);
          }
                                 
         if(MODE==0)//模式
         {
            FMQ=0;
            delay_ms(100);
            FMQ=1;
            if(MODE==0)
            {
              IS++;
              while(MODE==0);
              if(IS>1)
              {
                IS=0;
              }
             }
          }
         }
                 
                 if(IS==0)
                 {
                         lcd_set_cursor(11, 0);
                         lcd_write_string("--:--");
                 }
                 if(IS==1)
                 {
                         lcd_set_cursor(11, 0);
                         display_SJ(hour,min);//時間
                 }
     }
}

/* INT0中斷服務(wù)函數(shù) */
void int0_isr() interrupt 0
{
    TR0 = 0;         // 停止定時器0
    // 計算定時器初值(12MHz晶振,1us計數(shù))
    TH0 = (65536 - delay_time) /256;  // 高字節(jié)
    TL0 = (65536 - delay_time) %256;// 低字節(jié)
    TR0 = 1;         // 啟動定時器0      
}

/* 定時器0中斷服務(wù)函數(shù) */
void timer0_isr() interrupt 1
{
          static unsigned char i;
    TR0 = 0;         // 停止定時器0
    triac = 0;       // 觸發(fā)可控硅     
    // 短暫延時確保觸發(fā)(約10us,根據(jù)實際需求調(diào)整)
    for(i = 0; i < 10; i++); // 粗略延時
    triac = 1;       // 關(guān)閉脈沖

}

/* 定時器1中斷服務(wù)函數(shù) */
void timer1(void) interrupt 3
{
      TL1 = 0xB0;                               
      TH1 = 0x3C;                               
      TF1 = 0;                       
      count++;     
      if(count==20)
        {
          count=0;
          miao--;
          ptt=~ptt;
          if(miao<0)
            {
               miao=59;
               min--;
               if(min<0)
                 {
                   min=59;
                   hour--;
                   if(hour<0)
                     {
                       hour=0;
                     }
                 }
            }
        }
}

2345截圖20250627164926.png (74.8 KB, 下載次數(shù): 0)

2345截圖20250627164926.png

IMG_20250627_164031.jpg (1.98 MB, 下載次數(shù): 0)

IMG_20250627_164031.jpg

評分

參與人數(shù) 2黑幣 +60 收起 理由
waerdeng + 10 共享資料的獎勵!
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表