计算机控制技术实验说明

网友投稿 564 2022-05-29

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

实验1 AD转换--输入

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

原理图:

程序:

/*************** ex1 ******************/

#include

#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

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); //显示平均值

}

}

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

数字调压:

代码:

#include

#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

#include

#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

}

/**********************************************

输出数据到端口(注意考虑延时)

**********************************************/

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

}

/**********************************************

输出数据到端口(注意考虑延时)

**********************************************/

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();

}

}

实验台:

代码:

#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

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

display_num4_1(stop_count);

}

void delay1(uint num)

{

uint i;

for(i=0;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;

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:物联网网关开发:基于MQTT消息总线的设计过程丨【拜托了,物联网!】
下一篇:凯利公式(庄家必胜篇)——致放假在家的高薪程序员们
相关文章