计算机控制技术实验说明

编程实验分别仿真和实验台操作两种方式。

实验1 AD转换--输入

AD转换是所有嵌入式系统或机器人获取外部信息的一种重要方式,将温度、角度和位置等转换为对应的数字量,供处理器处理。

原理图:


程序:

/***************   ex1   ******************/
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char

uchar code LEDData[]=
{
 	0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
};
sbit OE  = P1^0;
sbit EOC = P1^1;
sbit ST  = P1^2;
sbit CLK = P1^3;

void DelayMS(uint ms)
{
 	uchar i;
	while(ms--)
	{
	 	for(i=0;i<120;i++);
	}
}

void Display_Result(uchar d)
{
 	P2 = 0xf7;
	P0 = LEDData[d%10];
	DelayMS(5);
	P2 = 0xfb;
	P0 = LEDData[d%100/10];
	DelayMS(5);
	P2 = 0xfd;
	P0 = LEDData[d/100];
	DelayMS(5);
}

void main()
{
 	TMOD = 0x02;
	TH0  = 0x14;
	TL0  = 0x00;
	IE   = 0x82;
	TR0  = 1;
	P1   = 0x3f;
	while(1)
	{
	 	ST = 0;
		ST = 1;
		ST = 0;
		while(EOC == 0);
		OE = 1;
		Display_Result(P3);
		OE = 0;
	}
}

void Timer0_INT() interrupt 1
{
 	CLK = !CLK;
}
如果加入报警功能,低于或超过亮灯报警如下:


实验台,测量电压值并显示:


代码:

//模数实验
#include "reg52.h"
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long

sbit LE1=P3^3;
//定义数值显示
uchar code xianshi[11]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xbE,0xE0,0xFE,0xF6,0x00};

sbit ST=P3^0;	 //起始
sbit OE=P3^1;	 //使能
sbit EOC=P3^2;   //转换完成标志位

sbit ADD_A=P3^5;  //输入端口选择A
sbit ADD_B=P3^6;  //输入端口选择B
sbit ADD_C=P3^7;  //输入端口选择C
uint  getdata,average,n,volt,sum;	 //变量

void delay1_ms(uint time)			 //延时
{
     uint i,j;
	 for(i=0;i<time;i++)
	 for(j=0;j<123;j++);
}
void display_num1(uint dat,uchar num1)		 //显示数值
{
//	P2=0x00;
//	P0=0x00;
	
	P0=xianshi[dat];
	switch(num1)
	{
		case 1:	P2=0x01;break;
		case 2:	P2=0x02;break;
	    case 3:	P2=0x04;break;
		case 4:	P2=0x08;break;
		case 5:	P2=0x10;break;
		case 6:	P2=0x20;break;
		case 7:	P2=0x40;break;
		case 8:	P2=0x80;break;
		default: break;
	}
	delay1_ms(1);
	//P0=0x00;	
}
//数码管4位显示函数

void display_num4(uint num)
{
	uint wan;
	uint qian;
	uint bai;
	uint shi;
	uint ge;
	
	P2=0x00;
	wan=(num/10000)%10;
	if(wan==0)	wan=10;
	display_num1(wan,5);
	qian=(num/1000)%10;
	if(wan==10&&qian==0)	qian=10;
	display_num1(qian,4);
	bai=(num/100)%10;
	if(wan==10&&qian==10&&bai==0) bai=10;
	display_num1(bai,3);
	shi=(num/10)%10;
	if(wan==10&&qian==10&&bai==10&&shi==0)	shi=10;
	display_num1(shi,2);
	ge=num%10;
	display_num1(ge,1);
}

void delay(uint N) 
{
	while(N--);
}

uint adconvert_date()
{
	ST=0;
	ST=1;
	delay(2);
	ST=0;
	while(!EOC);
	OE=1;
	delay(2);
	getdata=P1;
	delay(2);
	OE=0;
	return 	getdata;
}


void main()
{
	uint i;
	uint n;
	uint volt;
	ulong sum=0;
	uint average;
	P2=0x00;
	ADD_A=0;
	ADD_B=0;
	ADD_C=0;
	delay(1000);
	while(1)
	{   
        
      	ADD_A=0;
	  	ADD_B=0;
	  	ADD_C=0;
	  	ST=0;								   
	    P2=0x00;
		for(n=0;n<10;n++)
    	{
	
      		volt=adconvert_date();  //测量可变电阻电压         
      		sum += volt;  	        //累加次数50 	
    	}                                                            
    	average=sum/10;        //取平均值
		average=average*19.4;  //换算成电压值 19.4=OK
		sum=0;                 //和清零             
		for(i=0;i<400;i++) 
        display_num4(average); //显示平均值
     	   
	}
}

实验2 DA转换--输出

DA转换将控制器结果转为模拟量控制外部设备。最常用的实验是波形仿真。

数字调压:


代码:

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char

sbit K1 = P3^0;
sbit K2 = P3^1;
sbit K3 = P3^2;
sbit K4 = P3^3;
sbit K5 = P3^4;
sbit K6 = P3^5;
sbit K7 = P3^6;
sbit K8 = P3^7;

void DelayMS(uint ms)
{
 	uchar i;
	while(ms--)
	{
	 	for(i=0;i<120;i++);
	}
}

void main()
{
 	P2 = 0x00;
	while(1)
	{
	 	if(K1 == 0) P2 = 0;
		if(K2 == 0) P2 = 35;
		if(K3 == 0) P2 = 70;
		if(K4 == 0) P2 = 105;
		if(K5 == 0) P2 = 140;
		if(K6 == 0) P2 = 175;
		if(K7 == 0) P2 = 210;
		if(K8 == 0) P2 = 255;
		DelayMS(2);
	}
}
波形模拟:



代码:

#include <reg52.h>
#include <absacc.h>
#define uint unsigned int
#define uchar unsigned char
#define DAC0832 XBYTE[0xfffe]
char code sin_data[256]={0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,
0xab,0xae,0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,
0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf4,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,
0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe3,0xe1,0xde,0xdc,0xda,0xd8,0xd6,
0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb4,0xb1,0xae,0xab,0xa8,
0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x92,0x8f,0x8c,0x89,0x86,0x83,0x80,0x7d,0x79,0x76,0x73,
0x70,0x6d,0x6a,0x67,0x64,0x61,0x5e,0x5b,0x58,0x55,0x52,0x4f,0x4c,0x49,0x46,0x43,0x41,
0x3e,0x3b,0x39,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,
0x17,0x15,0x14,0x12,0x10,0xf,0xd,0xc,0xb,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x3,0x2,0x1,0x1,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x2,0x3,0x3,0x4,0x5,0x6,0x7,0x8,
0x9,0xa,0xc,0xd,0xe,0x10,0x12,0x13,0x15,0x17,0x18,0x1a,0x1c,0x1e,0x20,0x23,0x25,0x27,
0x29,0x2c,0x2e,0x30,0x33,0x35,0x38,0x3b,0x3d,0x40,0x43,0x46,0x48,0x4b,0x4e,0x51,0x54,
0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x73,0x76,0x79,0x7c};//正弦码表,可通过SIN()函数获得

void DelayMS(uint ms)
{
 	uchar i;
	while(ms--)
	{
	 	for(i=0;i<120;i++);
	}
}

void  delay_nus(unsigned int i)
{
   unsigned int j;
   while(i--)
   {
   for(j=0;j<127;j++);
   
   }


}
/**********************************************/
void delay(unsigned char i)
{
 	unsigned char t;
	for(t=0;t<i;t++);
}
/**********************************************
           输出数据到端口(注意考虑延时)
**********************************************/
void conversion(unsigned char out_data)
{
    DAC0832 =out_data; //输出数据
    delay(1);
		   //delay_nus(10);         //延时等待转换
}
/************************************************
          产生正弦波函数
************************************************/
void sine(void)
{
unsigned char i;
for(i=0;i<255;i++)
{
conversion(sin_data[i]);
}
}
/***********************************************
       产生锯齿波(下降型)
***********************************************/
void saw(void)
{
unsigned char j;
for(j=0;j<255;j++)
conversion(j);
}
/***********************************************
           产生方波(脉冲)
***********************************************/
void pulse(void)
{
conversion(0xff);
delay_nus(1000);
conversion(0x00);
delay_nus(1000);
}
/***********************************************
          产生三角波
***********************************************/
void triangle(void)
{
unsigned char k;
for(k=0;k<255;k++)
conversion(k);
for(;k>0;k--)
conversion(k);
}

void main()
{
	while(1)
	{
//		pulse();
//		saw();
//		sine();
		triangle();
	}
}
实验台:



代码:

#include"reg52.h"
char code sin_data[256]={0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,
0xab,0xae,0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,
0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf4,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,
0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe3,0xe1,0xde,0xdc,0xda,0xd8,0xd6,
0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb4,0xb1,0xae,0xab,0xa8,
0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x92,0x8f,0x8c,0x89,0x86,0x83,0x80,0x7d,0x79,0x76,0x73,
0x70,0x6d,0x6a,0x67,0x64,0x61,0x5e,0x5b,0x58,0x55,0x52,0x4f,0x4c,0x49,0x46,0x43,0x41,
0x3e,0x3b,0x39,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,
0x17,0x15,0x14,0x12,0x10,0xf,0xd,0xc,0xb,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x3,0x2,0x1,0x1,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x2,0x3,0x3,0x4,0x5,0x6,0x7,0x8,
0x9,0xa,0xc,0xd,0xe,0x10,0x12,0x13,0x15,0x17,0x18,0x1a,0x1c,0x1e,0x20,0x23,0x25,0x27,
0x29,0x2c,0x2e,0x30,0x33,0x35,0x38,0x3b,0x3d,0x40,0x43,0x46,0x48,0x4b,0x4e,0x51,0x54,
0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x73,0x76,0x79,0x7c};//正弦码表,可通过SIN()函数获得
void  delay_nus(unsigned int i)
{
   unsigned int j;
   while(i--)
   {
   for(j=0;j<127;j++);
   
   }
}

/**********************************************/
void delay(unsigned char i)
{
 	unsigned char t;
	for(t=0;t<i;t++);
}
/**********************************************
           输出数据到端口(注意考虑延时)
**********************************************/
void conversion(unsigned char out_data)
{
           P0=out_data; //输出数据
           delay(5);
		   //delay_nus(10);         //延时等待转换
}
/************************************************
          产生正弦波函数
************************************************/
void sine(void)
{
	unsigned char i;
	for(i=0;i<255;i++)
{
conversion(sin_data[i]);
}
}
/***********************************************
       产生锯齿波(下降型)
***********************************************/
void saw(void)
{
	unsigned char j;
	for(j=0;j<255;j++)
		conversion(j);
}
/***********************************************
           产生方波(脉冲)
***********************************************/
void pulse(void)
{
	conversion(0xff);
	delay_nus(1000);
	conversion(0x00);
	delay_nus(1000);
}
/***********************************************
          产生三角波
***********************************************/
void triangle(void)
{
	unsigned char k;
	for(k=0;k<255;k++)
		conversion(k);
	for(;k>0;k--)
		conversion(k);
}
void main()
{
	while(1)
	{
		pulse();
		//saw();
		//sine();
		//triangle();
	}
}

实验3 电机实验--控制



实验台:


代码:

#include"reg52.h"
#include "math.h"

#define uchar unsigned char
#define uint unsigned int

uchar code xianshi[12]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xbE,0xE0,0xFE,0xF6,0x9c,0x00};



sbit PWM=P1^7;
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;

uint wide=100;//脉宽计数
uint t1=0;	//低电平脉宽
uint t2=0;	//一个周期
uint time_low=0;
uint time_high=100;

bit high_flag=0;
bit low_flag=0;
bit state_flag=0;
uint set_count=100;//设定转速值
uint run_count=0;//实际频率的读取
uint stop_count=0;	  //电机转速存储变量
uint time=0;

int en=0,en_1=0,en_2=0;  			//定义 三个时刻的误差存储变量
float  a0=1.7,a1=0.30,a2 =0.002,un=0;  //定义PID计算参公式的参数

void delay1_ms(uint time);
void delay(uint time);
void display_num1(uint dat,uchar num1);
void display_num4(uint num);
void time01_initiat(void);
void key_precess(void);
void pid(void);


void main()
{
	time01_initiat(); //初始化定时器0和定时器1
	while(1)
	{
	   key_precess();		//键盘扫描函数
	}
}
//1ms延时函数
void delay1_ms(uint time)
{
	 uint i,j;
	 for(i=0;i<time;i++)
	 for(j=0;j<123;j++);
}
 //指定的位上显示 指定的一位数据
void display_num1(uint dat,uchar num1)
{

	P0=xianshi[dat];	//段显
	switch(num1)
	{
		case 1:	P2=0x01;break;
		case 2:	P2=0x02;break;
		case 3:	P2=0x04;break;
		case 4:	P2=0x08;break;
		default: break;
	}
	delay1_ms(2);

}
//四位数据显示函数
void display_num4(uint num)
{
	uint qian;
	uint bai;
	uint shi;
	uint ge;

	qian=num/1000;
	if(qian==0)//	qian=11;
	display_num1(11,4);
	bai=num%1000;
	bai=bai/100;
	if(qian==10&&bai==0) bai=10;
	display_num1(bai,3);
	shi=num%100;
	shi=shi/10;
	if(qian==10&&bai==10&&shi==0)	shi=10;
	display_num1(shi,2);
	ge=num%10;
	display_num1(ge,1);
}

//四位数据显示函数
void display_num4_1(uint num)
{
	uint qian;
	uint bai;
	uint shi;
	uint ge;
	display_num1(10,4);
	bai=num%1000;
	bai=bai/100;
	if(qian==10&&bai==0) bai=10;
	display_num1(bai,3);
	shi=num%100;
	shi=shi/10;
	if(qian==10&&bai==10&&shi==0)	shi=10;
	display_num1(shi,2);
	ge=num%10;
	display_num1(ge,1);
}

void delay(uint time)
{
	 uint i;
	 for(i=0;i<time&&key1==1;i++)
	 display_num4_1(stop_count);
}


void delay1(uint num)
{
	 uint i;
	 for(i=0;i<num;i++)
	 display_num4(set_count);
}


void time01_initiat()
{	
	TMOD=0X11; //计数器0和定时器1
	TL0=0X33;
	TH0=0XFE;//计数器0赋初值  0.5ms
	TH1=0X4C;
	TL1=0X00;//定时器1赋初值  50ms
	EA=1;
	PT0=1;
	ET0=1;	
	ET1=1;
	TR0=0;
	TR1=0;
	IT0=1;
	EX0=0;
}

void key_precess()
{
	if(key1==0&&key2==1&&key3==1) //判断系统的运行模式,如果KEY1键	按下
	//且state_flag为1则系统处于运行模式,如果state__flag为0则为设置模式
	{
		while(key1==0);
		state_flag=~state_flag;
		if(state_flag==1)
		{
			EX0=1;
			TR1=1;
			TR0=1;
			en =0;
			en_1 =0;
			en_2 =0;
			un =0;
            wide=150;
		    //wide = set_count;
		}
	}

	if(key1==1&&key2==0&&key3==1&&state_flag==0)   //KEY2为按键加
	{
		//while(key2==0);
	 	delay1(20);
		set_count+=1;
		if(set_count>300) set_count=100;
	}
	if(key1==1&&key2==1&&key3==0&&state_flag==0) //KEY3为按键减
	{
	//	while(key3==0);
     	delay1(20);
		if(set_count>100) set_count-=1;
		if(set_count==100) set_count=300;
	}
	if(state_flag==0) //如果系统处于设置模式,则关闭定时器中断和外部中断,同时初始化部分变量
	{
	    PWM = 0;
		EX0=0;
		TR0=0;
		TR1=0;
		run_count=0;
		stop_count=0;

		time=0;
		t1=0;
		t2=0;
		display_num4(set_count);
		
	}
	if(state_flag==1)  //如果系统处于运行模式则显示电机的实际转速值
	{

		display_num4_1(stop_count);

	} 
}
void pid(void)	 //PID 计算输出量
{
 
     en=set_count-stop_count;
  
	 un=1.7*en-0.03*en_1+0.002*en_2;//计算输出量 	
	 if(un > 400)un = 400;
	 if(un <-400)un = -400;

       en_2=en_1;	//更新误差
       en_1=en;

	   wide = wide + un/4;  //计算wide,用于调节PWM的占空比,计算周期为100ms

		if(wide>900)wide=900;  //防止超限,确保计算饿wide值有效
		if(wide<10)wide=10;  

}
//外部中断0用于电机转速测量
void int0() interrupt 0
{
	  EX0=0;
	  run_count++;
	  EX0=1;
}
 //定时器0用于产生PWM	,占空比通过PID计算获得
void time0() interrupt 1
{	

	TL0=0X9c;
	TH0=0XFF;//计数器0赋初值  100us
	TR0=0;
	if(low_flag==0)t1++;//低电平时间计时
   	     t2++; 
	if(t2==1000)	 //用于确定PWM的周期  ,t2乘以定时器的中断周期即为PWM的周期
	{
		 PWM=1;
		 t2=0;
		 low_flag=0;

	}
	if(t1==wide)//wide的值即为低电平的时间
	{
		PWM=0;
		t1=0;
		low_flag=1;
	}
	
	TR0=1;
}

void time1() interrupt 3
{
	TH1=0X3C;
	TL1=0XBD;  //50ms定时
	TR1=0;
	time++;
	if(time==40)	 //定时2s到,读取到的值run_count即为电机每秒的转速值
	{	
		stop_count=run_count/2;
		time=0;
		run_count=0;
		pid();	 //调用PID算法
	} 
	TR1=1;
}


-End-





posted on 2016-11-08 19:52  王亮1  阅读(403)  评论(0编辑  收藏  举报

导航