计算机控制技术实验说明
【摘要】 编程实验分别仿真和实验台操作两种方式。
实验1 AD转换--输入
AD转换是所有嵌入式系统或机器人获取外部信息的一种重要方式,将温度、角度和位置等转换为对应的数字量,供处理器处理。
原理图:
程序:
/*************** ex1 ******************/#include <reg52.h>#define uint unsign...
编程实验分别仿真和实验台操作两种方式。
实验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;
-
}
文章来源: zhangrelay.blog.csdn.net,作者:zhangrelay,版权归原作者所有,如需转载,请联系作者。
原文链接:zhangrelay.blog.csdn.net/article/details/53085968
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)