/*根据电池容量的mAh,可以计算电池的持续放电时间的电流数去确定电池的容量。
以下用了一个STC12C5608AD去做检测电池放电400mA的时间,再以公式400mA*时间=mAh
*/
#include "stc8051U.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define ADCTIM (*(unsigned char volatile xdata *)0xfea8)
#define VREFH_ADDR CHIPID7
#define VREFL_ADDR CHIPID8
uint BGV; //内部1.19V参考信号源值存放在idata中
typedef unsigned char BYTE;
uchar time1,time2,time3,pwm1;
uint fen=0,ad1=138,ad0;
sbit LED = P3^6; //背光脚H亮
sbit rw = P2^5;
sbit rs = P2^6; //
sbit en = P2^7; //
sbit cs1 = P3^2;
sbit cs2 = P3^3;
sbit rst = P3^4;
sbit SPK = P3^5; //蜂鸣器
sbit POW = P3^7; //PWM
void InitADC();
uint GetADCResult(BYTE ch);
void Delayus(uint us);
void Delay(uchar ms);
void lcdstate();
void write_command(uchar command);
void write_data(uchar datas);
void lcdinit();
void clearScreen();
void init();
void Timer0Init(void);
void dyADC();
void hz_display16(unsigned char pag, unsigned char col, unsigned char code *hzk);
unsigned char code SZ[][16]=
{/*-- 文字: 0 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0xF0,0x08,0x08,0x18,0xE0,0x00,0x00,0x00,0x0F,0x10,0x20,0x10,0x0F,0x00,
/*-- 文字: 1 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x10,0x00,0x00,0x00,
/*-- 文字: 2 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x30,0x08,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x18,0x14,0x13,0x10,0x08,0x00,
/*-- 文字: 3 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x10,0x08,0x88,0x78,0x00,0x00,0x00,0x00,0x10,0x20,0x20,0x11,0x0E,0x00,
/*-- 文字: 4 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x1F,0x02,0x00,
/*-- 文字: 5 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x70,0x48,0xC8,0x88,0x00,0x00,0x00,0x10,0x10,0x20,0x10,0x0F,0x00,0x00,
/*-- 文字: 6 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0xE0,0x90,0x88,0x80,0x00,0x00,0x00,0x07,0x18,0x20,0x20,0x19,0x06,0x00,
/*-- 文字: 7 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x10,0x08,0x08,0x88,0x78,0x00,0x00,0x00,0x00,0x00,0x18,0x07,0x00,0x00,0x00,
/*-- 文字: 8 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x78,0x88,0x88,0x78,0x00,0x00,0x00,0x0C,0x12,0x21,0x21,0x1E,0x00,0x00,
/*-- 文字: 9 --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x60,0x98,0x08,0x08,0xF8,0xC0,0x00,0x00,0x00,0x21,0x12,0x09,0x07,0x00,0x00,
/*-- 文字: : --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xC,0xC,0x00,0x00,0x00,0x00,0x00,
/*-- 文字: B --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,
/*-- 文字: a --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,
/*-- 文字: t --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,
/*-- 文字: T --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,
/*-- 文字: i --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,
/*-- 文字: m --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,
/*-- 文字: e --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,
/*-- 文字: V --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,
/*-- 文字: A --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,
/*-- 文字: h --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,
/*-- 文字: 一 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0x0,0x0,0x0,0x0,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
/*-- 文字: . --*/
/*-- 楷体_GB231212; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x0,0x0,0x00,0x00,0x00,0x00,0x00,0x00,0xC,0x0,0x00,0x00,0x00,0x00,0x00,
};
/*----------------------------
读取ADC结果
----------------------------*/
uint GetADCResult(BYTE channel)
{
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | channel; //启动 AD 转换
_nop_(); //等待4个NOP
_nop_();
_nop_();
_nop_();
while (!(ADC_CONTR & 0x20)); //查询ADC完成标志
ADC_CONTR &= ~0x20;
return (((int)ADC_RES << 8) | ADC_RESL); //adc_data*4的意思是左移两位,4 = 2的2次方。
//然后左移后加上adc_low的值,这个值应该是adc转换的低两位。
}
/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
P_SW2 |= 0x80; //扩展 RAM 区特殊功能寄存器(XFR)访问控制寄存器
ADCTIM = 0x3f; //ADC时序控制寄存器3f=00111111
P_SW2 &= 0x7f;
ADCCFG = 0x2f; //设置ADC时钟为系统时钟/2/16
ADC_CONTR = 0x80; //使能ADC模块,并选择第15通道 8f=10001111 //ADC上电并延时
}
void lcdstate() //读状态指令
{
uchar lcd=0x00; /*设置初值为0,全部为低,方便后面的判忙*/
rs=0; /*根据时序图拉低,选择写指令*/
rw=1; /*根据时序图拉低,选择写模式*/
do
{
en=1; /*使能,使液晶输出信号,检查是否忙*/
_nop_();_nop_();_nop_();_nop_();/*延时4US*/
lcd=P0; /*把P0口的状态值读回来给lcd*/
en=0; /*使能端跳变*/;
}while(lcd&0x80); /*结果的高位保留,如果高位DB7为一,则表示忙*/
}
void Delayus(uint us) //@12.000MHz
{
while(--us)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
void delay(uchar ms)
{ uchar i;
uchar j;
for(i=0;i<100;i++)
for(j=0;j<ms;j++);
}
void write_command(uchar command)
{
lcdstate();
rs=0; //RS=0;为往MCU进行指令操作
rw=0; //RW=0;为往MCU写入操作
en=0;
_nop_();_nop_();_nop_();_nop_();/*延时4US*/
en=1;
_nop_();_nop_();_nop_();_nop_();/*延时4US*/
P0=command;
_nop_();_nop_();_nop_();_nop_();/*延时4US*/
en=0;
}
void write_data(uchar datas)
{
lcdstate();
rs=1;
rw=0;
en=0;
_nop_();_nop_();_nop_();_nop_();/*延时4US*/
en=1;
_nop_();_nop_();_nop_();_nop_();/*延时4US*/
P0=datas;
_nop_();_nop_();_nop_();_nop_();/*延时4US*/
en=0;
}
void lcdinit()
{
delay(100); //
cs1=1;
cs2=1;
delay(100);
lcdstate(); //
write_command(0x3e); //
write_command(0xb8+0); //
write_command(0xc0+0); //
write_command(0x40+0); //
write_command(0x3f);
}
void clearScreen( )
{ uchar i,j;
lcdstate();
cs1=1;
cs2=1;
write_command(0x3f); //设置显示开
write_command(0xb8); //Y 设置第0页;
write_command(0x40); // 设置第0列
for(i=0;i<8;i++)
{
write_command(0xb8+i);
for(j=0;j<64;j++)
{
//write_command(0x40+j);
write_data(0x00);
}
}
}
void Timer0Init(void) //2毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x30; //设置定时初值
TH0 = 0xF8; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0开始计时
}
void Timer1Init(void) //5毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0x78; //设置定时初值
TH1 = 0xEC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
}
void hz_display8(unsigned char pag, unsigned char col, unsigned char zi)
{
uchar j=0;
uchar i=0;
for(j=0;j<2;j++) //这里写四页
{
write_command(0xb8+pag+j); //page在这里就是从page表示的这页开始写起。
write_command(0x40+col); //从列为col表示的列开始
for(i=0;i<8;i++) //这里写32列
write_data(SZ[zi][8*j+i]); //J为页,I,为第J行第I个数
}
}
void dyADC()
{
int res,ad1;
int xes;
GetADCResult(15);
GetADCResult(15);
res=GetADCResult(15);//读内部基准ADC, 读15通道
GetADCResult(0);
GetADCResult(0);
xes=GetADCResult(0);//读p1.1外部电压ADC
ad1=(int)((long)xes* BGV / res); //计算p5.5外部电压, vcc为1.19V,
ad0=ad1/10;
}
void main()
{
bit q1=0,q2=0,q3=0;
uchar k1;
ulong ww=1667;
P_SW2 = 0X80; //使能访问 XFR,没有冲突不用关闭
CKCON = 0x00; //设置外部数据总线速度为最快
WTST = 0x00;
P0M0 = 0x00; //00上拉准双向口/10浮空输入
P0M1 = 0x00; //11开漏输出/01推挽输出
P1M0 = 0x00;
P1M1 = 0x01; //设置P1.0为ADC
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00; //00上拉准双向口/10浮空输入
P3M1 = 0x00; //11开漏输出/01推挽输出
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
BGV = (VREFH_ADDR << 8) + VREFL_ADDR; //从 CHIPID 中读取内部参考电压值
POW=0;
SPK=0;
lcdinit();
clearScreen();
InitADC();
Timer0Init();
Timer1Init();
TR0 = 1; //timer0 start running
ET0 = 1; //enable timer0 interrupt
// TR1 = 1; //timer1 start running
// ET1 = 1; //enable timer1 interrupt
EA = 1; //open global interrupt switch
for(k1=255;k1>0;k1--)
{
SPK=~SPK;
Delayus(k1);
}
SPK=0;
cs1=1;
cs2=0;
hz_display8(0,0,11); //Batt:
hz_display8(0,8,12);
hz_display8(0,16,13);
hz_display8(0,24,13);
hz_display8(0,32,10);
hz_display8(6,0,14); //time:
hz_display8(6,8,15);
hz_display8(6,16,16);
hz_display8(6,24,17);
hz_display8(6,32,10);
while(1)
{
if(EA==1)
{
cs1=1;
cs2=0;
hz_display8(6,40,(time3%100/10)); //时
hz_display8(6,48,(time3%10/1));
hz_display8(6,56,10); //:
cs1=0;
cs2=1;
hz_display8(6,0,(time2%100/10)); //分
hz_display8(6,8,(time2%10/1));
hz_display8(6,16,10); //:
hz_display8(6,24,(time1%100/10)); //秒
hz_display8(6,32,(time1%10/1));
}
if(q1==0&time1==2)
{
dyADC();
cs1=1;
cs2=0;
hz_display8(0,40,(ad0/100));
hz_display8(0,48,22);
hz_display8(0,56,(ad0%100/10));
cs1=0;
cs2=1;
hz_display8(0,0,(ad0%10));
hz_display8(0,8,18); //v
q1=1;
for(k1=0;k1<255;k1++)
{
SPK=~SPK;
Delayus(150);
}
Delay(100);
for(k1=0;k1<255;k1++)
{
SPK=~SPK;
Delayus(150);
}
SPK=0;
CCON = 0; //PCA控制寄存器CCON
//PCA timer stop running
//Clear CF flag
//Clear all module interrupt flag
CL = 0; //PCA的16位计数器 — 低8位CL和高8位CH
CH = 0;
CMOD = 0x08; //工作模式寄存器CMOD
//Disable PCA timer overflow interrupt
CCAP1H = CCAP1L = 0xFF; //模块0的捕捉/比较寄存器用来控制输出的占?比
CCAPM1 = 0x42; //PCA比较/捕获寄存器CCAPMn (n=0,1,2,3) PCA interrupt
PCA_PWM1 = 0x40;
CCON |= CR; //PCA计数器阵列, 运行控制位
TR1 = 1;
ET1 = 1;
}
dyADC();
cs1=0;
cs2=1;
hz_display8(0,16,(ad0/100));
hz_display8(0,24,22);
hz_display8(0,32,(ad0%100/10));
hz_display8(0,40,(ad0%10));
hz_display8(0,48,18); //v
if(fen>=1)LED=0;
if(ad0<=286)q3=1;
while(q3==1)
{
for(k1=0;k1<100;k1++)
{
SPK=~SPK;
Delayus(110);
}
SPK=0;
LED=~LED;
CCAP1H = CCAP1L = 0xFF;
POW=0;
EA=0;
Delay(500);
dyADC();
// ad0=GetADCResult(0);
cs1=0;
cs2=1;
hz_display8(0,16,(ad0%1000/100));
hz_display8(0,24,10);
hz_display8(0,16,(ad0%100/10));
hz_display8(0,16,(ad0%10/1));
hz_display8(0,24,18); //v
if(!q2)
{
ww*=fen;
ww*=4;
cs1=1;
cs2=2;
hz_display8(6,0,21); //-------
hz_display8(6,8,21);
hz_display8(6,16,21);
hz_display8(6,24,21);
hz_display8(6,32,21);
hz_display8(6,40,21);
hz_display8(6,48,21);
hz_display8(6,56,21);
cs1=0;
cs2=1;
hz_display8(6,0,(ww%100000000/10000000));
hz_display8(6,8,(ww%10000000/1000000));
hz_display8(6,16,(ww%1000000/100000));
hz_display8(6,24,(ww%100000/10000));
hz_display8(6,32,(ww%10000/1000));
hz_display8(6,40,16); //mah
hz_display8(6,48,19);
hz_display8(6,56,20);
Delay(1000);
q2=1;
}
}
}
}
void tm0_isr() interrupt 1 using 1
{
static uchar i1,i2;
TL0 = 0x30; //设置定时初值
TH0 = 0xF8; //设置定时初值
i1++;
if(i1>=50)
{
i1=0;
i2++;
if(i2>=10)
{
i2=0;
time1++;
if(time1>=60)
{
time1=0;
time2++;
fen++;
if(time2>=60)
{
time2=0;
time3++;
if(time3>=24)time3=0;
}
}
}
}
// ad0=GetADCResult(0);
}
void tm1_isr() interrupt 3 using 1
{
TL1 = 0x78; //设置定时初值
TH1 = 0xEC; //设置定时初值
if(ad0>=428)CCAP1H = CCAP1L = 142; //模块0的捕捉/比较寄存器用来控制输出的占?比
if(ad0<=427&&ad0>424)CCAP1H = CCAP1L = 142;
if(ad0<=424&&ad0>420)CCAP1H = CCAP1L = 141;
if(ad0<=420&&ad0>416)CCAP1H = CCAP1L = 140;
if(ad0<=416&&ad0>412)CCAP1H = CCAP1L = 139;
if(ad0<=412&&ad0>408)CCAP1H = CCAP1L = 138;
if(ad0<=408&&ad0>404)CCAP1H = CCAP1L = 137;
if(ad0<=404&&ad0>400)CCAP1H = CCAP1L = 136;
if(ad0<=400&&ad0>396)CCAP1H = CCAP1L = 135;
if(ad0<=396&&ad0>392)CCAP1H = CCAP1L = 134;
if(ad0<=392&&ad0>388)CCAP1H = CCAP1L = 132;//
if(ad0<=388&&ad0>384)CCAP1H = CCAP1L = 131;
if(ad0<=384&&ad0>380)CCAP1H = CCAP1L = 129;
if(ad0<=380&&ad0>376)CCAP1H = CCAP1L = 128;
if(ad0<=376&&ad0>372)CCAP1H = CCAP1L = 127;
if(ad0<=372&&ad0>368)CCAP1H = CCAP1L = 126;//
if(ad0<=368&&ad0>364)CCAP1H = CCAP1L = 125;
if(ad0<=364&&ad0>360)CCAP1H = CCAP1L = 123;
if(ad0<=360&&ad0>356)CCAP1H = CCAP1L = 122;
if(ad0<=356&&ad0>352)CCAP1H = CCAP1L = 120;
if(ad0<=352&&ad0>348)CCAP1H = CCAP1L = 119;
if(ad0<=348&&ad0>344)CCAP1H = CCAP1L = 117;
if(ad0<=344&&ad0>340)CCAP1H = CCAP1L = 116;
if(ad0<=340&&ad0>336)CCAP1H = CCAP1L = 114;
if(ad0<=336&&ad0>332)CCAP1H = CCAP1L = 113;
if(ad0<=332&&ad0>328)CCAP1H = CCAP1L = 111;
if(ad0<=328&&ad0>324)CCAP1H = CCAP1L = 109;
if(ad0<=324&&ad0>320)CCAP1H = CCAP1L = 108;
if(ad0<=320&&ad0>316)CCAP1H = CCAP1L = 106;
if(ad0<=316&&ad0>312)CCAP1H = CCAP1L = 105;
if(ad0<=312&&ad0>308)CCAP1H = CCAP1L = 103;
if(ad0<=304&&ad0>300)CCAP1H = CCAP1L = 100;
if(ad0<=300&&ad0>296)CCAP1H = CCAP1L = 98;
if(ad0<=296&&ad0>292)CCAP1H = CCAP1L = 97;
if(ad0<=292&&ad0>288)CCAP1H = CCAP1L = 94;
if(ad0<=288&&ad0>284)CCAP1H = CCAP1L = 91;
if(ad0<=284)CCAP1H = CCAP1L = 0xFF;
//CCAPM0 = 0x42;*/
}
|