📄 capacitor.c
字号:
}
if ((lcd_asc<0x20)||(lcd_asc>=0x80))
{
lcd_asc=0x20;
}
lcd_asc=lcd_asc-0x20;
for (lcd_asc_column=0;lcd_asc_column<=0x03;lcd_asc_column++) //显示的5列的循环
{
asc_rdp=&asc[lcd_asc][lcd_asc_column]; //取出当前字符的每列内容
lcd_buffer1=*asc_rdp; //要写入lcd的数据放入lcd_buffer1中
if(lcd_invter&BIT(0))
{
lcd_buffer1=~lcd_buffer1;
}
lcd_wr1_data(lcd_buffer1);
}
asc_rdp=&asc[lcd_asc][lcd_asc_column]; //取出当前字符的每列内容
lcd_buffer1=*asc_rdp; //要写入lcd的数据放入lcd_buffer1中
if(lcd_invter&BIT(0))
{
lcd_buffer1=~lcd_buffer1;
}
lcd_wr2_data(lcd_buffer1);
if(lcd_invter&BIT(0))
{
lcd_wr2_data(0xff);
}
else
{
lcd_wr2_data(0x00);
}
for (lcd_column_counter=11;lcd_column_counter<=20;lcd_column_counter++) //显示的0~20列循环计数(cs2为11~20列)
{
lcd_asc=*lcd_display_rdp; //要显示的字符ASC码放在lcd_asc中
lcd_display_rdp++;
if (lcd_asc&BIT(7))
{
lcd_invter|=BIT(0);
lcd_asc&=(~BIT(7));
}
else
{
lcd_invter&=(~BIT(0));
}
if ((lcd_asc<0x20)||(lcd_asc>=0x80))
{
lcd_asc=0x20;
}
lcd_asc=lcd_asc-0x20;
for (lcd_asc_column=0;lcd_asc_column<=0x04;lcd_asc_column++) //显示的5列的循环
{
asc_rdp=&asc[lcd_asc][lcd_asc_column]; //取出当前字符的每列内容
lcd_buffer1=*asc_rdp; //要写入lcd的数据放入lcd_buffer1中
if(lcd_invter&BIT(0))
{
lcd_buffer1=~lcd_buffer1;
}
lcd_wr2_data(lcd_buffer1);
}
if(lcd_invter&BIT(0))
{
lcd_wr2_data(0xff);
}
else
{
lcd_wr2_data(0x00);
}
}
lcd_wr2_data(0x00);
lcd_wr2_data(0x00);
}
lcd_wr1_ins(0x3f); //lcd模块1显示
lcd_wr2_ins(0x3f); //lcd模块2显示
}
//这是按钮按下后调用的函数,主要功能是进行高量程和低量程校准,并把校准值存到EEPROM
void btnpressed(void)
{
dly(4);
if(keydown==1) //PA3口输入低电平,是进行低量程校准的标志
{
callow(); //进行低量程校准
keydown=0;
mn();
lcd_display2();
}
if(keydown==2) //PA1口输入低电平,是进行高量程校准的标志
{
calhigh(); //进行高量程校准
keydown=0;
// canoffset(); //进行零偏值校准,但在程序中常常没有意义,暂时将这一句撤销
mn();
lcd_display2();
}
if(comp1!=0||comp2!=0)
{
saveeep();
}
}
//高量程校准,主要功能是用大电流对标准大电容进行充电,然后通过一个式子算出高量程校准增益comp2,存入EEPROM
void calhigh(void)
{
jianche=1; //jianche置1,是进行高量程校准的标志
//改动 PORTB=PORTB&0b11111110;
PORTC=PORTC & 0xfd;
measure(); //对标准大电容进行测量
// calcomp(10060); //计算高量程校准值,参数8200需要根据实际的标准电容进行改变
calcomp(10000);
//改动 PORTB=PORTB|0b00000001;
PORTC=PORTC|0x02;
}
//低量程校准,主要功能是用小电流对标准小电容进行充电,然后通过一个式子算出高量程校准增益comp1,存入EEPROM
void callow(void)
{
jianche=0; //jianche置0,是进行低量程校准的标志
measure(); //对标准小电容进行测量
// calcomp(10720); //计算低量程校准值,参数8800需要根据实际的标准电容进行改变
calcomp(10000);
}
//计算增益
void calcomp(long int i)
{
if(result==0) //4.16改正
{
calerr();
return;
}
else
{
// if(i==10720) //判断是否是低量程校准
if(jianche==0)
{
asm("cli");
comp1=1000000; //计算低量程校准增益,里面的1000可以改动,只要与void adjustgain(void)中的相同就可以了
comp1=comp1/result;
asm("sei");
}
// else if(i==10060) //判断是否为高量程校准
else if(jianche==1)
{
asm("cli");
comp2=10000000; //计算高量程校准增益,里面的10000可以改动,只要与void adjustgain(void)中的相同就可以了
comp2=comp2/result;
asm("sei");
}
else
{
calerr(); //显示失败信号E5
}
adjustgain(); //这两句时自己加的,目的是显示出标准大电容和标准小电容的电容值,没有这两句也可以
dispval(result);
jianche=0;
}
}
//调0偏移,这个函数基本不起作用,因为测量出来的comp3通常都是0
void canoffset(void)
{
measure();
if (count2!=0)
{
calerr();
}
if(count2>=0x70)
{
calerr();
}
comp3=count1;
clrdisp();
}
//显示E5,这个是在测量出现错误的时候调用
void calerr(void)
{
int k=0;
for(k=0;k<=3;k++)
{
pdispbuf[k]=form4[k]; //向pdispbuf数组里存入14,5,15,15四个数字,这四个数字是E5代码在SEG7内的偏移量
}
putformd(); //将E5显示出来
dly(250); //延时一段时间
}
//延时i*4 ms
void dly(int i)
{
stm1=i;
while(stm1)
{
}
}
//电容值的测量过程,首先通过PB1输出高电平还是低电平进行判断是大电流充电还是小电流充电,并设置相应的tc1溢出次数上限,然后启动计时器进行计数,如果在响应的溢出次数上限内成功的测量电容大小,就将flags第三位置0,如果超时,就置1
void measure(void)
{
result=0; //4.16修改
TCNT1H=0; //TCNT1是负责计数充电时间的,首先清空
TCNT1L=0;
ntc1ovf=0; //ntc1ouf是记录tc1溢出次数的变量
//改动 if((PORTB&0b00000001)==0) //判断PB1是否为0,若为0,表明是高量程测量
if((PORTC&0x02)==0)
{
maxtc1ovf=110; //maxtc1ovf存储着tc1最多可以溢出几次,也就是说,它决定着测量范围的上限,大电流充电时,最多可 //以溢出152次
}
else
{
maxtc1ovf=9; //如果是小电流充电,则最多可以溢出20次
}
DDRB=DDRB|0x04; //????这一句话是自己加的,目的是电容在每次测量时都进行一段时间的放电
for(mm1=300000;mm1>0;mm1--) //????这一句话是自己加的,目的是电容在每次测量时都进行一段时间的放电
{
} //????这一句话是自己加的,目的是电容在每次测量时都进行一段时间的放电
TIFR=0x24; //tc1输入捕捉标志和tc1溢出中断标志置1
TIMSK=0x25; //tc0溢出中断使能,tc1输入捕捉中断使能,tc1溢出中断使能
flags=flags&0xf8; //将负数标志,测量完成标志和测量时间超时标志都置0
TCCR1B=0x41; //tc1的计数值在ICP1为上升沿的时候出发输入捕捉,同时选择tc1时钟频率是CLK/1,即10M HZ.
DDRB=DDRB&0xfb; //将PB2的方向改为输入
while(((flags&0x02)==0)&&((flags&0x04)==0)) //如果没有测量完成标志和测量时间超时标志的话,就说明没有测量完,等
{}
if((flags&0x04)!=0) //如果测量时间超时标志置1,表明电容过大,超过量程
{
TCCR1B=0x40; //将tc1停止计数
dly(4);
count2=0xFF00; //
flags=flags|0x08; //将flags的第3位置1,表明测量时间超时,测量失败
}
else if((flags&0x02)!=0) //如果测量完成标志置1,表明测量成功
{
TCCR1B=0x40; //将tc1停止计数
flags=flags&0xf7; //将flags的第3位置0,表明测量成功
}
}
//调0,即将result的值减去comp3的值
void adjustzero(void)
{
//改动 if((PORTB&0x01)==0) //如果PB1为0,即用大电流对电容充电,则不做任何操作,跳过此程序
if((PORTC&0x02)==0)
{
}
else
{
result=result-comp3; //将计数值减去0偏值,即进行了调0校准
if(result<0)
{
flags=flags|0x01; //将flags的第一位置1,即说明测量结果为负数
result=0xFFFFFFFF-result;
result=result+1;
}
}
}
//调整增益,功能是将测量的计数器计数值result通过comp1或comp2变换成实际的电容值大小
void adjustgain(void)
{
//改动 if((PORTB&0b00000001)!=0) //如果PB1输出高电平,说明是用小电流对电容进行充电
if((PORTC&0x02)!=0)
{
asm("cli");
result=result*comp1/100.0;
asm("sei");
}
else
{
asm("cli");
result=result*comp2/1000.0;
asm("sei");
}
}
//将要显示的结果result按从低位到高位存储到strbuf[10]里,并依据高量程测量还是低量程测量,以及result的位数给他找好显示模版,找//显示模板的意思是,看看电容值大小在什么范围内,主要是确定第几位有小数点,以及单位
void dispval(long int i)
{
int j;
int k=0;
int l=0;
int m=0;
nbit=0; //记录实际电容值result的位数
for (k=0;k<=9;k++) //将实际电容值按从低位到高位存储到strbuf[10]中,最低位存在strbuf[0]中,执行后,nbit==10
{
j=i%10;
strbuf[nbit]=j;
i=i/10;
nbit++;
}
nbit--; //nbit减成9
while (strbuf[nbit]==0) //判断result的位数
{
nbit--;
if(nbit==0) //4.17修改
break; //4.17修改
}
nbit++; //到此时为止,nbit存储着实际电容值result十进制的位数
m=nbit;
if (m<2) //如果nbit==1,则给他加上一位
{
m++;
}
//以下几句是通过判断是高量程测量还是低量程测量,以及result的位数,确定电容值的显示模板
//改动 if((PORTB&0b00000001)==0) //如果使用高量程测量,就将位数加3,因为高量程测量时的电流正好是低量程测量时电流的1000倍
if((PORTC&0x02)==0)
{
m=m+3;
}
j=0;
k=0;
if((flags&0x01)==0x01) //如果负数标志为1,则装入负数偏移
{
j=(m-2)*4;
for(l=0;l<=3;l++)
{
pdispbuf[l]=form2[j];
j++;
}
}
else //如果为正数,则转入正数偏移
{
j=(m-2)*4;
for(l=0;l<=3;l++)
{
pdispbuf[l]=form1[j]; //向pdispbuf数组里装入显示数据的模板
j++;
}
}
putformd(); //套用上面显示的模板,将电容数值表示出来
}
//通过pdispbuf[4]中存储的四个将要显示的数字在seg7当中的偏移,将要显示的代码存储到dispbuf[4]中,他的思路是这样的:如果数码管n//上要显示数字,那么pdispbuf[n]上肯定是0或1,0表示本数码管不显示小数点,1表示本数码管显示小树点,从strbuf数组中高位依次显示//对应数字的显示代码就可以了,如果是显示代码,那么pdispbuf[n]大于1,这时候就直接在seg7中寻找相应的显示代码就行
void putformd(void)
{
int k=0;
int d=0;
for(k=0;k<=3;k++)
{
switch(pdispbuf[k])
{
case 0:
dispbuf[d]=strbuf[nbit-1-k]+48;
d++;
break;
case 1:
dispbuf[d]=strbuf[nbit-1-k]+48;
d++;
dispbuf[d]=46;
d++;
break;
case 2:
dispbuf[d]=50;
d++;
break;
case 3:
dispbuf[d]=51;
d++;
break;
case 4:
dispbuf[d]=52;
d++;
break;
case 5:
dispbuf[d]=53;
d++;
break;
case 6:
dispbuf[d]=54;
d++;
break;
case 7:
dispbuf[d]=55;
d++;
break;
case 8:
dispbuf[d]=56;
d++;
break;
case 9:
dispbuf[d]=57;
d++;
break;
case 10:
dispbuf[d]=45;
d++;
break;
case 11:
dispbuf[d]=117;
d++;
break;
case 12:
dispbuf[d]=110;
d++;
break;
case 13:
dispbuf[d]=112;
d++;
break;
case 14:
dispbuf[d]=69;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -