首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >计算机控制技术实验说明

计算机控制技术实验说明

作者头像
zhangrelay
发布2019-01-23 11:30:24
4930
发布2019-01-23 11:30:24
举报

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

实验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-

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年11月08日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档