?? avrdcmotorcontrolsystem.txt
字號:
初學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;
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -