原创 电机调速控制系统_主程序

2008-3-13 18:36 4871 9 11 分类: 汽车电子

这个是电机调速控制系统的程序,单片机是AVR的mega16,采用液晶显示,电路图在前面已经发过了。


#include <mega16.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include "first.c"
#include "pid.c"
#include "delay.c"
#include "key_4.c" 
#include "1602a.c"
// Declare your global variables here
bit s1; //停止/开始
bit s2; //正转反转


// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here
TCNT0=0x83;
  
 if(++tc>250)
   {  
     tc="0";
    #asm("cli"); 
    read="1";
    }
   if (++key_stime_counter >=3)//定时10MS
  {      
   key_stime_counter = 0;
   key_stime_ok = 1; 
                 }
}  
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
//read=1;
counter++;
}//end interrupt
 
/**************************读取计数值显示************************/
void read_counter()
{
   unsigned int sett;
   unsigned int count;//计数值    
    count="counter";
   count=(count*60);
  count="count">>3; 
  LcdPos(0,1); //确定光标位置
  LcdWd('p');  //个位 
  LcdWd('r');  //
  LcdWd('e');
  LcdWd('='); 
  LcdPos(11,1); //确定光标位置
  LcdWd('s');  //
  LcdPos(10,1); //确定光标位置
  LcdWd('/');  //
  LcdPos(9,1); //确定光标位置
  LcdWd('n');  //
  LcdPos(8,1); //确定光标位置
  LcdWd(count%10+0x30);  //个位
 
  count/=10;  //十位
  LcdPos(7,1); //确定光标位置
  LcdWd(count%10+0x30);    
 
  count/=10;  //百位
  LcdPos(6,1); //确定光标位置
  LcdWd(count%10+0x30);
  count/=10;  //千位
  LcdPos(5,1); //确定光标位置
  LcdWd(count%10+0x30);
  count/=10;  //万位
  LcdPos(4,1); //确定光标位置
  LcdWd(count%10+0x30);


     sett="set";
     LcdPos(0,0);
     LcdWd('s');
     LcdWd('e');
     LcdWd('t');
     LcdWd('=');     
  LcdPos(11,0); //确定光标位置
  LcdWd('s');
  
  LcdPos(10,0); //确定光标位置
  LcdWd('/');
   
  LcdPos(9,0); //确定光标位置
  LcdWd('n');
  LcdPos(8,0); //确定光标位置
 
  LcdWd(sett%10+0x30);
  sett/=10;
 
  LcdPos(7,0); //确定光标位置
  LcdWd(sett %10+0x30);    
  sett/=10;
 
  LcdPos(6,0); //确定光标位置
  LcdWd(sett%10+0x30);
 
  sett/=10;
  LcdPos(5,0); //确定光标位置
  LcdWd(sett%10+0x30);
  sett/=10;
 
  LcdPos(4,0); //确定光标位置
  LcdWd(sett%10+0x30);   
  counter="0";
    #asm("sei");
}//end read_counter
/***************************主函数***********************************/
void main(void)
{
   
    double      rOut;                   //  PID Response (Output)
    double      rIn;                    //  PID Feedback (Input)
   PIDInit ( &sPID );                  //  Initialize Structure
   ocr="700";
  set="1500";
    sPID.Proportion =1.5;              //  Set PID Coefficients
   // sPID.Integral   = 0.683;
   // sPID.Derivative = 0.683;
  sPID.SetPoint =set;            //  Set PID Setpoint
  sPID.SetPoint=sPID.SetPoint/60.0;
  #asm("cli");


PORTA=0x00;   //液晶
DDRA=0XFF;
PORTB=0x00;
DDRB=0x0F;//0000 1111  
PORTC=0x00;
DDRC=0x00;
PORTD=0x30;//0000 0000  PD2外部中断入口
DDRD=0x30;//0011 0000


// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125.000 kHz
// Mode: CTC top="OCR0"
// OC0 output: Disconnected
TCCR0=0x04; //定时4MS*500
TCNT0=0x83;
OCR0=0x82;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 1000.000 kHz
// Mode: Ph. correct PWM top="00FFh"
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xc3;//选通OC1A
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x03;
OCR1AL=0xff;
OCR1BH=0x03;
OCR1BL=0xff;//对应着PD4口的PWM波,
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top="FFh"
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
// INT2: Off
GICR|=0x40;
MCUCR=0x03;
MCUCSR=0x00;
GIFR=0x40;  //通过写1来清0
 


// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;


// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
RstLcd();
key_init(); //键盘初始化
#asm("sei")   // 开放全局中断
 
while (1)
      {
      // Place your code here
//***********************键盘处理*******************************//
      
      if (key_stime_ok)    // 10ms到,键处理
          {
             key_stime_ok = 0;
              switch (read_key())   // 调用按键接口程序  
               {
             /****************复位******************/ 
               case 1:
    { 
    /************键值处理**************/
      s1=!s1;
      if (s1)
      {
        RR
         LcdPos(14,1); //确定光标位置
                       LcdWd('R');  //
                       LcdPos(12,0); //确定光标位置
                       LcdWd('R');
                       LcdWd('U');
                       LcdWd('N');
                       LcdWd(' ');
        }
       else
       {
         ocr="0";
         ST
                      LcdPos(12,0); //确定光标位置
                      LcdWd('S');
                      LcdWd('t');
                      LcdWd('o');
                      LcdWd('p'); 
                      }              
                                 
                   }  break; 
                      case 2:
                   { 
                      s2=!s2;
                      if (s2)
                      {
                        ocr="0";
                        RR//电机正转
                        ocr="700";
                        LcdPos(14,1); //确定光标位置
                         LcdWd('R');  //
                        LcdPos(12,0); //确定光标位置
                          LcdWd('R');
                      LcdWd('U');
                      LcdWd('N');
                      LcdWd(' ');
                      }
                      else
                      {
                      ocr="0";
                      LL
                      ocr="700";
                      LcdPos(14,1); //确定光标位置
                      LcdWd('L');  //
                      LcdPos(12,0); //确定光标位置
                      LcdWd('R');
                      LcdWd('u');
                      LcdWd('n');
                      LcdWd(' ');
                      }
                    
                   }break;
                case 3:
                 
                {  
                  set-=100; //按一次加100
                 if (set<1500)
                  set="4000";
                   }
                  
                   break;
               case 4:
               { 
        //   read_counter();
         //  rIn = sensor ();                //  Read Input
         //  rOut = PIDCalc ( &sPID,rIn );   //  Perform PID Interaction
        //   actuator ( rOut );              //  Effect Needed Changes
              set+=100; //按一次加100
              if (set>4000)
              set="1500";
              }
                 break;
                 }
           }//end keyproc
   //  read_counter();   
     if (read==1)
     {
       read="0";
     if (counter<2) ST  //当有外力时,停止
       sPID.SetPoint=((unsigned int )sPID.SetPoint<<3)/60.0; 
      sPID.SetPoint =set;
      sPID.SetPoint=sPID.SetPoint/60.0;
       rIn = sensor ();                //  Read Input
       rOut = PIDCalc ( &sPID,rIn );   //  Perform PID Interaction
       actuator ( rOut );              //  Effect Needed Changes
       read_counter(); 
     }//end  read
       }//end while
}//end main


/*====================================================================================================
   PID计算部分
=====================================================================================================*/


double PIDCalc( PID *pp, double NextPoint )//NextPOint为下次测量的值
{
    double  Error;
    //dError,
           


       Error = pp->SetPoint - NextPoint;          // 偏差  
         //  Error = NextPoint-pp->SetPoint ;
        //if (Error>3000) ST;
       // pp->SumError += Error;                      // 积分
       // dError = pp->LastError - pp->PrevError;     // 当前微分
        pp->PrevError = pp->LastError;
        pp->LastError = Error;
        return (pp->Proportion *(Error*2.45 -3.0*pp->LastError+1.55 *pp->PrevError)              // 比例项
                     // 积分项
                    // 微分项
        );
}
 
/*====================================================================================================
   Initialize PID Structure
=====================================================================================================*/


void PIDInit (PID *pp)  //定义一下结构类型变量PP
{
    memset ( pp,0,sizeof(PID)); //清空一个结构类型的变量或数组
}


/*====================================================================================================
    Main Program
=====================================================================================================*/


double sensor (void)                    // 接收采集的数据
{  
  // if (counter<30) ST  //当有外力时,停止
    return (counter>>3);
}


void actuator(double rDelta)            // 对接收回来的数进行处理送显示

   ocr="ocr"+rDelta;
  if (TCCR1A==0xc3)  
 
 { 
   OCR1A=ocr;}//  对应着PD5口输出的PWM波,当为0时最大
   if (TCCR1A==0x33)
   {OCR1B=ocr;} 
  if (ocr>1024) ocr="700";
  // if (ocr<300) { ST};//停止
  
 }


/***************定时器0中断进行键盘扫描时间****************/
/***********************************************
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
// Place your code here
if (++key_stime_counter >=5)//定时10MS
  {
   key_stime_counter = 0;
   key_stime_ok = 1; 
                  }
} */
/********************定时器0寄存初始化*********************/
/**********************************************/
void key_init(void)
{
  //TCCR0|=0x0b;//采用比较模式,256分频   8M/256=31.25K
  //TCNT0|=0x00;
  //OCR0=0x3D;// (61+1)/31.25   =2ms
// Timer(s)/Counter(s) Interrupt(s) initialization
 // TIMSK|=0x01;
 // #asm("sei")   // 开放全局中断
}
/***********************************/
/********函数功能说明***************/
/********键盘功能处理***************/
void key_pro(void)
{
      if (key_stime_ok)    // 10ms到,键处理
          {
             key_stime_ok = 0;
              switch (read_key())   // 调用按键接口程序  
               { case 1:
    { /************键值处理**************/
       PORTA="0X11";   
                   }  break;
                case 2:
                     PORTA="0XFE";
                     break;
                case 3:
                   PORTA="0XF1";
                   break;
               case 4:
                 PORTA="0x55";
                 break;
                 }
                
           }
}


/*************键盘扫描*****************/
/****************************************/


char read_key(void)
{
  char key_press, key_return = 0;
  key_press = key_input;  // 读按键I/O电平,当有键按下时为0,没按下时为1
  switch (key_state)
 {
  case key_state_0:    // 按键初始态
      if (key_press!=0x3c) key_state = key_state_1;// 键被按下,状态转换到键确认态
   break;
  case key_state_1:    // 按键确认态
      if (key_press!=0X3C)    //有键按下
    {
 //key_return = 1;   // 按键仍按下,按键确认输出为"1"
 switch (key_press=key_input)
 {
 case 0x1c:
 key_return=1;    break;
 case 0x2c:
 key_return=2;break;
 case 0x34:
 key_return=3;break;
 case 0x38:
 key_return=4;break;
 }   
 key_state = key_state_2; // 状态转换到键释放态
 }
 else
 key_state = key_state_0; // 按键已抬起,转换到按键初始态
 break;
 case key_state_2:       //键已经释放,确认了有键按下
 if (key_press==0x3c)
 key_state = key_state_0; //按键已释放,转换到按键初始态
 break;
  } 
     return key_return;         //当返回为0时,表示没有键按下,
}

文章评论2条评论)

登录后参与讨论

用户166298 2009-5-3 21:37

楼主:能否发那些子程序上来?

用户166298 2009-2-7 22:43

能否发整个程序出来看看!

用户66556 2006-11-23 13:01

非常不错的资料

12864_944456583 2006-11-15 09:04

多谢博主,收藏了,需要时来找啊,呵呵。

用户57318 2006-10-29 16:34

博主,你好哦,由于我的电脑出现了问题,不能下载上面的两个PDF,您能不能把它们发送到我的邮箱来呢? 谢谢哦!

             ----weiajiuge@163.com

用户1347946 2006-10-27 22:30

   不错,不错!向你学习!投你一票.

用户61435 2006-10-27 15:27

我想请教一个问题:

在一根照明电缆上,要分时实现两种交流电压:~220V和~50V,供~220V时,不能供~50V.不供~220V时,才供~50V.交流~50V的电流<1A.交流~220V是由低压开关实现的.

lzy@cie-nj.com

用户10264 2006-10-15 11:05

我正需要这资料了。谢谢了

用户475531 2006-10-13 11:37

下载了您的资料,非常感动.我是初学DSP,对于外围功率器件更是不熟我想选(600~1200V,10~60A,开关频率较高--满足工作时的10KHZ,这样的IGBT三极管--不带二极管的),以及相应的二极管.功率驱动等.请您帮忙,哪里能查到.谢谢
相关推荐阅读
用户1316816 2008-10-19 23:58
写下心情,一段平凡的日子
      2008,不平常的一年,这一年我毕业了,从自己的梦想走入了社会,也许刚入社会,总要有一段适应的过程,从实习到工作,离开学校也快半年了,时间总是过得这么快,有时又觉得又是那么的慢.曾经的梦想...
用户1316816 2008-08-28 20:27
我的毕业设计--存储示波器
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />整个系统采用FPGA Cyclone 2C5芯片,在内嵌...
用户1316816 2008-03-15 12:12
基于FPGA的密码锁
采用4X4键盘电路,和一个四位动显示电路.来完成基本的控制功能 .1.4X4 键盘扫描电路的设计电路中分为键盘去抖电路和键盘译码电路。弹跳消除电路所使用的频率必须比其它电路的工作频率高,扫描电路的工作...
用户1316816 2008-03-13 18:43
简易电压源
/*****************************************************This program was produced by theCodeWizardAVR ...
用户1316816 2008-03-13 18:41
基于1302的万年历
这个是1302程序,液晶用12864来显示...
用户1316816 2008-03-13 18:38
模拟SPI接口程序
//***********************************************************//功能      : 由AVR作为主机,向FPGA发送数据,采用模拟SPI接...
我要评论
2
9
关闭 站长推荐上一条 /2 下一条