📄 motor.c
字号:
// Demo program for stepper motor control with linear ramps// Hardware: PIC18F252, L6219#include "18F252.h"// PIC18F252 SFRs#byte TRISC = 0xf94#byte T3CON = 0xfb1#byte CCP2CON = 0xfba#byte CCPR2L = 0xfbb#byte CCPR2H = 0xfbc#byte CCP1CON = 0xfbd#byte CCPR1L = 0xfbe#byte CCPR1H = 0xfbf#byte T1CON = 0xfcd#byte TMR1L = 0xfce#byte TMR1H = 0xfcf#bit TMR1ON = T1CON.0// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)#define C0 50000#define C_MIN 2500// ramp state-machine states#define ramp_idle 0#define ramp_up 1#define ramp_max 2#define ramp_down 3#define ramp_last 4// Types: int8,int16,int32=8,16,32bit integers, unsigned by defaultint8 ramp_sts=ramp_idle;signed int16 motor_pos = 0; // absolute step numbersigned int16 pos_inc=0; // motor_pos incrementint16 phase=0; // ccpPhase[phase_ix] int8 phase_ix=0; // index to ccpPhase[] int8 phase_inc; // phase_ix incrementint8 run_flg; // true while motor is runningint16 ccpr; // copy of CCPR1&2int16 c; // integer delay countint16 step_no; // progress of moveint16 step_down; // start of down-rampint16 move; // total steps to moveint16 midpt; // midpoint of moveint32 c32; // 24.8 fixed point delay countsigned int16 denom; // 4.n+1 in ramp algo// Config data to make CCP1&2 generate quadrature sequence on PHASE pins// Action on CCP match: 8=set+irq; 9=clear+irqint16 const ccpPhase[] = {0x909, 0x908, 0x808, 0x809}; // 00,01,11,10void current_on(){/* code as needed */} // motor drive currentvoid current_off(){/* code as needed */} // reduce to holding value// compiler-specific ISR declaration#INT_CCP1void isr_motor_step() { // CCP1 match -> step pulse + IRQ ccpr += c; // next comparator value: add step delay count switch (ramp_sts) { case ramp_up: // accel if (step_no==midpt) { // midpoint: decel ramp_sts = ramp_down; denom = ((step_no - move)<<2)+1; if (!(move & 1)) { // even move: repeat last delay before decel denom +=4; break; } } // no break: share code for ramp algo case ramp_down: // decel if (step_no == move-1) { // next irq is cleanup (no step) ramp_sts = ramp_last; break; } denom+=4; c32 -= (c32<<1)/denom; // ramp algorithm // beware confict with foreground code if long div not reentrant c = (c32+128)>>8; // round 24.8format->int16 if (c <= C_MIN) { // go to constant speed ramp_sts = ramp_max; step_down = move - step_no; c = C_MIN; break; } break; case ramp_max: // constant speed if (step_no == step_down) { // start decel ramp_sts = ramp_down; denom = ((step_no - move)<<2)+5; } break; default: // last step: cleanup ramp_sts = ramp_idle; current_off(); // reduce motor current to holding value disable_interrupts(INT_CCP1); run_flg = FALSE; // move complete break; } // switch (ramp_sts) if (ramp_sts!=ramp_idle) { motor_pos += pos_inc; ++step_no; CCPR2H = CCPR1H = (ccpr >> 8); // timer value at next CCP match CCPR2L = CCPR1L = (ccpr & 0xff); if (ramp_sts!=ramp_last) // else repeat last action: no step phase_ix = (phase_ix + phase_inc) & 3; phase = ccpPhase[phase_ix]; CCP1CON = phase & 0xff; // set CCP action on next match CCP2CON = phase >> 8; } // if (ramp_sts != ramp_idle)} // isr_motor_step()void motor_run(short pos_new){ // set up to drive motor to pos_new (absolute step#) if (pos_new < motor_pos) // get direction & #steps { move = motor_pos-pos_new; pos_inc = -1; phase_inc = 0xff; } else if (pos_new != motor_pos) { move = pos_new-motor_pos; pos_inc = 1; phase_inc = 1; } else return; // already there midpt = (move-1)>>1; c = C0; c32 = c<<8; // keep c in 24.8 fixed-point format for ramp calcs step_no = 0; // step counter denom = 1; // 4.n+1, n=0 ramp_sts = ramp_up; // start ramp state-machine run_flg = TRUE; TMR1ON = 0; // stop timer1; ccpr = make16(TMR1H,TMR1L); // 16bit value of Timer1 ccpr += 1000; // 1st step + irq 1ms after timer1 restart CCPR2H = CCPR1H = (ccpr >> 8); CCPR2L = CCPR1L = (ccpr & 0xff); phase_ix = (phase_ix + phase_inc) & 3; phase = ccpPhase[phase_ix]; CCP1CON = phase & 0xff; // sets action on match CCP2CON = phase >> 8; current_on(); // current in motor windings enable_interrupts(INT_CCP1); TMR1ON=1; // restart timer1;} // motor_run()void initialize(){ disable_interrupts(GLOBAL); disable_interrupts(INT_CCP1); disable_interrupts(INT_CCP2); output_c(0); set_tris_c(0); T3CON = 0; T1CON = 0x35; enable_interrupts(GLOBAL);} // initialize()void main(){ initialize(); while (1) { // repeat 5 revs forward & back motor_run(1000); while (run_flg); motor_run(0); while (run_flg); }} // main()// end of file motor.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -