直流电机PID转速闭环调速控制系统

在工业自动控制系统和各种智能产品中常常会用用电动机进行驱动、传动和控制,而现代智能控制系统中,对电机的控制要求越来越精确和迅速,对环境的适应要求越来越高。随着科技的发展,通过对电机的改造,出现了一些针对各种应用要求的电机,如伺服电机、步进电机、开关磁阻电机等非传统电机。但是在一些对位置控制要求不高的电机控制系统如传动控制系统中,传统电机如直流电机乃有很大的优势,而要对其进行精确而又迅速的控制,就需要复杂的控制系统。随着微电子和计算机的发展,数字控制系统应用越来越广泛,数字控制系统有控制精确,硬件实现简单,受环境影响小,功能复杂,系统修改简单,有很好的人机交换界面等特点。
在电机控制系统开发中,常常需要消耗各种硬件资源,系统构建时间长,而在调试时很难对硬件系统进行修改,从而延长开发周期。随着计算机仿真技术的出现和发展,可用计算机对电机控制系统进行仿真,从而减小系统开发开支和周期。计算机仿真可分为整体仿真
和实时仿真。整体仿真是对系统各个时间段对各个对象进行计算和分析,从而对各个对象的变化情况有直观的整体的了解,即能对系统进行精确的预测,如Matlab就是一个典型的实时仿真软件。实时仿真是对时间点的动态仿真,即随着时间的推移它能动态仿真出当时系统的状态。Proteus是一个实时仿真软件,用来仿真各种嵌入式系统。它能对各种微控制器进行仿真,本系统即用Proteus对直流电机控制系统进行仿真。
在系统软件开发中开发中可用操作系统,也可不用操作系统。如用操作系统,程序可实现模块化,并能对系统资源进行统筹管理,最主要的是可实现多任务运行。如果需要多任务并行运行,并且需要一定的时间间隔,某些任务对时间的要求不高时,如不用操作系统则要占用定时器资源,并且对栈空间和硬件资源很难进行管理,所以在这种情况下需要操作系统。本系统用操作系统uC/COS.
uC/COS是一个完整的、可移植、可固化、可剪裁的占先式实时多任务内核.uC/COS
已经有很多产品成功使用的案例且得到美国军方的认证,说明了该系统的可靠性。uC/COS
源代码公开,代码短,源代码大部分是使用ANSI C编写的,移植性和裁减性好,功能强大,
能可靠应用于各种控制系统中。
   系统构成

直流电机PID转速闭环调速控制系统_第1张图片

硬件全图
直流电机PID转速闭环调速控制系统_第2张图片

各子系统
1. 转速控制输入
如用按键输入则需要复杂的软件实现,并且需要足够的引脚资源,本系统用ADC0832采样电位器上的电压信号来实现转速信号输入。
直流电机PID转速闭环调速控制系统_第3张图片

2.LPC2106微控制器
LPC2106是Phlip公司推出的核心为ARM的控制器。LPC2106 包含一个支持仿真的ARM7TDMI-S CPU、与片内存储器控制器接口的ARM7 局部总线、与中断控制器接口的AMBA 高性能总线(AHB)和连接片内外设功能的VLSI 外设总线(VPB,ARMAMBA 总线的兼容超集)。片内有64K 字节静态RAM和128K的FLASH存储器。可寻址4GB。
在本仿真中LPC2106没加晶振电路,频率在芯片属性中设置。
直流电机PID转速闭环调速控制系统_第4张图片

3.液晶显示
本系统采用Proteus仿真库有的液晶显示模块AMPIRE128X64,为8192像素的单色LCD
屏幕分为两半控制,控制引脚为CS1和CS2。数据通过移位寄存器输入。

直流电机PID转速闭环调速控制系统_第5张图片

4.电机驱动电路
本系统仿真的是最大输入电压为12伏的微型电机,故用通用电机驱动电路实现假设该电路输入电阻为无穷大,输出电阻为0。
直流电机PID转速闭环调速控制系统_第6张图片

5.仿真电机的51单片机
虽然Proteus有电机模块,但其电机模块没有输出转速接口故用一单片机代替它,单片机用ADC0832采样输入的电压,经过处理即输出和真实电机同步的转速(需要大量的浮点运算,可考虑用DSP)。通过两个按键改变转矩没按一次增大或减小0.001,上面的是增大。
直流电机PID转速闭环调速控制系统_第7张图片

6.仿真结果
仿真1.8秒钟后得下图,可看到转速逐渐增大然后稳定下来。
直流电机PID转速闭环调速控制系统_第8张图片

增大转矩后,可看到转速下降后又恢复

直流电机PID转速闭环调速控制系统_第9张图片

/******************************************************************************
**       实时微型直流电机PID转速闭环调速控制系统程序(基于移植于LPC2106上的uc/cos实时操作系统)
**                            
******************************************************************************/
#include "config.h"
#include "LCD.h"

#define  TASK_STK_SIZE                  512	   //各任务栈大小
#define  IO_Init()       \
          PINSEL0= 2;    \
		  IODIR|= 0x00007FB0;			  //P0.4\P0.5\P0.7-P1.4为输出其他的为输入
#define  Umax 1000						   //最大调节转速
#define  Kp 0.7							   //比例放大系数
#define  Ts 0.03							   //采样周期
#define  t0 4								   //积分时间常数
#define  td 0.0005							   //微分时间常数
#define  q0  Kp*(1+Ts*t0+td/Ts)
#define  q1  -Kp*(1+2*td/Ts) 
#define  q2  Kp*td/Ts
#define  ADC_DO	 0x00000040		       //P0.6
#define  ADC_CS	 0x00000080		       //P0.7
#define  ADC_CLK 0x00000100			   //P0.8
#define  ADC_DI  0x00000200			   //P0.9
OS_STK        Main_TaskStk[TASK_STK_SIZE];
OS_STK        Task1_TaskStk[TASK_STK_SIZE];
OS_STK        Task2_TaskStk[TASK_STK_SIZE];
OS_STK        Task3_TaskStk[TASK_STK_SIZE];
OS_STK        Task4_TaskStk[TASK_STK_SIZE];		//各任务栈
OS_EVENT      *Conbox;							   //控制信号邮箱
float n=0;										       // 输入转速
float nb=0;										   // 反馈转速
void Main_Task(void *data);
void Task1(void *p_arg);
void Task2(void *p_arg);
void Task3(void *p_arg);
void Task4(void *p_arg);						 //函数声明
void PWMInit(void)							   
{
     
    PWMPR = 0x00;			    // 不分频,计数频率为Fpclk
    PWMMCR = 0x02;			    // 设置PWMMR0匹配时复位PWMTC
	PWMMR0 = 2765;    		    // 设置PWM周期
    PWMMR1 = 0;			    // 设置PWM占空比
    PWMLER = 0x03;			    // PWMMR0、PWMMR1锁存
    PWMPCR = 0x0200;			// 允许PWM1输出,单边PWM
    PWMTCR = 0x09;			    // 启动定时器,PWM使能
	PWMMR0 = 2765;    		    // 设置PWM周期
    PWMMR1 = 0;			    // 设置PWM占空比
    PWMLER = 0x03;			    // PWMMR0、PWMMR1锁存

}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: c语言的主函数,由它启动多任务环境
********************************************************************************************************/
int main (void)
{
     
    OSInit();
    OSTaskCreate(Main_Task, (void*)0, &Main_TaskStk[TASK_STK_SIZE - 1], 0);
    OSStart();
	return 0;
}
                        
/******************************************************************************
** 函数名称: Main_Task
** 功能描述: 初始化系统及建立任务
******************************************************************************/
  void  Main_Task(void *p_arg)
{
       
   p_arg = p_arg;                                         // 避免编译警告 
   TargetInit();
   IO_Init();                                      
   Conbox = OSMboxCreate((void*)0);	
   LCD_Main();	
   OSTaskCreate(Task1, (void *)0, &Task1_TaskStk[TASK_STK_SIZE - 1], 2);
   OSTaskCreate(Task2, (void *)0, &Task2_TaskStk[TASK_STK_SIZE - 1], 3);
   OSTaskCreate(Task3, (void *)0, &Task3_TaskStk[TASK_STK_SIZE - 1], 1);
   OSTaskCreate(Task4, (void *)0, &Task4_TaskStk[TASK_STK_SIZE - 1], 5);
   OSTaskSuspend(0);
}

/******************************************************************************
** 函数名称: Task1_Task
** 功能描述: 实时任务,负责采样和处理数据
******************************************************************************/
 void Task1(void *p_arg)   
 {
      float us;				//上次输出控制信号
   float es;				//上次采样误差信号
   float es2 = 0;			//上次的上次的采样误差信号
   uint32 nj;				//采样转速信号
   float u;				//此次输出控制信号
   float e;				//此次采样误差信号
   p_arg = p_arg;
   PWMInit();			//PWM初始化
   while(1)
  {
      nj=IOPIN>>16;
    nb=(float)nj/10;		//采样反馈转速
    e=n-nb;
	u=us+q0*e+q1*es+q2*es2;	//PID处理
	if(u>=Umax)
	u=Umax;
	es2=es;
	es=e;
	us=u;
    OSMboxPost(Conbox,(void*)&u);  //发送处理后的信号
	OSTimeDlyHMSM(0,0,0,30);
   }
} 
/******************************************************************************
** 函数名称: Task2_Task
** 功能描述: 根据控制信号输出PWM波
******************************************************************************/
 void  Task2(void *p_arg)
 {
       uint8 err;
    float *nh;
    p_arg = p_arg;
    while(1)
   {
     nh=(float*)OSMboxPend(Conbox,0,&err);
    if(*nh>=Umax-0.5)
   {
     PWMMR0 = 2765;
    PWMMR1=  2764;
	PWMLER = 0x03;
	}
	else
   {
     PWMMR0 = 2765;
    PWMMR1=(uint32)(*nh/Umax*2765);
	PWMLER = 0x03;
    }			                             
}
 }
 void Delay(uint8 n)		  //延时函数
 {
     uint8 i;
  for(i=1;i<=n;i++);
 }
/******************************************************************************
** 函数名称: Task3_Task
** 功能描述: 定时采样输入的转速要求(0832采样)
******************************************************************************/
 void Task3(void *p_arg)
 {
       uint8 ch,i,flag=0;
    p_arg=p_arg;
    ch=0;
    IOCLR=ADC_CS;
    IOCLR=ADC_DI;//片选,DO为高阻态
    for(i=0;i<10;i++)
    {
     ;}
	IOCLR=ADC_CLK;
     Delay(4);
     IOSET=ADC_DI; 
     IOSET=ADC_CLK; 
     Delay(4);     //第一个脉冲,起始位 
     IOCLR=ADC_CLK; 
     Delay(4); 
     IOSET=ADC_DI; 
     IOSET=ADC_CLK;
     Delay(4);     //第二个脉冲,DI=1表示双通道单极性输入
     IOCLR=ADC_CLK;
     Delay(4);
	 IOSET=ADC_DI; 
     IOSET=ADC_CLK;
     Delay(4);     //第三个脉冲,DI=1表示选择通道1(CH2)
     IOCLR=ADC_DI; //DI转为高阻态,DO脱离高阻态为输出数据作准备
     IOSET=ADC_CLK;
     Delay(4);
     IOCLR=ADC_CLK; 
     Delay(4);     //经实验,这里加一个脉冲AD便能正确读出数据
     for (i=0; i<8; i++)
    {
      IOSET=ADC_CLK; 
      Delay(4); 
      IOCLR=ADC_CLK; 
      Delay(4);
	  if((IOPIN & ADC_DO)!=0)
      ch=(ch<<1)|1;//在每个脉冲的下降沿DO输出一位数据,最终ch为8位二进制数
	  else
	  ch=(ch<<1)|0;
     }
     IOSET=ADC_CS;
	 n=(float)ch*1000/256;
	 if(flag==0)
	 {
     flag=1;
	  OSTaskChangePrio(1,4);
	 }
	 OSTimeDlyHMSM(0,0,0,300);
	}
/******************************************************************************
** 函数名称: Task4_Task
** 功能描述: 液晶显示任务
******************************************************************************/
 void Task4(void *p_arg)
 {
     
 #if OSCRITICAL_METHOD ==3
      OS_CPU_SR cpu_sr;
  #endif
  uint16 w,q,k;
  uint8 i;
  uint8 shu1[6],shu2[6];
  p_arg=p_arg;
  for(;;)
  {
     shu1[4]=10;
   w=(uint16)(n*10);
   k=10000;
   for(i=0;i<4;i++)
   {
     shu1[i]=(uint8)(w/k);
    w=w%k;
	k=k/10;
   }
  shu1[5]=(uint8)w;
  OS_ENTER_CRITICAL();
  LCD_num(80,2,shu1,6);
  shu2[4]=10;
  q=(uint16)(nb*10);
  k=10000;
  for(i=0;i<4;i++)
   {
     shu2[i]=(uint8)(q/k);
    q=q%k;
	k=k/10;
   }
  shu2[5]=(uint8)q;
  LCD_num(80,4,shu2,6);
  OS_EXIT_CRITICAL();
  OSTimeDlyHMSM(0,0,0,100);
  }
 } 

/******************************************************************************
**                            End Of File
******************************************************************************/
2.自编的LCD驱动程序
  (1)头文件LCD.h
/******************************************************************************
**                           LCD驱动头文件LCD.h(基于LPC21**)
**                              程序编写者:	  吴斌
**                              编写日期:    2007年11月12日
******************************************************************************/
#ifndef _LCD_H_
#define _LCD_H_
#include "config.h"
#define	 SPI_CLK	0x00000010		 //P0.4 
#define  SPI_DATA	0x00000020		 //P0.5 
#define  RW         0x00000800      //RW
#define  RS         0x00000400       //RS
#define  CS1        0x00001000       //CS1
#define  CS2        0x00002000       //CS2
#define  E          0x00004000       //E
#define  Kai        0x3F
#define  Guang      0x3E
#define  Hang       0xC0
#define  Ye         0xB8
#define  Lie    	   0x40
		                  	          		  
#define  Setlie(a)  	  \
          IOCLR = RW;	  \
          IOCLR = RS;	  \
		  send(Lie+a);
		 
#define  Setye(a)  		  \
          IOCLR = RW;  	  \
          IOCLR = RS;	  \
		  send(Ye+a);
		  
#define  Setweizi(a,b)          \
          IOCLR = RW;			\
          IOCLR = RS;			\
		  send(Lie+a);			\
		  send(Ye+b);

#define  Write(a)		  \
          IOCLR = RW;	  \
          IOSET = RS;	  \
          send(a);
void send(uint8 dat);
void LCD_disp(uint8 a,uint8 b,uint8 c,uint8 d,uint8 m,uint8 *shuju)	;
void SetCS(uint8 a);
void LCD(uint8 a,uint8 b,uint8 c,uint8 d, uint8 *shuju);
void LCD_num(uint8 a,uint8 b,uint8 *shuju,uint8 n);
void LCD_str(uint8 a,uint8 b,uint8 *strtab,uint8 n);
void LCD_hanzi(uint8 a,uint8 b,uint8 *hanzitab,uint8 n);
void LCD_xian(uint8 a,uint8 b,uint8 *strtab,uint8 n);
void LCD_Main(void);
#endif
/******************************************************************************
**                            End Of File
******************************************************************************/
  (2)LCD驱动程序LCD.c
/******************************************************************************
**                           LCD驱动程序(基于LPC21**)
**                              程序编写者:	  吴斌
**                              编写日期:    2007年11月12日
******************************************************************************/
#include"LCD.h"
void send(uint8 dat)						 //用移位寄存器输出一字节数据
{
       uint8  i;
   IOSET = E;			        //   E = 1
   for(i=0; i<8; i++)			// 发送8位数据
   {
       IOCLR = SPI_CLK;			// SPI_CLK = 0
      if( (dat&0x80)!=0 ) IOSET = SPI_DATA;
        else IOCLR = SPI_DATA;
        dat <<= 1;
        IOSET = SPI_CLK;			// SPI_CLK = 1
   }
   IOCLR = E;			    // E = 0
}
void LCD_disp(uint8 a,uint8 b,uint8 c,uint8 d,uint8 m,uint8 *shuju)	/*LCD显示函数,在第a列b页输出大小为c*d的图像(只能选择在左或右屏幕显示) */
{
     uint8 i,j,f;
 SetCS(m);
 for(j=0;j<d;j++)
 {
     Setweizi(a,j+b);
  for(i=0;i<c;i++)
  {
     Write(*(shuju+i));
   for(f=0;f<0xFF;f++);
  }
 }
}
 void SetCS(uint8 a)
 {
     if(a==0)
  {
     IOSET =CS2;
   IOCLR =CS1;
   }
   else
   {
     IOSET =CS1;
    IOCLR =CS2;
   }
  }
void LCD(uint8 a,uint8 b,uint8 c,uint8 d, uint8 *shuju)	   /*LCD主显示函数,在第a列b页输出大小为c*d的图像*/
{
     uint8 i,j,m,f,n;
 uint8 *p=shuju;
 if(a+c<=64)
 {
     SetCS(0);
  for(j=0;j<d;j++)
  {
     Setweizi(a,j+b);
   for(i=0;i<c;i++)
   {
     Write(*p);
    p++;
    for(f=0;f<0xFF;f++);
    }
   }
  }
 else if(a<64&&(a+c)>64)
 {
     m=64-a;
  n=c-m;
  for(j=0;j<d;j++)
  {
     SetCS(0);
   Setweizi(a,j+b);
   for(i=0;i<m;i++)
   {
     Write(*p);
    p++;
    for(f=0;f<0xFF;f++);
    }
    SetCS(1);
	Setweizi(0,j+b);
    for(i=0;i<n;i++)
    {
     Write(*p);
     p++;
     for(f=0;f<0xFF;f++);
     }
   }
  }
 else
 {
     SetCS(1);
  for(j=0;j<d;j++)
  {
     Setweizi(a-64,j+b);
   for(i=0;i<c;i++)
   {
     Write(*p);
    p++;
    for(f=0;f<0xFF;f++);
    }
   }
  }
}
void LCD_num(uint8 a,uint8 b,uint8 *shuju,uint8 n)	/*在第a列b页显示shuju数组的数字或小数点和空格*/
{
     uint8 numzimo[192]={
     0xFF,0x1F,0xEF,0xF7,0xF7,0xEF,0x1F,0xFF,0xFF,0xF0,0xEF,0xDF,0xDF,
0xEF,0xF0,0xFF, /*"0",0*/
0xFF,0xEF,0xEF,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xDF,0xC0,0xDF,0xDF,0xFF,0xFF,
/*"1",1*/
0xFF,0x8F,0xF7,0xF7,0xF7,0x77,0x8F,0xFF,0xFF,0xCF,0xD7,0xDB,0xDD,0xDE,0xCF,0xFF,
/*"2",2*/
0xFF,0xCF,0xF7,0x77,0x77,0xB7,0xCF,0xFF,0xFF,0xE7,0xDF,0xDF,0xDF,0xEE,0xF1,0xFF,
/*"3",3*/
0xFF,0xFF,0x3F,0xDF,0xEF,0x07,0xFF,0xFF,0xFF,0xF8,0xFB,0xDB,0xDB,0xC0,0xDB,0xFF,
/*"4",4*/
0xFF,0x07,0xF7,0x77,0x77,0xF7,0xF7,0xFF,0xFF,0xE6,0xDE,0xDF,0xDF,0xEE,0xF1,0xFF,
/*"5",5*/
0xFF,0x1F,0xEF,0x77,0x77,0xE7,0xFF,0xFF,0xFF,0xF0,0xEE,0xDF,0xDF,0xEE,0xF1,0xFF,
/*"6",6*/

0xFF,0xC7,0xF7,0xF7,0x37,0xC7,0xF7,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,
/*"7",7*/
0xFF,0x8F,0x77,0xF7,0xF7,0x77,0x8F,0xFF,0xFF,0xE3,0xDD,0xDE,0xDE,0xDD,0xE3,0xFF,
/*"8",8*/
0xFF,0x1F,0xEF,0xF7,0xF7,0xEF,0x1F,0xFF,0xFF,0xFF,0xCE,0xDD,0xDD,0xEE,0xF0,0xFF,
/*"9",9*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,
/*".",10*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
/*" ",11*/
 uint8 i,f;
 uint8 *p;
 for(i=0;i<n;i++)
 {
     f=*(shuju++);
  p=numzimo+f*16;
  LCD(a,b,8,2,p);
  a=a+8;
 }
}
void LCD_str(uint8 a,uint8 b,uint8 *strtab,uint8 n)	  /*在第a列b页显示ASCII字符串(要点阵数据)*/
{
     uint8 i;
 for(i=0;i<n;i++)
 {
     LCD(a,b,8,2,strtab);
  a=a+8;
  strtab=strtab+16;
 }
}
void LCD_hanzi(uint8 a,uint8 b,uint8 *hanzitab,uint8 n)  /*在第a列b页显示汉字串(要点阵数据)*/
{
     uint8 i;
 for(i=0;i<n;i++)
 {
     LCD(a,b,16,2,hanzitab);
  a=a+16;
  hanzitab=hanzitab+32;
 }
}
void LCD_xian(uint8 a,uint8 b,uint8 *strtab,uint8 n)	 //显示ASCII字符串到顶时换行
{
     uint8 m;
 if(a+(n-1)*8<=120)
   LCD_str(a,b,strtab,n);
 else
   {
     if(a%8>0)
    m=a/8+1+n-16;
    else
    m=a/8+n-16;
    LCD_str(a,b,strtab,n-m);
    LCD_str(0,b+2,strtab+16*(n-m),m);
   }
}
void LCD_Main(void)			  //本系统显示主界面
{
     uint8 i;
uint8 zifu[80]={
     0xF7,0x07,0xF7,0xFF,0xFF,0xF7,0x07,0xF7,0xFF,0xE0,0xDF,0xDF,0xDF,0xDF,
0xE0,0xFF,/*"U",0*/
0xFF,0xFF,0xFF,0xFF,0x7F,0x9F,0xE7,0xFB,0xFF,0x9F,0xE7,0xF9,0xFE,0xFF,0xFF,0xFF,
/*"/",1*/
0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xF1,0xEE,0xDF,0xDF,0xDF,0xEE,0xFF,
/*"c",2*/
0xFF,0xFF,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xE0,0xDF,0xDF,0xDF,0xDF,0xE0,0xFF,
/*"o",3*/
0xFF,0xFF,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xCC,0xDB,0xDB,0xDB,0xDB,0xE6,0xFF};/*"s",4*/
uint8 inputn[160]=
{
     0xBB,0x0B,0xB0,0x1B,0xBB,0x9B,0x6F,0x67,0x6B,0x6C,0xEB,0x67,0xF7,0x2F,0xEF,0xFF,
0xFB,0xFB,0xFB,0x00,0xFD,0xFD,0x00,0xB5,0x75,0x80,0xFF,0xC0,0x7F,0x00,0xFF,0xFF,
/*"输",0*/
0xFF,0xFF,0xFF,0xFF,0xFE,0x7C,0x89,0xE7,0x9F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xBF,0xDF,0xEF,0xF7,0xF9,0xFE,0xFF,0xFF,0xFF,0xFF,0xFC,0xFB,0xE7,0xCF,0xEF,0xFF,
/*"入",1*/
0x37,0x57,0x63,0x14,0x77,0x77,0x77,0xBF,0xB7,0x07,0xB0,0xB7,0xB7,0xB7,0xBF,0xFF,
0xF7,0xF7,0xFB,0x00,0xFB,0xFB,0xFF,0xFD,0xF4,0xED,0xDD,0x2D,0xF1,0xFD,0xFF,0xFF,/*"转",2*/
0xBF,0xBD,0x33,0xFF,0xFB,0x1B,0xDB,0xDB,0x0,0xDB,0xDB,0xDB,0x1B,0xFB,0xFF,0xFF,
0xBF,0xDF,0xE0,0xDF,0xB7,0xB6,0xBA,0xBC,0x80,0xBE,0xBC,0xBA,0xB2,0xBF,0xBF,
0xFF,/*"速",3*/

0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xC9,0xC9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
/*":",4*/
uint8 outputn[160]={
     0xBB,0x0B,0xB0,0x1B,0xBB,0x9B,0x6F,0x67,0x6B,0x6C,0xEB,0x67,0xF7,
0x2F,0xEF,0xFF,
0xFB,0xFB,0xFB,0x00,0xFD,0xFD,0x00,0xB5,0x75,0x80,0xFF,0xC0,0x7F,0x00,0xFF,0xFF,
/*"输",0*/
0xFF,0xFF,0x03,0xBF,0xBF,0xBF,0xBF,0x00,0xBF,0xBF,0xBF,0xBF,0xBF,0x03,0xFF,0xFF,
0xFF,0xFF,0x81,0xDF,0xDF,0xDF,0xDF,0xC0,0xDF,0xDF,0xDF,0xDF,0xDF,0x81,0xFF,0xFF,
/*"出",1*/
0x37,0x57,0x63,0x14,0x77,0x77,0x77,0xBF,0xB7,0x07,0xB0,0xB7,0xB7,0xB7,0xBF,0xFF,
0xF7,0xF7,0xFB,0x00,0xFB,0xFB,0xFF,0xFD,0xF4,0xED,0xDD,0x2D,0xF1,0xFD,0xFF,0xFF,/*"转",2*/
0xBF,0xBD,0x33,0xFF,0xFB,0x1B,0xDB,0xDB,0x0,0xDB,0xDB,0xDB,0x1B,0xFB,0xFF,0xFF,
0xBF,0xDF,0xE0,0xDF,0xB7,0xB6,0xBA,0xBC,0x80,0xBE,0xBC,0xBA,0xB2,0xBF,0xBF,
0xFF,/*"速",3*/
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xC9,0xC9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
/*":",4*/
 uint8 xinhao[16]={
     0xBF,0xBF,0x7F,0x0F,0x7F,0xBF,0xBF,0xFF,0xFD,0xFD,0xFE,0xF0,0xFE,
0xFD,0xFD,0xFF};/*"*",0*/
 LCD_str(44,0,zifu,5);
 LCD_hanzi(0,2,inputn,5);
 LCD_hanzi(0,4,outputn,5);
 for(i=0;i<16;i++)
 {
      LCD_str(i*8,6,xinhao,1);
 }
}
/******************************************************************************
**                            End Of File
******************************************************************************/
3. 用AT89S52单片机仿真直流电动机程序
/******************************************************************************
**                          用AT89S52单片机仿真直流电动机程序
**                              程序编写者:	  吴斌
**                              编写日期:    2007年11月11日
******************************************************************************/ 
   #include 
   #include  
   #include 
   #define La 0.1				//电枢电感
   #define CeQ 0.005
   #define CmQ 0.2				//
   #define Ja 0.0000018			//转动惯量
   #define Ra 10
   #define Ra-La 11.9
   sbit ADC_CS =P3^4;
   sbit ADC_CLK=P3^5;
   sbit ADC_DI =P3^6;
   unsigned int nc; 
   float TL=0.1;
   float Te;
   float Tz=0;
   float Ts=0;
   float U=0.68;
   float Uz=0;
   float ia=0;
   float iaz=0;
   float ias=0;
   float ea=0;
   float eaz=0;
   float eas=0;
   float n=0;
   bit   f=0;
   bit   e=0;

	void Delay(unsigned char x)

{
      
  unsigned char i; 
  for(i=0;i<x;i++);
}
   void INTf0(void)interrupt 0
   {
     TL=TL+0.001;
   }
   void INTf1(void)interrupt 2
   {
     TL=TL-0.001;
   } 

   void timer0(void)interrupt 1
   {
     unsigned int i,ch;
    ch=0;
    ADC_CS=0;
    ADC_DI=0;
    for(i=0;i<10;i++)
    {
     ;}
	 ADC_CLK=0;
     Delay(2);
     ADC_DI=1; 
     ADC_CLK=1; 
     Delay(2); 
     ADC_CLK=0; 
     Delay(2); 
     ADC_DI=0; 
     ADC_CLK=1;
     Delay(2);
     ADC_CLK=0;
     Delay(2);
	 ADC_DI=0; 
     ADC_CLK=1;
     Delay(2); 
     ADC_DI=0; 
     ADC_DI=1;
     ADC_CLK=1;
     Delay(2);
     ADC_CLK=0; 
     Delay(2);
     for (i=0; i<8; i++)
    {
      ADC_CLK=1; 
      Delay(2); 
      ADC_CLK=0; 
      Delay(2);
      ch=(ch<<1)|ADC_DI;
     }
     ADC_CS=1;
	 U=0.1*(float)ch/256;
	 Uz=Uz+U;
     ia=(Uz-iaz*Ra-eaz)/(Ra*0.01+La);
	 Te=CmQ *ia;
     if(f==0);
	 {
     f=1;
	   ias=ia;
	   Ts=Te-TL;
	  }
	 if(n<=0&&Te<TL&&e==0)
	 n=0;
	 else
	 {
     e=1;
	  Tz=Tz+(1.5*(Te-TL)-0.5*Ts)*0.01;
	  Ts=Te-TL;
	  n=Tz/Ja;
    	}
    ea=CeQ *n;
	eaz=eaz+(1.5*ea-0.5*eas)*0.01-U*0.9727;
	eas=ea;
	Uz=Uz-U;
	iaz=iaz+(1.5*ia-0.5*ias)*0.01-U*0.0273/Ra;
	ias=ia;
	nc=	(unsigned int)(n*10);
	P2=nc/256;
	P0=nc%256; 
	printf("n=%f,i=%f\n",n,ia);
	TH0 =-(9216/256);
	TL0 =-(9216%256);
	}
    
   main()
   {
     int i;
    TCON  = 0x0F;
    SCON  = 0xDA;    
    TMOD |= 0x20;     
    TH1   = 0xFD;       
    TR1   = 1;          
    TI    = 1;           
	TH0 = -(9216/256);
	TL0 = -(9216%256);
	EX0=1;
	EX1=1;
	PX1=1;
	EA =1;
	ET0 =1;
	TR0= 1;
	while(1)
	{
     ;}
 }
/******************************************************************************
**                            End Of File
******************************************************************************/



你可能感兴趣的:(单片机)