zoukankan      html  css  js  c++  java
  • 计算机控制技术实验说明

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

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





  • 相关阅读:
    大型网站随着业务的增长架构演进
    springboot日志logback配置
    一些容易出错的细节
    从一个下载优化说起
    徒手优化冒泡排序
    php设计模式之观察者模式
    php设计模式之抽象工厂模式
    phper談談最近重構代碼的感受(3)
    php设计模式----工厂模式
    偏执的我从Linux到Windows的感受
  • 原文地址:https://www.cnblogs.com/liang123/p/6324835.html
Copyright © 2011-2022 走看看