×
单片机 > 单片机程序设计 > 详情

小型直流电机控制例子

发布时间:2020-06-19 发布时间:
|
初学AVR,手头没有什么具体实践的课题,拆了几个小马达,玩玩中,也学到不少东西。希望可以给初学着一点帮助。 
这个小型的直流电机控制系统很容易就可以实现,采用PWM调速方式,驱动电路,可以用分立元件搭,(网上这种电路很多),也可以采用集成IC器件,我采用的就是L293。电路很简单,就不画图了。 
接线描述如下: 
   PORTC7,PORTC6分别接L293 IN1,IN2,察看L293资料可知,ENA=H,IN1=H,IN2=L正转 
                                                        ENA=H,IN1=L,IN2=H反转 
                                             ENA=H,同IN2(IN4),同IN1(IN3)  快速停止 
                                             ENA=L,                            停止 
   OCR2接L293 ENA 
   测速反馈信号接T0 
代码描述如下: 
   本系统可以同过串口接收上位机控制命令,可以实现开启,停机,调速,及时速度反馈。串口采用接收中断方式,命令协议如下:命令采用M**C模式,所有命令字符串以M开头,C结尾。中间两个字符定义:s表示调速,以第三个命令字符和0xff的比值作为PWM的占空比进行调速。 
    d表示向上位机发送当前转速。 
    t表示停机 
    r表示开启 
    o表示方向翻转 
测速采用测速脉冲信号(霍尔速度传感器)作为T2的外部计数脉冲,T1 CTC模式,实现1s定时,比较匹配中断允许,中断服务程序读TCNT2的值,即为转速,读后重新初始化Timer2。 
对初学者来说,测速可以使用cpu风扇来作试验,cpu风扇自带一个速度输出线,内部采用的是霍尔传感器,注意,霍尔传感器输出端是oc门开路,需要接上拉电阻。可以得到很标准的方波!另:注意将风扇接地和你的开发板接地连在一起。 
原代码如下: 
  程序采用的是ICC自动生成代码,再移植到codevision中,本人觉得ICC自动生成代码结构清晰,很适合初学者,也可能有不妥的地方! 
 // Target : M16 
// Crystal: 4.0000Mhz 

#include  
#include  
#include  
unsigned char rx_data[5];//数据缓冲区 
volatile unsigned char rx_counter=0; 

volatile unsigned char crut_sped;//当前转速 
//const unsigned char seg_table[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d, 
//0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  
void port_init(void) 

 PORTA = 0x00; 
 DDRA  = 0x00; 
 PORTB = 0x00; 
 DDRB  = 0x00; 
 PORTC = 0b01000000; //m103 output only 
 DDRC  = 0xFF; 
 PORTD = 0xFF; 
 DDRD  = 0xFF; 

//外部事件计数 
void timer0_init(void) 

TCCR0 = 0x00; //stop 
TCNT0 = 0x00;  
OCR0  = 0x00 ;    
TCCR0 = 0x07; //start 
}   
//TIMER1 initialize - prescale:64 
// WGM: 4) CTC, TOP=OCRnA 
// desired value: 1Sec 
// actual value:  1.000Sec (0.0%) 
void timer1_init(void) 

 TCCR1B = 0x00; //stop 
 TCNT1H = 0x0B; //setup 
 TCNT1L = 0xDD; 
 OCR1AH = 0xF4; 
 OCR1AL = 0x23; 
 OCR1BH = 0xF4; 
 OCR1BL = 0x23; 
 ICR1H  = 0xF4; 
 ICR1L  = 0x23; 
 TCCR1A = 0b00000000; 
 TCCR1B = 0b00001011; //start Timer 
}  
//TIMER2 initialize - prescale:64 
// WGM: PWM Phase correct 
// desired value: 122Hz 
// actual value: 122.549Hz (0.4%) 
void timer2_init(void) 

 TCCR2 = 0x00; //stop 
 TCNT2 = 0x01; //set count 
 OCR2  = 0x3f;  //set compare 
 TCCR2 = 0b01100011; //start timer 


 interrupt [TIM1_COMPA] void timer1_compa_isr(void) 

 //compare occured TCNT3=OCR3A 
 crut_sped=TCNT0; 
 timer0_init();  
}   
//UART0 initialize 
// desired baud rate: 19200 
// actual: baud rate:19231 (0.2%) 
// char size: 8 bit 
// parity: Disabled 
void uart_init(void) 

 UCSRB = 0x00; //disable while setting baud rate 
 UCSRA = 0x00; 
 UCSRC = 0x06; 
 UBRRL = 0x0C; //set baud rate lo 
 UBRRH = 0x00; //set baud rate hi 
 UCSRB = 0x98; 



interrupt[USART_RXC] void uart_rx_isr(void) 

  /*if (rx_counter >= 4)  
       { 
               rx_counter = 0; 
                if ((!(rx_data[0] == 'M'))||(!(rx_data[3] == 'C'))) 
                  { 
                    rx_data[0]=0; 
             rx_data[1]=0; 
             rx_data[2]=0; 
             rx_data[3]=0; 
                  }   
       }   */ 
    rx_data[rx_counter] = UDR; 
      
     if (rx_data[rx_counter]=='M') 
       { 
                 rx_data[0]=rx_data[rx_counter]; 
                 rx_counter=0; 
       } 
     rx_counter++;  
   
        
}     

void init_devices(void) 

 //stop errant interrupts until set up 
#asm("cli"); //disable all interrupts 
 port_init(); 
 timer0_init(); 
 timer1_init(); 
 timer2_init(); 
 uart_init(); 
 MCUCR = 0x00; 
 GICR  = 0x00; 
 TIMSK = 0b00010000; //输出比较匹配A中断使能 
 #asm("sei");//re-enable interrupts 
 //all peripherals are now initialized 

void timer2_reset(unsigned char i) 

 if((i>0x00)&&(i<0xff)) 
 { 
 TCCR2 = 0x00; //stop 
 TCNT2 = 0x01; //set count 
 OCR2  = i;  //set compare 
 TCCR2 = 0b01100011; //start timer 
 } 
  
}  
 void speed_direction(void) 
 { 
  PORTC^=0x80; 
  PORTC^=0x40;   
 } 

void main(void) 
{  
 init_devices(); 
  while(1) 
  {  
    if (rx_counter==4) 
       { 
          rx_counter=0; 
          if ((rx_data[0] == 'M')&&(rx_data[3] == 'C')) 
          { 
            if(rx_data[1]=='s')//设定速度 
            { 
             timer2_reset(rx_data[2]); 
            } 
             else if(rx_data[1]=='d') 
               { 
              putchar(crut_sped); 
               }   
             else if(rx_data[1]=='t') 
               { 
              PORTC=0x00; 
               }  
             else if(rx_data[1]=='r') 
             { 
             PORTC=0x80; 
             }  
             else if(rx_data[1]=='o') 
             { 
             speed_direction(); 
             } 
            }   
           else   
             
           {   
          printf("your command is wrong 
"); 
             } 
              rx_data[0]=0; 
              rx_data[1]=0; 
              rx_data[2]=0; 
              rx_data[3]=0; 
            }   
        
  } 
关键字:直流电机  控制例子 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM硬件设计四 - EBI总线