کد:
#include <mega88pa.h>
#include <delay.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define LED_on PORTB.0=0
#define LED_off PORTB.0=1
#define MaxSpeed 25
#define MinSpeed -25
signed char vel_l,vel_r;
void initAVR(void);
void Speed2(void);
//===================================== Forward Moving for Right Motor
void RForward(unsigned char REnable)
{
PORTB.5=1;
PORTB.4=0;
OCR1AL=REnable;
}
//===================================== Backward Moving for Right Motor
void RBackward(unsigned char REnable)
{
PORTB.5=0 ;
PORTB.4=1;
OCR1AL=REnable;
}
//===================================== Forward Moving for Left Motor
void LForward(unsigned char LEnable)
{
PORTD.6=1;
PORTD.7=0;
OCR1BL=LEnable;
}
//===================================== Backward Moving for Left Motor
void LBackward(unsigned char LEnable)
{
PORTD.6=0;
PORTD.7=1;
OCR1BL=LEnable;
}
//===================================== OFF the Motors
void OFF()
{
PORTB.4=0;
PORTB.5=0;
OCR1AL=0;
PORTD.6=0;
PORTD.7=0;
OCR1BL=0;
}
//=====================================
int Char2int(char c)
{
switch(c)
{
case '1': return(1);
case '2': return(2);
case '3': return(3);
case '4': return(4);
case '5': return(5);
case '6': return(6);
case '7': return(7);
case '8': return(8);
case '9': return(9);
case '0': return(0);
}
}
//=====================================
#define ADC_VREF_TYPE 0x40
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
//=====================================
#ifndef RXB8
#define RXB8 1
#endif
#ifndef TXB8
#define TXB8 0
#endif
#ifndef UPE
#define UPE 2
#endif
#ifndef DOR
#define DOR 3
#endif
#ifndef FE
#define FE 4
#endif
#ifndef UDRE
#define UDRE 5
#endif
#ifndef RXC
#define RXC 7
#endif
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
// USART Receiver buffer
#define RX_BUFFER_SIZE0 15
char rx_buffer0[RX_BUFFER_SIZE0];
char buffer[RX_BUFFER_SIZE0];
#if RX_BUFFER_SIZE0 <= 256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif
// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow0;
// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
if (data=='$') rx_wr_index0=0;
if ((rx_wr_index0==1) && (data=='P')) rx_wr_index0=1;
if (rx_wr_index0==2 && data=='W') rx_wr_index0=2;
if (rx_wr_index0==3 && data=='M') rx_wr_index0=3;
=if (rx_wr_index0==4 && data=='=') rx_wr_index0==4; //$PWM=
rx_buffer0[rx_wr_index0++]=data;
#if RX_BUFFER_SIZE0 == 256
// special case for receiver buffer size=256
if (++rx_counter0 == 0) rx_buffer_overflow0=1;
#else
if (rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
if (++rx_counter0 == RX_BUFFER_SIZE0)
{
rx_counter0=0;
rx_buffer_overflow0=1;
}
#endif
}
}
#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0++];
#if RX_BUFFER_SIZE0 != 256
if (rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#endif
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif
void main(void)
{
initAVR();
LED_on;
delay_ms(500);
LED_off;
printf("Salam...\r");
#asm("sei");
while(1)
{
if (rx_buffer0[0]=='$' && rx_buffer0[1]=='P' && rx_buffer0[2]=='W' && rx_buffer0[3]=='M'&& rx_buffer0[4]=='=' )
{
#asm("cli");
if(rx_buffer0[rx_wr_index0-3]=='*')
{
rx_counter0=0;
rx_wr_index0=0;
rx_buffer0[3]='0'; // to reset buffer
Speed2();
}
#asm("sei");
}
}
}//End Main
//============================================================================
void Speed2()
{
char i;
i=5;
if (rx_buffer0[i]=='-')
{
i++; //6
if(rx_buffer0[i+1]==',')
{
vel_l = -(Char2int(rx_buffer0[i])) ;
}
else
{
vel_l = -((Char2int(rx_buffer0[i])*10)+ Char2int(rx_buffer0[i+1])) ; //i=7
i++;
}
}
else
{
if(rx_buffer0[i+1]==',') vel_l = Char2int(rx_buffer0[i]) ;
else
{
vel_l = ((Char2int(rx_buffer0[i])*10)+ Char2int(rx_buffer0[i+1]));
i++;
}
}
i++;
i++; // ','
if (rx_buffer0[i]=='-')
{
i++;
if(rx_buffer0[i+1]=='*') vel_r = -Char2int(rx_buffer0[i]) ;
else
{
vel_r = -((Char2int(rx_buffer0[i])*10)+ Char2int(rx_buffer0[i+1])) ;
i++;
}
}
else
{
if(rx_buffer0[i+1]=='*') vel_r = Char2int(rx_buffer0[i]) ;
else
{
vel_r = ((Char2int(rx_buffer0[i])*10)+ Char2int(rx_buffer0[i+1])) ;
i++;
}
}
if(vel_l>MaxSpeed) vel_l=MaxSpeed;
if(vel_l<MinSpeed) vel_l=MinSpeed;
if(vel_r>MaxSpeed) vel_r=MaxSpeed;
if(vel_r<MinSpeed) vel_r=MinSpeed;
if(vel_l>0) LForward((unsigned char)vel_l);
else LBackward(cabs(vel_l));
if(vel_r>0) RForward((unsigned char)vel_r);
else RBackward(cabs(vel_r));
}
//=========================
void initAVR(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=Out Func4=Out Func3=In Func2=Out Func1=Out Func0=Out
// State7=T State6=T State5=0 State4=0 State3=T State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0x37;
// Port D initialization
// Func7=Out Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=In
// State7=0 State6=0 State5=T State4=T State3=T State2=T State1=0 State0=T
PORTD=0x00;
DDRD=0xC0;
// Timer/Counter 0 initialization
// Clock source: T0 pin Falling Edge
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x06;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7.813 kHz
// Mode: Fast PWM top=0x00FF
// OC1A output: Non-Inv.
// OC1B output: Non-Inv.
// Noise Canceler: On
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xA1;
TCCR1B=0x8D;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: Ext. clk. on TOSC1 pin
// Clock value: PCK2
// Mode: Normal top=0xFF
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x60;
TCCR2A=0x00;
TCCR2B=0x01;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x33;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR1=0x00;
// ADC initialization
// ADC Clock frequency: 62.500 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
// ADC4: On, ADC5: On
DIDR0=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x87;
}
میشه اشکال زدایی بشه ؟
دستور ارسال سرعت برای موتور سمت چپ و راست از طریق سریال انجام میشه که به فرمت زیر است:
کد:
$PWM=[2,2]*
$PWM=[10,24]*
$PWM=[-12,-3]*
$PWM=[-20,3]*
یکی از حالتهای فوق دریافت میشود البته اعداد یا یک رقمی است یا دو رقمی. که باید عدد دریافتی تشخیص داده شود و به موتورها اعمال شوند که این کار توسط تابع Speed2 انجام میشه.(البته شاید خوب نوشته نشده باشه ولی جواب میده !)
مشکل:
وقتی با هیپر ترمینال به فرمت ذکر شده دستور ارسال میکنم موتورها شروع به چرخش میکنند اما به محض اینکه کاراکتری جدید ارسال میکنم موتورها متوقف میشوند(ظاهرا تایمر یک که برای تولید PWM می باشد از کار می افته!!) و تا زمان فشردن اینتر ظاهرا در روتین وقفه میماند و اگر مقدار جدیدی به فرمت ذکر شده ارسال نشود موتورها همچنان متوقف می مانند.