- /**********************************************
- * 功能:LED显示锂电池容量检测
- * 编程:ztzp
- * 日期:2020-04-14
- * P0 段码控制
- * P2 位码控制
- * P1 5位拨码开关,决定放电电流。
- **********************************************/
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define ulong unsigned long
- sfr T2MOD = 0xC9; //使用定时器2必须定义,T2MOD的地址。
- float Iout; //放电电流,与预设值相关。
- float Sum; //放电量累加值
- ulong S; //放电量四舍五入后转换为整数
- uchar S1; //第一位
- uchar S2; //第二位
- uchar S3; //第三位
- uint i; //1秒钟计时变量
- uint State = 0; //计数状态,0开始计数;1停止计数。此值由外部中断0控制。
- sbit LED_R = P3^6; //红色LED,表示正在放电,低电平有效。
- sbit LED_G = P3^7; //绿色LED,表示停止放电,低电平有效。
- void init(); //系统初始化
- void init_int0(); //外部中断初始化
- void init_Time2(); //定时器2初始化
- void Show(); //LED数码管显示放电量
- //共阳LED数码管位码(从左到右:1、2、3、4、5、6、7、8)
- //用PNP管驱动
- code uchar WEI_CODE [] =
- {
- 0xFE, //1 11111110
- 0xFD, //2 11111101
- 0xFB, //3 11111011
- 0xF7, //4 11110111
- 0xEF, //5 11101111
- 0xDF, //6 11011111
- 0xBF, //7 10111111
- 0x7F //8 01111111
- };
- //共阳LED数码管段码(带小数点)
- code uchar DSY_CODE [] =
- {
- 0x40, //0
- 0x79, //1
- 0x24, //2
- 0x30, //3
- 0x19, //4
- 0x12, //5
- 0x02, //6
- 0x78, //7
- 0x00, //8
- 0x10 //9
- };
- // 延时 xms(晶振:11.0592MHz,)
- void DelayMS(uint x)
- {
- uchar i;
- while( x-- )
- {
- for( i=0; i<111; i++ );
- }
- }
- //主程序
- void main()
- {
- init(); //系统初始化
- init_int0(); //外部中断初始化
- init_Time2(); //定时器2初始化
- while(1)
- {
- Show(); //显示
- }
- }
- //LED数码管显示放电量(从左到右)
- void Show()
- {
- //第1位
- S = Sum + 0.5; //四舍五入
- S1 = S/10000000;
- if (S1 != 0)
- {
- P2 = WEI_CODE[0];
- P0 = DSY_CODE[S1] + 0x80; //无小数点
- DelayMS(1);
- P2 = 0xFF;
- P0 = 0xFF;
- DelayMS(1);
- }
- //第2位
- S = Sum + 0.5;
- S2 = S%10000000/1000000;
- if (S2 != 0 || S1 != 0) //当第一位不等于0时,第二位必须显示
- {
- P2 = WEI_CODE[1];
- P0 = DSY_CODE[S2] + 0x80;
- DelayMS(1);
- P2 = 0xFF;
- P0 = 0xFF;
- DelayMS(1);
- }
- //第3位
- S = Sum + 0.5;
- S3 = S%1000000/100000;
- if (S3 != 0 || S2 != 0 || S1 != 0) //当第二位(或者第一位)不等于0时,第三位必须显示。
- {
- P2 = WEI_CODE[2];
- P0 = DSY_CODE[S3] + 0x80;
- DelayMS(1);
- P2 = 0xFF;
- P0 = 0xFF;
- DelayMS(1);
- }
- //第4位(个位)
- S = Sum + 0.5;
- S = S%100000/10000;
- P2 = WEI_CODE[3];
- P0 = DSY_CODE[S]; //有小数点
- DelayMS(1);
- P2 = 0xFF;
- P0 = 0xFF;
- DelayMS(1);
- //第5位
- S = Sum + 0.5;
- S = S%10000/1000;
- P2 = WEI_CODE[4];
- P0 = DSY_CODE[S]+0x80;
- DelayMS(1);
- P2 = 0xFF;
- P0 = 0xFF;
- DelayMS(1);
- //第6位
- S = Sum + 0.5;
- S = S % 1000 /100;
- P2 = WEI_CODE[5];
- P0 = DSY_CODE[S]+0x80;
- DelayMS(1);
- P2 = 0xFF;
- P0 = 0xFF;
- DelayMS(1);
- //第7位
- S = Sum + 0.5;
- S = S % 100/10;
- P2 = WEI_CODE[6];
- P0 = DSY_CODE[S]+0x80;
- DelayMS(1);
- P2 = 0xFF;
- P0 = 0xFF;
- DelayMS(1);
- //第8位
- S = Sum + 0.5;
- S = S % 10;
- P2 = WEI_CODE[7];
- P0 = DSY_CODE[S]+0x80;
- DelayMS(1);
- P2 = 0xFF;
- P0 = 0xFF;
- DelayMS(1);
- }
- //系统初始化
- //根据读入P1的拨码开关状态值,决定放电电流。
- void init()
- {
- LED_R = 0; //红灯亮
- LED_G = 1; //绿灯灭
- switch( P1 )
- {
- case 0XFE: //50mA
- Iout = 500.0/3.6;
- break;
- case 0XFD: //100mA
- Iout = 1000.0/3.6;
- break;
- case 0XFC: //150mA
- Iout = 1.5*1000.0/3.6;
- break;
- case 0XFB: //200mA
- Iout = 2.0*1000.0/3.6;
- break;
- case 0XFA: //250mA
- Iout = 2.5*1000.0/3.6;
- break;
- case 0XF9: //300mA
- Iout = 3.0*1000.0/3.6;
- break;
- case 0XF8: //350mA
- Iout = 3.5*1000.0/3.6;
- break;
- case 0XF7: //400mA
- Iout = 4.0*1000.0/3.6;
- break;
- case 0XF6: //450mA
- Iout = 4.5*1000.0/3.6;
- break;
- case 0XF5: //500mA
- Iout = 5.0*1000.0/3.6;
- break;
- case 0XF4: //550mA
- Iout = 5.5*1000.0/3.6;
- break;
- case 0XF3: //600mA
- Iout = 6.0*1000.0/3.6;
- break;
- case 0XF2: //650mA
- Iout = 6.5*1000.0/3.6;
- break;
- case 0XF1: //700mA
- Iout = 7.0*1000.0/3.6;
- break;
- case 0XF0: //750mA
- Iout = 7.5*1000.0/3.6;
- break;
- case 0XEF: //800mA
- Iout = 8.0*1000.0/3.6;
- break;
- case 0XEE: //850mA
- Iout = 8.5*1000.0/3.6;
- break;
- case 0XED: //900mA
- Iout = 9.0*1000.0/3.6;
- break;
- case 0XEC: //950mA
- Iout = 9.5*1000.0/3.6;
- break;
- case 0XEB: //1000mA
- Iout = 10.0*1000.0/3.6;
- break;
- case 0XEA: //1050mA
- Iout = 10.5*1000.0/3.6;
- break;
- case 0XE9: //1100mA
- Iout = 11.0*1000.0/3.6;
- break;
- case 0XE8: //1150mA
- Iout = 11.5*1000.0/3.6;
- break;
- case 0XE7: //1200mA
- Iout = 12.0*1000.0/3.6;
- break;
- case 0XE6: //1250mA
- Iout = 12.5*1000.0/3.6;
- break;
- case 0XE5: //1300mA
- Iout = 13.0*1000.0/3.6;
- break;
- case 0XE4: //1350mA
- Iout = 13.5*1000.0/3.6;
- break;
- case 0XE3: //1400mA
- Iout = 14.0*1000.0/3.6;
- break;
- case 0XE2: //1450mA
- Iout = 14.5*1000.0/3.6;
- break;
- case 0XE1: //1500mA
- Iout = 15.0*1000.0/3.6;
- break;
- case 0XE0: //1550mA
- Iout = 15.5*1000.0/3.6;
- break;
- }
- }
- //外部中断初始化
- void init_int0()
- {
- PX0 = 1; //设置外部中断0为最高优先级
- IT0 = 1; //1:设置下降沿触发方式;0:低电平触发方式
- EA = 1; //开总中断
- EX0 = 1; //开外部中断0
- }
- //定时器2初始化
- void init_Time2()
- {
- T2MOD = 0;
- T2CON = 0;
- RCAP2H = (65536 - 50000)/256; //12M晶振,50ms产生一次中断
- RCAP2L = (65536 - 50000)%256;
- ET2 = 1; //允许T2中断
- TR2 = 1; //启动T2中断
- }
- //外部中断0,用于停止放电计数。
- void Int0() interrupt 0
- {
- LED_R = 1; //红灯灭
- LED_G = 0; //绿灯亮
- State = 1; //停止放电计数
- // EX0 = 0; //停止外部中断
- }
- //定时器2中断服务程序
- void Time2() interrupt 5
- {
- TF2 = 0; //定时器2必须由软件对溢出标志位清零!
- if (i > 20 && State == 0) //每1秒累加一次放电量
- {
- Sum += Iout; //以100mA放电,1秒钟的放电量。
- i = 0;
- }
- i++;
- }
复制代码
|