历史上的今天

今天是:2024年10月12日(星期六)

正在发生

2020年10月12日 | 自制BMS监控仪通过485通讯读BMS信息并显示在LCD2004上

发布者:美人如玉剑如虹 来源: 51hei关键字:BMS监控仪  485通讯  BMS信息  LCD2004 手机看文章 扫描二维码
随时随地手机看文章

公司是做锂电池管理系统的,主要是通信用16串锂电池用的保护板(BMS),产品有485接口,可以上传各种测量和告警信息。最近开始学习单片机,自己动手做了一个BMS监控仪,通过485与自家的BMS通讯获取状态信息并显示在LCD2004上。
程序也是自己弄了好久才排除各种bug,现在具备了基本状态信息显示、菜单、16串单体电压显示、各温度显示、BMS状态显示、基本告警信息显示。
这个小产品使用STC89C54RD+,MAX485芯,使用5V升压锂电池供电,在外壳上留出了USB充电接口。
电路原图是自己搞了一个,然后同事帮我画的PCB。制作比较废劲,尤其是壳子不好切割,还把手割伤了。。。
因为工作比较忙,从头到尾断断续续搞了一个来月终于算是完成了,和大家分享一下。

已附上原理图和单片机程序。因自己初学,程序有很多不足,比如没有按模块化编写、逻辑较乱等,希望大家帮忙指点。

制作出来的实物图如下:
     

电路原理图如下:

单片机源程序如下:

#include "STC89C54.h"

#define uint unsigned int

#define uchar unsigned char


uchar code welcome1[]="BMS Monitor";

uchar code welcome2[]="RichPower";

uchar code waiting[]="CONNECTING...";

uchar code menu_table1[]="CELL VOLTAGE"; //12个字符

uchar code menu_table2[]="TEMPERATURE";  //11个字符

uchar code menu_table3[]="BMS STATUS";        //10个字符

uchar code menu_table4[]="ALARM INFO"; //10个字符

uchar code BMSINFO1[20]={0x7E,0x32,0x36,0x30,0x30,0x34,0x36,0x46,0x32,0x45,0x30,0x30,0x32,0x30,0x31,0x46,0x44,0x31,0x45,0x0D};         //询遥测的命令报文

uchar code BMSINFO2[20]={0x7E,0x32,0x36,0x30,0x30,0x34,0x36,0x46,0x34,0x45,0x30,0x30,0x32,0x30,0x31,0x46,0x44,0x31,0x43,0x0D};  //询遥信命令报文

uchar buffer[145]={0};          //用于缓存遥测报文

sbit lcdrs=P2^5;        //指令和数据寄存器选择,高电平时为数据,低电平选择命令

sbit lcdrw=P2^6;        //读写选择,高电平为读,低电平为写

sbit lcden=P2^7;    //使能

sbit lcdbg=P2^4;        //背光,0为开

sbit beep=P2^0;                //蜂鸣器,0为开

sbit key1=P1^0;                //菜单或确认

sbit key2=P1^1;                //上一项

sbit key3=P1^2;                //下一项

sbit key4=P1^3;                //返回或背光开关

bit data datareceived_flag=0,displayclear=1;           //datareceived_flag为遥测报文是否接收完的标志位,current_bit为电流值符号标志位

bit data current_bit,celltemp_unit,envtemp_unit,mostemp_unit;

uchar data num;

uchar data i=0,watchdog=0,end_position;

uint single_max,single_min,totalvoltage,current,totalcap,remaincap;

uint data remaincap2;               

uchar digit0,digit1,digit2,digit3,digit4;                                   //LCD显示数字的万千百十个位

uchar cellnumber,cellnumber_offset,address_offset;                 //串数,串数差,地址偏移量

uchar cappercentage;                                                                         //SOC

uint singlevoltage[15];                                                   //单体电芯电压

uint temperature[5];                                                           //4个电芯温度和环境温度及功率温度

uchar display_mode=0,menu_position=1,singlevoltage_page=1;                         //显示模式



void delayms(uint z)         //延时子程序

{

        uint x,y;

        for(x=z;x>0;x--)

                for(y=110;y>0;y--);

}



void write_com(uchar com)           //LCD1602写命令函数

{

        lcdrs=0;                 //rs低电平为写命令

        P0=com;                        

        delayms(4);

        lcden=1;                 //EN先置高电平

        delayms(4);

        lcden=0;                 //短暂延时后EN置低电平

}

void write_dat(uchar dat)           //LCD1602写数据函数

{

        lcdrs=1;                 //rs高电平为写数据

        P0=dat;

        delayms(4);

        lcden=1;

        delayms(4);

        lcden=0;

}


void UsartInit()           //串口初始化

{

        SCON=0X50;                        //设置为工作方式1

        TMOD=0X20;                        //设置计数器工作方式2

        PCON=0X80;                        //波特率加倍

        TH1=0XFA;                                //计数器初始值设置,注意11.0592Mhz波特率是9600的

        TL1=0XFA;

        ES=1;                                                //打开接收中断

        EA=1;                                                //打开总中断

        TR1=1;                                        //打开计数器

}


void init()                                //LCD初始化及开机界面

{

        lcdrw=0;

        lcden=0;

        P0=0;

        write_com(0x38);

        write_com(0x0f);   //初始化,开显示,开光标,开光标闪烁

        write_com(0x06);   //初始化,读写一个字符后地址指针自动加1

        write_com(0x01);   //清屏

//        write_com(0x80);   //数据地址指针从0开始

        lcdbg=0;                   //开背光

        write_com(0x0C);        //关光标

/**********************欢迎界面**************************/

        write_com(0x80+0x44);  //第2行第5个字符

        for(num=0;num<11;num++)

        write_dat(welcome1[num]);

        write_com(0x94+0x05);         //第3行第6个字符

        for(num=0;num<9;num++)

        write_dat(welcome2[num]);

        delayms(1000);

        beep=0;

        delayms(60);

        beep=1;

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

}


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

计算报文缓存中的一个字节

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

uchar buffer_byte_process(uchar buffer_address)

{

        uchar byte_value;

        if(buffer[buffer_address]<=0x39)

                buffer[buffer_address]=buffer[buffer_address]-0x30;        //若为0~9的字符,减0x30即为数值

        else

                buffer[buffer_address]=buffer[buffer_address]-0x37;        //若为大于9即为A~F的字符,减0x37即为数值

        if(buffer[buffer_address+1]<=0x39)

                buffer[buffer_address+1]=buffer[buffer_address+1]-0x30;

        else

                buffer[buffer_address+1]=buffer[buffer_address+1]-0x37;

        byte_value=(buffer[buffer_address]<<4)|buffer[buffer_address+1];               

        return byte_value;

}


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

计算报文缓存中的一个字

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

uint buffer_word_process(uchar buffer_address)

{

        uint word_value;

        if(buffer[buffer_address]<=0x39)

                buffer[buffer_address]=buffer[buffer_address]-0x30;        //若为0~9的字符,减0x30即为数值

        else

                buffer[buffer_address]=buffer[buffer_address]-0x37;        //若为大于9即为A~F的字符,减0x37即为数值

        if(buffer[buffer_address+1]<=0x39)

                buffer[buffer_address+1]=buffer[buffer_address+1]-0x30;

        else

                buffer[buffer_address+1]=buffer[buffer_address+1]-0x37;

        if(buffer[buffer_address+2]<=0x39)

                buffer[buffer_address+2]=buffer[buffer_address+2]-0x30;        //若为0~9的字符,减0x30即为数值

        else

                buffer[buffer_address+2]=buffer[buffer_address+2]-0x37;        //若为大于9即为A~F的字符,减0x37即为数值

[1] [2] [3]
关键字:BMS监控仪  485通讯  BMS信息  LCD2004 引用地址:自制BMS监控仪通过485通讯读BMS信息并显示在LCD2004上

上一篇:单片机非接触式智能测温系统程序
下一篇:单片机动态数码管显示DS18B20测温显示程序

推荐阅读

佳能近日在美国注册了一款与360°全景相机相关的专利技术。从专利描述文件上看,这款设备共有八个可实现独立变焦的相机组成,并可以将各自拍摄的图片进行叠加拼接成一张完整的照片。除了可拍摄360°的影响外,这款相机也支持全景影像拍摄。此外,这款相机还配备有三脚架便于放置,以及支持通过电脑和手机进行无线操控。或许,佳能会在明年一月的CES展会上...
电磁流量计在各行业上的应用主要有三种:*、大口径仪表较多应用于给排水工程;第二、中小口径常用于固液双相等难测流体或高要求场所;如测量造纸工业纸浆液和黑液、有色冶金业的矿浆、选煤厂的煤浆、化学工业的强腐蚀液以及钢铁工业高炉风口冷却水控制和监漏,长距离管道煤的水力输送的流量测量和控制。第三、小口径、微小口径;常用于医药工业、食品工业...
根据博主 Kang 此前的消息,iPhone 12 机型可能会支持「智能数据模式」,即可以在 4G 和 5G 之间无缝切换。而且该过程是完全自动的,整个过程会在后台进行。接下来不妨让我们进一步了解它的工作模式。苹果将为 iPhone 12 的系列带来 5G 连接。但是,mmWave 支持的 iPhone 12 型号将仅在美国销售,其余地区将支持 sub-6GHz 5G。而苹果将...
  活塞式电磁阀的工作原理  常闭:当线圈通电时,电磁铁芯吸合,卸压孔打开,主活塞由由介质压力推动,打开主阀口,介质流通。  当线圈断电时,主阀口关闭,介质截止。  常开:当线圈通电时,电磁铁芯吸合,卸压孔关闭,主活塞由介质压力推动,关闭主阀口,介质截止。  当线圈断电时,主阀口打开,介质流通。    活塞式电磁阀的特点  1、...

史海拾趣

问答坊 | AI 解惑

ISE综合错误:Failed to synthesize logic for signal

最近用ISE写个频率计的verilog程序 ,  下面这个报错弄了很久没发现错在哪,在quartus里综合能通过,但在ISE里综合就不行,能哪位大虾能指点一二吗?不胜感激!`timescale 1ns / 1psmodule plj(clk,clk_test,sw0,sw1,rst,out_wei,ou ...…

查看全部问答∨

mooncmy 请进

呵呵,找你帮个忙,QQ上聊:85457796…

查看全部问答∨

hostapd 配置

使用hostapd如何配置ap,…

查看全部问答∨

关于系统线程的两个问题

关于系统线程的两个问题 1.进程列表里有个System进程,系统线程是属于这个进程吗? 2.系统线程和系统工作者线程,有啥区别呢…

查看全部问答∨

关于语音的问题

我想将语音采集下来后进行传输,选用什么语音芯片比较好 …

查看全部问答∨

STM32F103ZCT6用KEIL调试怪事情

这两天用STM32F103ZCT6开发碰到怪事了:我用KEIL + JLINK II进行开发,在编译好以,下载到我的片上,用反汇编看烧写下去的代码,会有一段区域是全1,也就是代码没有烧写成功,不知为什么1!!开始怀疑是这个扇区坏了,但用别一 ...…

查看全部问答∨

SCI发送16位数据

我的AD采集到的是16位的有符号整数,我想通过串口发送,但SCI编程后接收到的数据只是16位数据的低8位,请问我该怎么修改程序?…

查看全部问答∨

初学者,请教各位一个很蹊跷的问题

#include <MSP430x14x.h> void main (void) { int i; int array[]={1,2,3,4,5}; int l=1; while(1) { switch (l) { case 1:i=array[l];break; case 2:i=array[l];break; ...…

查看全部问答∨

内置扫描生成能力支持更快的吞吐量和精密定时控制1

Flexibility has been one of the advantages Series 2600instruments provided. Such flexibility was due in part to theirindependence from a rigid trigger model, which was common to SCPI-based instrumentation. However, using a tri ...…

查看全部问答∨

安防招聘 安防求职 安防人才网-安防英才网

安防英才网讯10月31日,由广东省公共安全技术防范协会与深圳市安全防范行业协会主办,广东省公安厅安全技术防范办公室协办的“2012年中国广东国际社会公共安全产品博览会”(下称“广东安博会”)新闻发布会在深圳国际会展中心召开。会议通报了2012 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved