⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainprog.c

📁 单体电容测试仪源码程序 可测电压、有A/D转换等。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
水6月15日 47吨 每吨2.93共137.7元
卫生费24   电共1088,每度0.49元,共1088*0.49=533元。
*/

#include 	<intrins.h>		  //含_nop_()函数
#include "SM5964reg.h"
#include "OS_CFG.H"
#include "NewType.h"
#include "SerialNewType.h"
#include "ht1621.h"

//****************************************************************************//
//注意在SerialNewType.h中修改摘机振铃次数(pick_ring_times)供北京铁通使用。    //
//注意如果需要将程序改为拨9次电话不锁机在os_cfg.h中修改CALL9_LOCK_LINE        //
//****************************************************************************//
//定义版本号常量
unsigned char code Versoin[]={"070723"};
//中断用全局变量
bit ADC0_open=0;	//adc0打开控制
bit ADC1_open=1;	//adc1打开控制
bit ADC2_open=0;	//adc2打开控制
bit ADC3_open=1;	//adc3打开控制

unsigned char timer0_interrupt_counter;
unsigned int ADC_result_intr;		//adc结果
unsigned int ADC_result_intr0;
unsigned int ADC_result_intr1;
unsigned int ADC_result_intr2;
unsigned int ADC_result_intr3;
unsigned long ADC1_accumulate_intr;		//1通道累加值
unsigned int ADC2_accumulate_intr;		//2通道累加值
unsigned int ADC3_accumulate_intr;		//3通道累加值
unsigned char ADC2_counter_intr;			//adc计数
unsigned char ADC3_counter_intr;			//adc计数

//主程序使用变量
unsigned long idata ADC1_accumulate;			//1通道累加值

unsigned int ADC_result1,ADC_result2,ADC_result3;		//adc结果

float  ADC0_coefficient;	//adc系数
float  ADC1_coefficient;	//adc系数
float  ADC2_coefficient;	//adc系数
float  ADC3_coefficient;	//adc系数
float idata charge;				//累加电荷量
float start_votage;		//充电起始电压
float Curent_Votage;			//当前电压
float Votage;					//电压值
float current;			//电流记录
float Capacitance;			//电容
float resistance;

unsigned char chip_connect;	 	//芯片是否连接
unsigned char timer0_10ms=0;
unsigned char timer0_0d1s=0;
unsigned char timer0_1s=0;
bit flag_1ms_adc=0;
bit flag_10ms_1=0;
bit flag_0d1s=0;
bit flag_1s_1=0;
unsigned int resistance_measure_1ms=0;

unsigned char data Mesure_state;		//侧量状态
unsigned int data Mesure_counter_10ms;	//侧量计数
unsigned char data disp_flag;		//动态显示电压标志
unsigned char data stop_flag;		//停止测试标志
unsigned char data second;		//秒	
unsigned char data minute;		//分钟
unsigned char data hour;		//小时

unsigned char Display_state=0;
unsigned char RefreshDisplay_1s=0;
unsigned char MAX_SP=0;
#define timer0_counter_start 65536-(25000/4)*5 +20;

extern bit Ti;					//Ti=1,串口准备好,可以发送数据
extern bit SendBufFullFlag;		//发送缓冲区满标志
bit RefreshDisplay_0d1s;

void main()
{

	//初始化硬件设置。
	//WDTC = 0x87;			//5964打开看门狗。复位周期限约4秒钟。
 	WDTC = 0x3f;			//stc89le516打开看门狗。复位周期限约4.5秒钟。
	
	//初始化定时器及串口。
	IP = 0x02;				//T0为高级中断
	TMOD = 0x21;            //定时器0设为方式1,定时器1设为方式2。
                            //(方式1:16位计数结构。方式2:8位重置)
	//TL0 = 0x00;			//普通定时器初值。14745600Hz下,10ms产生一次中断。
	//TH0 = 0xd0;			//65536-14745600/1200=0xd000

	TL0 = 0x00;				//12倍速
	TH0 = 0xd0;				//65536-14745600/1000=0xc666


	TL1 = BAUDRATE9600;    //定时器一作为波特率发生器。初值
	TH1 = BAUDRATE9600;    //重装值,BAUDRATE38400作为系统默认值。

	PCON = 0x80;            //pcon=#80h时,SMOD=1,波特率加倍;
							//波特率=(2^SMOD)*(振荡频率/[384(256-TH1)]
	SCON = 0x50;            //串行口设为方式1,REN=1允许接收。
                            //定时器1作为波特率发生器,1个起始位,8个数据位,1个停止位。
	TCON = 0x50;            //启动T0,T1。

    P0=0xff;
	P0M0=0;				//P0为普通I/0
	P0M1=0;								

    P1=0xff;
	P1M0=0x0f;				//P1.4-01.7推挽输出1,其它为输入
	P1M1=0xf0;								

    P2=0;				//各开关均关闭

    P3=0xff;
	P3M0=0;				//P3为普通I/O输入
	P3M1=0;								



	CLK_DIV=0;	//时钟分频00=1,01=2,03=4,03=8,04=16,05=32,06=64,07=128
	AUXR=0x80;	//d7=1,T0为系统时钟,d6=0,T1为系统时钟/12,d5=0,正常串口波特率
	
	//葛同府所写模块初始化函数。
	InitialGeTF();
	InitialHT1621();
	ClearDisplay();

	timer0_0d1s=0;
	Mesure_state=0;
	disp_flag=1;	//动态显示电压
	ADC_coefficient_measure();	//ADC系数计算
	IE = 0x92;              //允许T0、串行中断开,开总中断位。

    while(1)
    {
		//清硬件看门狗。
		CearHardWatchDog();
		Display ();
		//葛同府所写任务调用。
		TaskGeTF();
		//键盘扫描
		JP_SM();
		//电容测量
		Capacitance_Mesure();
	}
}

void Timer() interrupt 1
{
	//TL0 = 0x1e;	
	//TH0 = 0xd0;	//14745600Hz下,系统时钟/12,10ms产生一次中断计数器初值为0xd000。

	TL0 = TL0+0x66;	
	TH0 = 0xc6;		//14745600Hz下,系统时钟/1,1ms产生一次中断计数器初值为0xc666。
	if (SP <0x20)
	{
	 // sp_over_flow=1; 
	  if (SP>MAX_SP) MAX_SP=SP; //最大堆栈
	}
	if (F12_drv==1) F12_drv=0;
	else F12_drv=1;
									 
	//0通道转换
	if (ADC0_open==1){	//adc0打开控制
		ADC_CONTR=0xe8+0;					//启动AD转换,用最低转换速率
		while ((ADC_CONTR & 0x10)==0) {}
		ADC_CONTR=0xe0+0;					//停止AD转换
		ADC_result_intr0 = ADC_HIGH*4;
		ADC_result_intr0 +=ADC_LOW & 0x03;			//adc结果
	}
	//1通道转换
	if (ADC1_open==1){	//adc1打开控制
		ADC_CONTR=0xe8+1;					//启动AD转换,用最低转换速率
		while ((ADC_CONTR & 0x10)==0) {}
		ADC_CONTR=0xe0+1;					//停止AD转换
		ADC_result_intr1 = ADC_HIGH*4;
		ADC_result_intr1 +=ADC_LOW & 0x03;			//adc结果
		ADC1_accumulate_intr +=ADC_result_intr1;		//2通道累加值
	}
	//2通道转换
	if (ADC2_open==1){	//adc2打开控制
		ADC_CONTR=0xe8+2;					//启动AD转换,用最低转换速率
		while ((ADC_CONTR & 0x10)==0) {}
		ADC_CONTR=0xe0+2;					//停止AD转换
		ADC2_accumulate_intr += ADC_HIGH*4;
		ADC2_accumulate_intr +=ADC_LOW & 0x03;			//adc结果
		if (++ADC2_counter_intr>=4) {
			ADC2_counter_intr=0;
			ADC_result_intr2=ADC2_accumulate_intr/4;	//adc计数
			ADC2_accumulate_intr=0;
		}
	}
	//3通道转换
	if (ADC3_open==1){	//adc3打开控制
		ADC_CONTR=0xe8+3;					//启动AD转换,用最低转换速率
		while ((ADC_CONTR & 0x10)==0) {}
		ADC_CONTR=0xe0+3;					//停止AD转换
		ADC3_accumulate_intr += ADC_HIGH*4;
		ADC3_accumulate_intr +=ADC_LOW & 0x03;			//adc结果
		if (++ADC3_counter_intr>=1) {
			ADC3_counter_intr=0;
			ADC_result_intr3=ADC3_accumulate_intr/1;	//adc计数
			ADC3_accumulate_intr=0;
		}
	}
	flag_1ms_adc=1;
	resistance_measure_1ms ++;
    //timer0中断计数
    if (++timer0_interrupt_counter<10) return;
    timer0_interrupt_counter=0;
	Mesure_counter_10ms++;	//侧量计数
	flag_10ms_1=1;
	if (++timer0_10ms==10) {
		timer0_10ms=0;
		flag_0d1s=1;
		RefreshDisplay_0d1s=1;
		if (++ timer0_0d1s==10) {
			timer0_0d1s=0;
			flag_1s_1=1;
			RefreshDisplay_1s++;
			if (timer0_1s!=0xff) timer0_1s++;
			//disp_char_decimal(second);
			if(++second>=60){
				second=0;
				if(++minute>=60){
					minute=0;
					if(++hour>=60){
						hour=0;
					}
				}	
			}
		}
	}
}



//复位硬件看门狗
void CearHardWatchDog(void)
{
	WDTC = 0x3f;	//d4:CLR_WDT=1清看门狗,硬件自动清零该位
}
/*
//以十进制方式显示char形数
void disp_char_decimal(unsigned char char_data)
{				  
	unsigned bai,shi,ge;
	ge = char_data%10;
	char_data = char_data/10;
	shi = char_data%10;
	bai = char_data/10;
	printh(bai + 0x30);
	printh(shi + 0x30);
	printh(ge + 0x30);
	printh(0x20);
}*/

/*
//浮点数打印到串口(最大99999)
void pinint_float_decimal(float float_data)
{				  
	unsigned long long_data;
	unsigned char wan,qian,bai,shi,ge;

	long_data=(unsigned int)float_data;
	ge = long_data%10;
	long_data = long_data/10;
	shi = long_data%10;
	long_data = long_data/10;
	bai = long_data%10;
	long_data = long_data/10;
	qian = long_data%10;
	long_data = long_data/10;
	wan = long_data%10;

	printh(wan + 0x30);
	printh(qian + 0x30);
	printh(bai + 0x30);
	printh(shi + 0x30);
//	printh(ge + 0x30);
	printh(0x20);
} */

/*
//以十进制方式显示电压,单位V.
void disp_float_votage(float float_data,unsigned char decimal_digits)
{				  
	unsigned long long_data;
	unsigned char shiyi,yi,qianwan,baiwan,shiwan,wan,qian,bai,shi,ge;

	long_data=(unsigned long)float_data;
	ge = long_data%10;
	long_data = long_data/10;
	shi = long_data%10;
	long_data = long_data/10;
	bai = long_data%10;
	long_data = long_data/10;
	qian = long_data%10;
	long_data = long_data/10;
	wan = long_data%10;
	long_data = long_data/10;
	shiwan = long_data%10;
	long_data = long_data/10;
	baiwan = long_data%10;
	long_data = long_data/10;
	qianwan = long_data%10;
	long_data = long_data/10;
	yi = long_data%10;
	long_data = long_data/10;
	shiyi = long_data%10;

	if (shiyi!=0) {
		printh(shiyi + 0x30);	
		printh(yi + 0x30);
		printh(qianwan + 0x30);
		printh(baiwan + 0x30);
		printh(shiwan + 0x30);
		printh(wan + 0x30);
	}
	else if (yi!=0)	{
		printh(yi + 0x30);
		printh(qianwan + 0x30);
		printh(baiwan + 0x30);
		printh(shiwan + 0x30);
		printh(wan + 0x30);
	}
	else if (qianwan!=0)	{
		printh(qianwan + 0x30);
		printh(baiwan + 0x30);
		printh(shiwan + 0x30);
		printh(wan + 0x30);
	}
	else if (baiwan!=0)	{
		printh(baiwan + 0x30);
		printh(shiwan + 0x30);
		printh(wan + 0x30);
	}
	else if (shiwan!=0)	{
		printh(shiwan + 0x30);
		printh(wan + 0x30);
	}
	else if (shiwan!=0)	{
		printh(shiwan + 0x30);
		printh(wan + 0x30);
	}
	else if (wan!=0)	printh(wan + 0x30);
	printh(qian + 0x30);
	printh('.');
	//printh(ge + 0x30);
	//显示小数
	if(decimal_digits==3){	//3位
		printh(bai + 0x30);
		printh(shi + 0x30);
		printh(ge + 0x30);
	}
	else if(decimal_digits==1){	 //1位
		printh(bai + 0x30);
	}
	else{					 //默认2位
		printh(bai + 0x30);
		printh(shi + 0x30);
		//printh(ge + 0x30);
	}

	printh(0x20);
}

*/

//AD转换
/*
A/D 转换控制寄存器:ADC_CONTR      d7      d6     d5      d4       d3      d2   d1   d0
                              ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0
d2-d0=0通道0,p1.0(12脚)作为ADC0;d2-d0=7通道7,p1.7(19脚)作为ADC7;
SPEED1,SPEED0:模数转换器转换速度控制位
SPEED1/SPEED0为A/D转换所需时间
	1 1: 2 1 0 个时钟周期转换一次,CPU工作频率14.7456MHz时,A/D转换速度约70.217KHz,实测约30K
	1 0: 4 2 0 个时钟周期转换一次
	0 1: 6 3 0 个时钟周期转换一次
	0 0: 8 4 0 个时钟周期转换一次
ADC_POWER: ADC 电源控制位。0:关闭ADC 电源;1:打开A/D 转换器电源
ADC_START: 模数转换器(ADC)转换启动控制位,设置为“1”时,开始转换, 转换结束后为0 。
ADC_FLAG: 模数转换器转换结束标志位,当A/D 转换完成后,ADC_FLAG = 1,要由软件清0。

启动AD 转换前一定要确认AD 电源已打开,AD 转换结束后关闭AD 电源可降低功耗,也可不关闭。

初次打开内部A/D 转换模拟电源,需适当延时,等内部模拟电源稳定后,再启动A/D 转换

建议启动A/D 转换后,在A/D 转换结束之前,不改变任何I/O 口的状态,有利于高精度A/D 转换

不管是A/D 转换完成后由该位申请产生中断,还是由软件查询该标志位A/D 转换是否结束,
当A/D 转换完成后,ADC_FLAG = 1,一定要软件清0。

ADC_HIGH / ADC_LOW 特殊功能寄存器: A/D 转换结果特殊功能寄存器
模拟/ 数字转换结果计算公式如下:结果 ( ADC_HIGH[7:0],ADC_LOW[1:0] ) = 1024 x Vin / Vcc

*/


void adc(unsigned char channel)
{
	//设置p1口为纯输入状态,用于adc
	ADC_CONTR=0xe8+channel;					//启动AD转换,用最低转换速率
	while ((ADC_CONTR & 0x10)==0) {}
	ADC_CONTR=0xe0+channel;					//停止AD转换
	ADC_result_intr = ADC_HIGH*4;
	ADC_result_intr +=ADC_LOW & 0x03;			//adc结果
}


//ADC系数计算
//以各通道A/D值乘以系数所得值为毫伏值
void ADC_coefficient_measure(void)
{
	unsigned int i;
	unsigned long ADC_result_temp;
	ADC_result_temp=0;
	for (i=0;i<30000;i++){
		adc(0);	//0通道AD转换1次
		ADC_result_temp+=ADC_result_intr;
	}
	ADC_result_intr=(unsigned int)(ADC_result_temp/i);
	ADC_result_intr0=ADC_result_intr;
	ADC0_coefficient=(float)2485/ADC_result_intr0;	//最大5.3V
	//实际51mV,运放输出5.1V,放大倍数为=0.01
	//ADC1_coefficient=ADC0_coefficient/100;		//实际电阻为100K/1K倍,最大0.053V
	ADC1_coefficient=ADC0_coefficient/50;			//实际电阻为50K/1K倍,最大0.106V
	//实际1.468V,运放输出4.102V,放大倍数为=0.3579
	ADC2_coefficient=ADC0_coefficient*3579/10000;	//实际电阻为10K/3.3K倍,最大1.9
	//实际30.59V,运放输出4.14V,放大倍数为=7.39
	ADC3_coefficient=ADC0_coefficient*739/100;	//实际电阻为2.6K/20K倍,最大40.77V
}



//带滤波AD转换
//全局变量ADC_result表示滤波后AD值
void ADC_filter(unsigned char channel)
{
	adc(channel);	//AD转换1次
	ADC_result1=ADC_result_intr;
	adc(channel);	//AD转换1次
	ADC_result2=ADC_result_intr;
	adc(channel);	//AD转换1次
	ADC_result3=ADC_result_intr;
	if (ADC_result1>=ADC_result2) {
		if (ADC_result2>=ADC_result3) ADC_result_intr=ADC_result2;	//ADC_result2为中间
		else {	//ADC_result2最小
			if (ADC_result1>ADC_result3) ADC_result_intr=ADC_result3; //ADC_result3为中间
			else  ADC_result_intr=ADC_result1;						 //ADC_result1为中间
		}
	}
	else { 	//ADC_result1<ADC_result2
		if (ADC_result2<=ADC_result3) ADC_result_intr=ADC_result2;	//ADC_result2为中间

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -