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

📄 final.c

📁 单片机AT89S52实现的玻璃厚度控制
💻 C
字号:
/***** 芯片位选及端口地址 *****/
/***** LED & KEYBOARD 8255 A:0x00H B:0x01H C:0x02H CTL:0x03*****/
/***** RESERVED 	  8255 A:0x20H B:0x21H C:0x22H CTL:0x23*****/
/***** ADC0832			   0x40H *****/

/***** 芯片管脚定义 *****/
/***** AT89S52 *****/
/***** P24,P25 Keyboard ********************/
/***** P22,P23 Serial COMMNICATION CTL *****/
/***** P20,P21  8255 I/O PORT SELECT *****/
/***** P10,P11,P13 Serial AD Conversion CTL *****/
/***** P14 SSR CTL *****/


#include <REGX52.H>
#include <MATH.H>
#include <ABSACC.H>

#define Uchar 	unsigned char
#define Uint	unsigned int
#define P8255_1A XBYTE[0x0000]
#define P8255_1B XBYTE[0x0100]
#define P8255_1C XBYTE[0x0200]
#define P8255_1CTL XBYTE[0x0300]
#define ADC0832 XBYTE[0x4000]

sbit DI=P1^0;
sbit DO=P1^1;
sbit CLK=P1^2;

void SSR_GainPower(void);
void Data_AC(void);
void Data_Block(void);//保持最近一次正常厚度值
void Data_Pass(void);
void SSR_LosePower(void);
void ErrorDisplay(void); //显示错误ERROR
void Delay(Uint);
void Pulse(void);
void SystemHold(void);

code unsigned char Digital_7Seg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};
								//   0    1    2    3    4    5    6    7    8    9  blank								
                				 //  0    1    2    3    4    5    6    7    8    9   10
code unsigned char Character_7Seg[]={0x3F,0x06,0x5B,0x4F,0x31,0x76,0x5E,0x77,0x79,0x3F,0x38};
								//     0    1    2    3    T    H    d    R    E    O    L   
								//     0    1    2    3    4    5    6    7    8    9	 10

Uint hd=128;//AD转换后的中心偏移值
Uchar TimerExpension=2;//定时器时长扩展50ms*2=0.1s
Uchar ButtonDelay=0;	//按键显示延时
Uint  CT1=40,CT2=10,CT3=8,H0=520,H1=30;//所有参数设定,及预制参数,参数值存储单元

Uint  T1C,T2C,T3C;
Uchar TimerExpensionC;

//键盘全局变量
Uchar keywait_2s=0;
bit keywait_flag=0;//键盘按下显示延时标志位
bit keydown_flag=0;
Uchar keytype=0;
Uchar keycount=0;//记录选参键按下次数

Uint Up_boundary=0,Down_boundary=0;
bit ADNow_flag=0;
bit executed_once_flag=0;
bit error_flag=0;
bit continue_flag=1;

void Initial_8255_1()
{
	P8255_1CTL=0x80;/*1000 0000 方式0 A B C口全输出*/
}

void Delay(Uint ms)//ms Delay
{	
	Uchar j;
	while(ms>=1)
	{
		for(j=0;j<250;j++)//per "for loop" takes 1 ms @12Mhz
		{;}
		ms--;
	}
}

void Timer0() interrupt 1 using 0
{
	TimerExpensionC--;
	if(TimerExpensionC==0)
	{
		if(T1C!=0){T1C--;}//T1C 采样周期 T2C 吸合时长 T3C 采样延时时长
		if(T1C==0 && T2C!=0)
		{
			SSR_GainPower();
		}
		if(T1C==0 && T3C!=0){T3C--;}
		if(T3C==0 && T2C!=0 && T1C==0 && executed_once_flag==0)
		{
			ADNow_flag=1;
			executed_once_flag=1;
		}
		if(T1C==0 && T2C!=0){T2C--;}
		if(T2C==0 && T1C==0 && T3C==0)
		{
			SSR_LosePower();
			T1C=CT1;T2C=CT2;T3C=CT3;executed_once_flag=0;
		}

		if(keywait_2s!=0)
		{
			keywait_2s--;
			if(keywait_2s==0){keywait_flag=0;}
		}

		TimerExpensionC=TimerExpension;
	}
	
	TH0=0x3C;//50 ms Cycle
	TL0=0xB0;

}

void CharDisplay(Uchar num1,Uchar num2)//高两位参数类型显示
{			
		switch (num2)
		{
		case 6:P8255_1C=0x20;break;
		case 5:P8255_1C=0x10;break;
		case 4:P8255_1C=0x08;break;
		case 3:P8255_1C=0x04;break;
		case 2:P8255_1C=0x02;break;
		default: break;
		}	

		P8255_1A=Character_7Seg[num1];
		Delay(2);
}

void DigiDisplay(Uint temp)
{
		Uchar lamp1,lamp2,lamp3,lamp4=10;
		
		lamp3=temp/100;
		lamp2=(temp-lamp3*100)/10;
		lamp1=temp-lamp3*100-lamp2*10;
		//第四位LED显示
		P8255_1C=0x08;
		P8255_1A=Digital_7Seg[lamp4];
		Delay(2);
		//第三位LED显示
		P8255_1C=0x04;
		P8255_1A=Digital_7Seg[lamp3];
		Delay(2);
		//第二位LED显示
		P8255_1C=0x02;
		P8255_1A=Digital_7Seg[lamp2]|0x80;//加上小数点
		Delay(2);
		//第一位LED显示
		P8255_1C=0x01;
		P8255_1A=Digital_7Seg[lamp1];
		Delay(2);
}

void ScanKeyboard()
{
	Uchar i=1,temp=0;
	keytype=0;

	P8255_1B=0x00;
	if(P3_4==0 || P3_5==0)//有键按下
	{
		keydown_flag=1;
		keywait_flag=1;
		keywait_2s=40;

		if(P3_4==0 && P3_5!=0)//行码:1行 +1
		{
			keytype++;	
		}
		else if(P3_4!=0 && P3_5==0)//行码:2行 +2
		{
			keytype+=2;	
		}
	
	Delay(120);
	for(i=1;i<=4;i++)//列码:1列 +10 2列 +20 3列 +30 4列 +40
	{
		switch(i)
		{
			case 1:  P8255_1B=~0x01;break;
			case 2:  P8255_1B=~0x02;break;
			case 3:  P8255_1B=~0x04;break;
			case 4:  P8255_1B=~0x08;break;
			default: break;
		}
		if(P3_4==0 || P3_5==0)
		{
			keytype+=i*10;
		}
	}
	}
	else		//无键按下
	{
		keydown_flag=0;
	}
	
	if(keytype==11)//选参键按下的次数
	{
		keycount++;
		if(keycount==6){keycount=1;}
	}

	switch(keytype)
	{
		case 12:continue_flag=0;
				break;//SYS HOLD
		case 22:error_flag=0;
				continue_flag=1;
				break;//SYS CONTINUE
	}
}

void LedDisplay()
{	//Used Parameters:Uchar hd,Uchar HdOff,Uchar lampCount,Uchar keydown_flag,Uchar keydown_count,Uchar key_type
	Uint  Parameter[5],temp=0;
	if(!keydown_flag)		//无键按下
	{
		//temp=H0+100*(hd-128)/256;//十进制厚度值的LED化,包括参数名'Hd'显示
		temp=H0+100*hd/256-100*128/256;
		CharDisplay(5,6);	//最高位LED显示
		CharDisplay(6,5);	//次高位LED显示
		DigiDisplay(temp);		//四位数字LED显示
	}
	else if(keydown_flag==1 || keywait_flag==1)		//有键按下或键显示延时有效
	{
		if(keytype==11)		//选参键按下则继续
		{
			Parameter[0]=CT1;Parameter[1]=CT2;Parameter[2]=CT3;
			Parameter[3]=H0;Parameter[4]=H1;
			while(keywait_flag==1)//延时2秒标志位有效则继续	
			{
				switch(keycount)//Character_7Seg[]={0x3F,0x06,0x9B,0x4F,0x31,0x76,0x5E,0x71,0x79,0x6D};
								//                   0    1    2    3    T    H    d    F    E    S  
								//                   0    1    2    3    4    5    6    7    8    9
				{
				case 1:	CharDisplay(4,6);//Display T1 DigitalDisplay(T1)
						CharDisplay(1,5);
						DigiDisplay(Parameter[keycount-1]);break;
				case 2:	CharDisplay(4,6);//Display T2 DigitalDisplay(T2)
						CharDisplay(2,5);
						DigiDisplay(Parameter[keycount-1]);break;
				case 3:	CharDisplay(4,6);//Display T3 DigitalDisplay(T3)
						CharDisplay(3,5);
						DigiDisplay(Parameter[keycount-1]);break;
				case 4:	CharDisplay(5,6);//Display H0 DigitalDisplay(H0)
						CharDisplay(0,5);
						DigiDisplay(Parameter[keycount-1]);break;
				case 5:	CharDisplay(5,6);//Display H1 DigitalDisplay(H1)
						CharDisplay(1,5);
						DigiDisplay(Parameter[keycount-1]);break;
				default: break;
				}
				switch(keytype)
				{
				case 21:Parameter[keycount-1]+=1;break;//PARAMETER UP
				case 31:Parameter[keycount-1]-=1;break;//PARAMETER DOWN
				case 41:if(keycount==1){CT1=Parameter[keycount-1];}
						if(keycount==2){CT2=Parameter[keycount-1];}
						if(keycount==3){CT3=Parameter[keycount-1];}
						if(keycount==4){H0=Parameter[keycount-1];}
						if(keycount==5)
									    {
											H1=Parameter[keycount-1];
											Up_boundary=128+256*H1/100;
											Down_boundary=128-256*H1/100;
									    }
												 break;//PARAMETER CONFIRMATION
				//case 12:break;//SYS HOLD
				//case 22:break;//SYS CONTINUE
				default: break;
				}

				ScanKeyboard();

				if(ADNow_flag==1)
				{
					Data_AC();
					ADNow_flag=0;
				}
			}
		}
		keytype=0;
		keycount=0;
		keydown_flag=0;
	}
}

void SSR_GainPower()
{
	P1_3=0;	
	//P1_6=0;//测试标志位
}

void Pulse(void)
{
	
	Uchar i;
	CLK=1;
	i++;
	CLK=0;
}
void Data_AC()
{
	Uchar temp=0;
	bit DI_bit=0;
	
	CLK=0;
	//ADC0832 Initialize & Data ACquire
	P2=0x40;//Select AD	
	DI=1;//Pulse 1 of ADDRESS MUX:Start bit
	Pulse();
	DI=1;//Pulse 2 of ADDRESS MUX:Single ended
	Pulse();
	DI=0;//Pulse 3 of ADDRESS MUX:Channel 0 selected
	Pulse();
	//NOP;//ADC0832 MUX Setting Time
	DI_bit=0;
	Pulse();//Pulse 1 of DATA Conversion:MSB OUT FIRST
	DI_bit=DO;
    if(DI_bit==0){temp=temp<<1;}
	if(DI_bit==1){temp=temp<<1;temp++;}
	Pulse();//Pulse 2 of DATA Conversion
	DI_bit=DO;
    if(DI_bit==0){temp=temp<<1;}
	if(DI_bit==1){temp=temp<<1;temp++;}
	Pulse();//Pulse 3 of DATA Conversion
	DI_bit=DO;
    if(DI_bit==0){temp=temp<<1;}
	if(DI_bit==1){temp=temp<<1;temp++;}
	Pulse();//Pulse 4 of DATA Conversion
	DI_bit=DO;
    if(DI_bit==0){temp=temp<<1;}
	if(DI_bit==1){temp=temp<<1;temp++;}
	Pulse();//Pulse 5 of DATA Conversion
	DI_bit=DO;
    if(DI_bit==0){temp=temp<<1;}
	if(DI_bit==1){temp=temp<<1;temp++;}
	Pulse();//Pulse 6 of DATA Conversion
	DI_bit=DO;
    if(DI_bit==0){temp=temp<<1;}
	if(DI_bit==1){temp=temp<<1;temp++;}
	Pulse();//Pulse 7 of DATA Conversion
	DI_bit=DO;
    if(DI_bit==0){temp=temp<<1;}
	if(DI_bit==1){temp=temp<<1;temp++;}
	Pulse();//Pulse 8 of DATA Conversion:LSB OUT LAST
	DI_bit=DO;
    if(DI_bit==0){temp=temp<<1;}
	if(DI_bit==1){temp=temp<<1;temp++;}

	if(temp>Up_boundary || temp<Down_boundary)//1mm 对应25.6
	{
		Data_Block();//锁存最近一次正常厚度值
		SSR_LosePower();
		ErrorDisplay(); //显示错误ERROR,等待Error_flag==0跳出错误显示,进入正常循环
	}
	else
	{
		Data_Pass();
		hd=temp;
	}
}

void SSR_LosePower()
{
	P1_4=0;//LF398N锁存数据
	P1_3=1;
	//P1_6=1;//测试标志位
}

void Data_Pass()//允许数据通过LF398N,进入速度闭环
{
	if(T1C==0 && T3C==0)
	{
		P1_4=1;
	}
}

void Data_Block()//阻挡数据通过LF398N,保持上次速度
{
	P1_4=0;
	error_flag=1;
}

void ErrorDisplay() //显示错误ERROR,机械故障或电路异常引起,此时ABS(hd-128)>H0
{
	EA=0;
	while(error_flag==1)
	{
		CharDisplay(8,6);//E
		CharDisplay(7,5);//R
		CharDisplay(7,4);//R
		CharDisplay(9,3);//O
		CharDisplay(7,2);//R
		ScanKeyboard();
	}
	T1C=10;T2C=CT2;T3C=CT3;executed_once_flag=0;
	EA=1;
}

void SystemHold(void)
{
	EA=0;
	while(continue_flag==0)
	{
		CharDisplay(5,6);//H
		CharDisplay(9,5);//O
		CharDisplay(10,4);//L
		CharDisplay(6,3);//D
		ScanKeyboard();
	}
	T1C=10;T2C=CT2;T3C=CT3;executed_once_flag=0;
	EA=1;
}

void main()
{
	Uchar i=0;
	P1_3=0;
	IE=0x82;//1000 0010 使能中断,使能定时器0
	TMOD=0x01;//0000 0001
	TH0=0x3C;//50 ms Cycle
	TL0=0xB0;
	Delay(150);
	Initial_8255_1();/*方式0 A B C口全输出*/

	T1C=0;T2C=CT2;T3C=CT3;TimerExpensionC=TimerExpension;//上电快采一次
	Up_boundary=128+256*H1/100;
	Down_boundary=128-256*H1/100;

	TR0=1;//开始周期采样

	while(1)
	{
		LedDisplay();
		ScanKeyboard();
		
		if(ADNow_flag==1)
		{
			Data_AC();
			ADNow_flag=0;
		}

		if(continue_flag==0)
		{
			SystemHold();
		}
	}
}

⌨️ 快捷键说明

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