📄 18motor.c
字号:
// Setup() initializes program variables and peripheral registers
//---------------------------------------------------------------------
void Setup(void)
{
firstseg = 0; // Initialize motion segment
lastseg = 0; // variables
segnum = 0;
parameter = 0; // Motion segment parameter#
i = 0; // Receive buffer index
comcount = 0; // Input command index
udata = 0; // Holds USART received data
stat.phase = 0; // Set flags to 0.
stat.saturated = 0;
stat.motion = 0;
stat.run = 0;
stat.loop = 0;
stat.neg_move = 0;
dtime = 0;
integral.l = 0;
vlim = 0;
mvelocity = 0;
DnCount = 0;
UpCount = 0;
temp.l = 0;
accel.l = 0;
error.l = 0;
ypid.l = 0;
velact.l = 0;
phase1dist.l = 0;
position = 0;
mposition = 0;
fposition = 0;
flatcount = 0;
udata = 0;
memset(inpbuf,0,8); // clear the input buffer
// Setup A/D converter
OpenADC(ADC_FOSC_32 & ADC_LEFT_JUST & ADC_1ANA_0REF,
ADC_CH0 & ADC_INT_OFF);
OpenPWM1(0xff); // Setup Timer2, CCP1 to provide
// 19.53 Khz PWM @ 20MHz
OpenTimer2(T2_PS_1_1 & T2_POST_1_10 & TIMER_INT_ON);
SetDCPWM1(512); // 50% initial duty cycle
EnablePullups(); // Enable PORTB pullups
PORTC = 0; // Clear PORTC
PORTD = 0; // Clear PORTD
PORTE = 0x00; // Clear PORTD
TRISC = 0xdb; //
TRISD = 0; // PORTD all outputs.
TRISE = 0; // PORTE all outputs.
// Setup the USART for 19200 baud @ 20MHz
SPBRG = 15; // 19200 baud @ 20MHz
TXSTA = 0x20; // setup USART transmit
RCSTA = 0x90; // setup USART receive
putrsUSART("\r\nPIC18C452 DC Servomotor");
putrsUSART(ready);
OpenI2C(MASTER,SLEW_OFF); // Setup MSSP for master I2C
SSPADD = 49; // 100KHz @ 20MHz
kp = ExtEERead(122); // Get PID gain constants
ki = 0; // from data EEPROM
kd = ExtEERead(126);
TMR0L = 0; // Clear timers.
TMR0H = 0;
TMR1L = 0;
TMR1H = 0;
OpenTimer0(TIMER_INT_OFF & T0_16BIT & TIMER_INT_OFF & T0_EDGE_RISE &
T0_SOURCE_EXT & T0_PS_1_1);
OpenTimer1(TIMER_INT_OFF & T1_SOURCE_EXT & T1_16BIT_RW & TIMER_INT_OFF
& T1_PS_1_1 & T1_SYNC_EXT_ON & T1_OSC1EN_OFF );
// Load motion profile data for segments 1 through 12 from
// data EEPROM
for(segnum=0;segnum < 12;segnum++)
{
for(parameter=0;parameter < 4;parameter++)
{
eeadr = (segnum << 3) + (parameter << 1);
segment1[segnum][parameter] = ExtEERead(eeadr);
}
}
segment2[0][DIST] = 29500; // Motion profile data for segments
segment2[0][VEL] = 4096; // 13 through 24 are loaded into RAM
segment2[0][ACCEL] = 2048; // from program memory
segment2[0][TIME] = 1200;
segment2[1][DIST] = -29500;
segment2[1][VEL] = 1024;
segment2[1][ACCEL] = 512;
segment2[1][TIME] = 1200;
segment2[2][DIST] = 737;
segment2[2][VEL] = 4096;
segment2[2][ACCEL] = 2048;
segment2[2][TIME] = 1200;
segment2[3][DIST] = 737;
segment2[3][VEL] = 4096;
segment2[3][ACCEL] = 2048;
segment2[3][TIME] = 1200;
segment2[4][DIST] = 738;
segment2[4][VEL] = 4096;
segment2[4][ACCEL] = 2048;
segment2[4][TIME] = 1200;
segment2[5][DIST] = 738;
segment2[5][VEL] = 4096;
segment2[5][ACCEL] = 2048;
segment2[5][TIME] = 1200;
segment2[6][DIST] = -2950;
segment2[6][VEL] = 1024;
segment2[6][ACCEL] = 128;
segment2[6][TIME] = 1200;
segment2[7][DIST] = 2950;
segment2[7][VEL] = 256;
segment2[7][ACCEL] = 64;
segment2[7][TIME] = 1200;
segment2[8][DIST] = -2950;
segment2[8][VEL] = 4096;
segment2[8][ACCEL] = 512;
segment2[8][TIME] = 1200;
segment2[9][DIST] = 29500;
segment2[9][VEL] = 1024;
segment2[9][ACCEL] = 512;
segment2[9][TIME] = 1200;
segment2[10][DIST] = 29500;
segment2[10][VEL] = 2048;
segment2[10][ACCEL] = 512;
segment2[10][TIME] = 1200;
segment2[11][DIST] = 29500;
segment2[11][VEL] = 4096;
segment2[11][ACCEL] = 1024;
segment2[11][TIME] = 1200;
if(MODE1) // Check DIP switches at powerup
stat.loop = 1; // If SW1 is on, set for loop mode
if(MODE2) // If SW2 is on, execute
{ // segments 12 and 13
firstseg = 12;
lastseg = 13;
segnum = 12;
stat.run = 1;
}
else if(MODE3) // If SW3 is on, execute
{ // segments 14 through 18
firstseg = 14;
lastseg = 18;
segnum = 14;
stat.run = 1;
}
else if(MODE4) // If SW4 is on, execute
{ // segments 18 and 19
firstseg = 18;
lastseg = 19;
segnum = 18;
stat.run = 1;
}
INTCONbits.PEIE = 1; // Enable peripheral interrupts
INTCONbits.GIE = 1; // Enable all interrupts
}
//---------------------------------------------------------------------
// main()
//---------------------------------------------------------------------
void main(void)
{
Setup(); // Setup peripherals and software
// variables.
while(1) // Loop forever
{
ClrWdt(); // Clear the WDT
ConvertADC(); // Start an A/D conversion
while(BusyADC()); // Wait for the conversion to complete
PORTD = 0; // Clear the LED bargraph display.
PORTE &= 0x04; // "
if(ADRES > 225)
{
PORTE |= 0x03; // Turn on 10 LEDS
PORTD = 0xff;
}
if(ADRES > 200)
{
PORTE |= 0x01; // Turn on 9 LEDS
PORTD = 0xff;
}
else if(ADRES > 175) PORTD = 0xff; // Turn on 8 LEDS
else if(ADRES > 150) PORTD = 0x7f; // 7 LEDS
else if(ADRES > 125) PORTD = 0x3f; // 6 LEDS
else if(ADRES > 100) PORTD = 0x1f; // 5 LEDS
else if(ADRES > 75) PORTD = 0x0f; // 4 LEDS
else if(ADRES > 50) PORTD = 0x07; // 3 LEDS
else if(ADRES > 25) PORTD = 0x03; // 2 LEDS
else if(ADRES > 0) PORTD = 0x01; // 1 LED
if(PIR1bits.RCIF) // Check for USART interrupt
{
switch(udata = RCREG)
{
case ',': DoCommand(); // process the string
memset(inpbuf,0,8); // clear the input buffer
i = 0; // clear the buffer index
comcount++; // increment comma count
TXREG = udata; // echo the character
break;
case 0x0d: DoCommand(); // process the string
memset(inpbuf,0,8); // clear the input buffer
i = 0; // clear the buffer index
comcount = 0; // clear comma count
segnum = 0; // clear segment number
parameter = 0; // clear paramater
putrsUSART(ready); // put prompt to USART
break;
default: inpbuf[i] = udata; // get received char
i++; // increment buffer index
if(i > 7) // If more than 8 chars
{ // received before getting
putrsUSART(ready); // a <CR>, clear input
memset(inpbuf,0,8); // buffer
i = 0; // the buffer index
}
else TXREG = udata; // echo character
break; //
} //end switch(udata)
} //end if(RCIF)
} //end while(1)
}
//-------------------------------------------------------------------
// DoCommand()
// Processes incoming USART data.
//-------------------------------------------------------------------
void DoCommand(void)
{
if(comcount == 0) // If this is the first parameter of the input
{ // command...
switch(inpbuf[0])
{
case 'X': parameter = DIST; // Segment distance change
break;
case 'V': parameter = VEL; // Segment velocity change
break;
case 'A': parameter = ACCEL; // Segment acceleration change
break;
case 'T': parameter = TIME; // Segment delay time change
break;
case 'P': parameter = 'P'; // Change proportional gain
break;
case 'I': parameter = 'I'; // Change integral gain
break;
case 'D': parameter = 'D'; // Change differential gain
break;
case 'L': parameter = 'L'; // Loop a range of segments
break;
case 'S': stat.run = 0; // Stop execution of segments
break;
case 'G': parameter = 'G'; // Execute a range of segments
break;
case 'W': if(PORTEbits.RE2) // Enable or disable motor
{ // driver IC
putrsUSART("\r\nPWM On");
PORTEbits.RE2 = 0;
}
else
{
putrsUSART("\r\nPWM Off");
PORTEbits.RE2 = 1;
}
break;
default: if(inpbuf[0] != '\0')
{
putrsUSART(badcmd);
}
break;
}
}
else if(comcount == 1) // If this is the second parameter of the
{ // input command.
if(parameter < 4) segnum = atob(inpbuf);
else
switch(parameter)
{
case 'P': kp = atoi(inpbuf); // proportional gain change
ExtEEWrite(122, kp); // Store value in EEPROM
break;
case 'I': ki = atoi(inpbuf); // integral gain change
ExtEEWrite(124, ki); // Store value in EEPROM
break;
case 'D': kd = atoi(inpbuf); // differential gain change
ExtEEWrite(126, kd); // Store value in EEPROM
break;
case 'G': firstseg = atob(inpbuf);
break;
// Get the first segment in
// the range to be executed.
case 'L': firstseg = atob(inpbuf);
break;
default: break;
}
}
else if(comcount == 2)
{
if(!stat.run) // If no profile is executing
{
if(parameter < 4) // If this was a segment parameter
{ // change.
if(segnum < 12)
{
// Write the segment paramater into data memory
segment1[segnum][parameter] = atoi(inpbuf);
// Compute EEPROM address and write data to EEPROM
eeadr = (segnum << 3) + (parameter << 1);
ExtEEWrite(eeadr, segment1[segnum][parameter]);
}
else if(segnum < 24)
// Write segment parameter data into data memory
segment2[segnum - 12][parameter] = atoi(inpbuf);
}
else switch(parameter)
{
case 'G': lastseg = atob(inpbuf); // Get value for
segnum = firstseg; // last segment.
stat.loop = 0;
stat.run = 1; // Start profile.
break;
case 'L': lastseg = atob(inpbuf); // Get value for
segnum = firstseg; // last segment.
stat.loop = 1; // Enable looping
stat.run = 1; // Start profile
break;
default: break;
}
}
}
}
//---------------------------------------------------------------------
// ExtEEWrite()
// Writes an integer value to an EEPROM connected to the I2C bus at
// the specified location.
//---------------------------------------------------------------------
void ExtEEWrite(unsigned char address, int data)
{
union
{
char b[2];
int i;
}
temp;
char error, retry;
temp.i = data;
error = 0;
retry = 10; // Poll the EEPROM up to 10 times
do
{
error = EEAckPolling(0xA0);
retry--;
} while(error && retry > 0);
retry = 10; // Attempt to write low byte of data
do // up to 10 times
{
error = EEByteWrite(0xA0, address, temp.b[0]);
retry--;
} while(error && retry > 0);
retry = 10; // Poll the EEPROM up to 10 times
do
{
error = EEAckPolling(0xA0);
retry--;
} while(error && retry > 0);
retry = 10; // Attempt to write high byte of data
do // up to 10 times
{
error = EEByteWrite(0xA0, address + 1, temp.b[1]);
retry--;
} while(error && retry > 0);
}
//---------------------------------------------------------------------
// ExtEEWrite()
// Reads an integer value from an EEPROM connected to the I2C bus at
// the specified location.
//---------------------------------------------------------------------
int ExtEERead(unsigned char address)
{
union
{
char b[2];
int i;
}
data;
union
{
char b[2];
int i;
}
temp;
char retry;
retry = 10; // Attempt to read low byte of data
do // up to 10 times
{
temp.i = EERandomRead(0xA0, address);
retry--;
} while(temp.b[1] && retry > 0);
if(temp.b[1]) data.b[0] = 0; // Make read result 0 if error
else data.b[0] = temp.b[0]; // Otherwise get the low byte of data
retry = 10; // Attempt to read high byte of data
do // up to 10 times
{
temp.i = EERandomRead(0xA0, address + 1);
retry--;
} while(temp.b[1] && retry > 0);
if(temp.b[1]) data.b[1] = 0; // Make read result 0 if error
else data.b[1] = temp.b[0]; // Otherwise get the high byte of data
return data.i;
}
//---------------------------------------------------------------------
// putrsUSART()
// Writes a string of characters in program memory to the USART
//---------------------------------------------------------------------
void putrsUSART(const rom char *data)
{
do
{
while(!(TXSTA & 0x02));
TXREG = *data;
} while( *data++ );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -