新闻  |   论坛  |   博客  |   在线研讨会
转贴:*帖一个偶写的小型直流电机控制例子*
hnxtqzh | 2008-07-06 16:33:03    阅读:1545   发布文章

初学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 <mega16.h>
#include <delay.h>
#include <stdio.h>
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;
            }  
       
  }
}

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客