Port stepper
This commit is contained in:
parent
fdf6e31218
commit
d4cbac2a5c
@ -415,14 +415,18 @@
|
|||||||
// NOTE: Uncomment to enable. The recommended delay must be > 3us, and, when added with the
|
// NOTE: Uncomment to enable. The recommended delay must be > 3us, and, when added with the
|
||||||
// user-supplied step pulse time, the total time must not exceed 127us. Reported successful
|
// user-supplied step pulse time, the total time must not exceed 127us. Reported successful
|
||||||
// values for certain setups have ranged from 5 to 20us.
|
// values for certain setups have ranged from 5 to 20us.
|
||||||
// #define STEP_PULSE_DELAY 10 // Step pulse delay in microseconds. Default disabled.
|
// not ported; don't use. #define STEP_PULSE_DELAY 10 // Step pulse delay in microseconds. Default disabled.
|
||||||
|
|
||||||
|
// Creates a delay between setting the direction pin and pulsing the step pin. This delay
|
||||||
|
// lives inside the main Grbl interrupt.
|
||||||
|
#define STEP_PULSE_DELAY_NS 200 // Step pulse delay in nanoseconds.
|
||||||
|
|
||||||
// The number of linear motions in the planner buffer to be planned at any give time. The vast
|
// The number of linear motions in the planner buffer to be planned at any give time. The vast
|
||||||
// majority of RAM that Grbl uses is based on this buffer size. Only increase if there is extra
|
// majority of RAM that Grbl uses is based on this buffer size. Only increase if there is extra
|
||||||
// available RAM, like when re-compiling for a Mega2560. Or decrease if the Arduino begins to
|
// available RAM, like when re-compiling for a Mega2560. Or decrease if the Arduino begins to
|
||||||
// crash due to the lack of available RAM or if the CPU is having trouble keeping up with planning
|
// crash due to the lack of available RAM or if the CPU is having trouble keeping up with planning
|
||||||
// new incoming motions as they are executed.
|
// new incoming motions as they are executed.
|
||||||
// #define BLOCK_BUFFER_SIZE 16 // Uncomment to override default in planner.h.
|
#define BLOCK_BUFFER_SIZE 32 // Uncomment to override default in planner.h.
|
||||||
|
|
||||||
// Governs the size of the intermediary step segment buffer between the step execution algorithm
|
// Governs the size of the intermediary step segment buffer between the step execution algorithm
|
||||||
// and the planner blocks. Each segment is set of steps executed at a constant velocity over a
|
// and the planner blocks. Each segment is set of steps executed at a constant velocity over a
|
||||||
@ -617,9 +621,9 @@
|
|||||||
#define Y_LIMIT_BIT 27 // Y-MIN=26, Y-MAX=27
|
#define Y_LIMIT_BIT 27 // Y-MIN=26, Y-MAX=27
|
||||||
#define Z_LIMIT_BIT 29 // Z-MIN=28, Z-MAX=29
|
#define Z_LIMIT_BIT 29 // Z-MIN=28, Z-MAX=29
|
||||||
#define LIMIT_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)) // All limit bits
|
#define LIMIT_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)) // All limit bits
|
||||||
// hard/soft limit not ported #define LIMIT_INT PCIE0 // Pin change interrupt enable pin
|
// hard limits not ported #define LIMIT_INT PCIE0 // Pin change interrupt enable pin
|
||||||
// hard/soft limit not ported #define LIMIT_INT_vect PCINT0_vect
|
// hard limits not ported #define LIMIT_INT_vect PCINT0_vect
|
||||||
// hard/soft limit not ported #define LIMIT_PCMSK PCMSK0 // Pin change interrupt register
|
// hard limits not ported #define LIMIT_PCMSK PCMSK0 // Pin change interrupt register
|
||||||
|
|
||||||
// Define spindle enable and spindle direction output pins.
|
// Define spindle enable and spindle direction output pins.
|
||||||
#define SPINDLE_ENABLE_DDR DDRB
|
#define SPINDLE_ENABLE_DDR DDRB
|
||||||
|
@ -73,7 +73,7 @@ static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE-1];
|
|||||||
// the planner, where the remaining planner block steps still can.
|
// the planner, where the remaining planner block steps still can.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t n_step; // Number of step events to be executed for this segment
|
uint16_t n_step; // Number of step events to be executed for this segment
|
||||||
uint16_t cycles_per_tick; // Step distance traveled per ISR tick, aka step rate.
|
uint32_t cycles_per_tick; // Step distance traveled per ISR tick, aka step rate.
|
||||||
uint8_t st_block_index; // Stepper block data index. Uses this information to execute this segment.
|
uint8_t st_block_index; // Stepper block data index. Uses this information to execute this segment.
|
||||||
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
|
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
|
||||||
uint8_t amass_level; // Indicates AMASS level for the ISR to execute this segment
|
uint8_t amass_level; // Indicates AMASS level for the ISR to execute this segment
|
||||||
@ -97,7 +97,8 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t execute_step; // Flags step execution for each interrupt.
|
uint8_t execute_step; // Flags step execution for each interrupt.
|
||||||
uint8_t step_pulse_time; // Step pulse reset time after step rise
|
uint32_t step_setup_time; // Delay between dir change and step pulse
|
||||||
|
uint32_t step_pulse_time; // Step pulse width
|
||||||
uint32_t step_outbits; // The next stepping-bits to be output
|
uint32_t step_outbits; // The next stepping-bits to be output
|
||||||
uint32_t dir_outbits;
|
uint32_t dir_outbits;
|
||||||
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
|
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
|
||||||
@ -220,12 +221,14 @@ void st_wake_up()
|
|||||||
// Set delay between direction pin write and step command.
|
// Set delay between direction pin write and step command.
|
||||||
OCR0A = -(((settings.pulse_microseconds)*TICKS_PER_MICROSECOND) >> 3);
|
OCR0A = -(((settings.pulse_microseconds)*TICKS_PER_MICROSECOND) >> 3);
|
||||||
#else // Normal operation
|
#else // Normal operation
|
||||||
// Set step pulse time. Ad hoc computation from oscilloscope. Uses two's complement.
|
st.step_setup_time = uint32_t(uint64_t(SystemCoreClock)*STEP_PULSE_DELAY_NS/1000'000'000);
|
||||||
st.step_pulse_time = -(((settings.pulse_microseconds-2)*TICKS_PER_MICROSECOND) >> 3);
|
st.step_pulse_time = settings.pulse_microseconds*TICKS_PER_MICROSECOND;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable Stepper Driver Interrupt
|
// Enable Stepper Driver Interrupt Timer
|
||||||
TIMSK1 |= (1<<OCIE1A);
|
LPC_TIM1->TCR = 0b10; // reset
|
||||||
|
LPC_TIM1->MR0 = 4000; // Generate first interrupt soon
|
||||||
|
LPC_TIM1->TCR = 0b01; // enable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -233,8 +236,7 @@ void st_wake_up()
|
|||||||
void st_go_idle()
|
void st_go_idle()
|
||||||
{
|
{
|
||||||
// Disable Stepper Driver Interrupt. Allow Stepper Port Reset Interrupt to finish, if active.
|
// Disable Stepper Driver Interrupt. Allow Stepper Port Reset Interrupt to finish, if active.
|
||||||
TIMSK1 &= ~(1<<OCIE1A); // Disable Timer1 interrupt
|
LPC_TIM1->TCR = 0; // Disable Timer1
|
||||||
TCCR1B = (TCCR1B & ~((1<<CS12) | (1<<CS11))) | (1<<CS10); // Reset clock to no prescaling.
|
|
||||||
busy = false;
|
busy = false;
|
||||||
|
|
||||||
// Set stepper driver idle state, disabled or enabled, depending on settings and circumstances.
|
// Set stepper driver idle state, disabled or enabled, depending on settings and circumstances.
|
||||||
@ -299,8 +301,9 @@ void st_go_idle()
|
|||||||
// TODO: Replace direct updating of the int32 position counters in the ISR somehow. Perhaps use smaller
|
// TODO: Replace direct updating of the int32 position counters in the ISR somehow. Perhaps use smaller
|
||||||
// int8 variables and update position counters only when a segment completes. This can get complicated
|
// int8 variables and update position counters only when a segment completes. This can get complicated
|
||||||
// with probing and homing cycles that require true real-time positions.
|
// with probing and homing cycles that require true real-time positions.
|
||||||
ISR(TIMER1_COMPA_vect)
|
extern "C" void TIMER1_IRQHandler()
|
||||||
{
|
{
|
||||||
|
LPC_TIM1->IR = LPC_TIM1->IR; // Clear interrupt
|
||||||
if (busy) { return; } // The busy-flag is used to avoid reentering this interrupt
|
if (busy) { return; } // The busy-flag is used to avoid reentering this interrupt
|
||||||
|
|
||||||
// Set the direction pins a couple of nanoseconds before we step the steppers
|
// Set the direction pins a couple of nanoseconds before we step the steppers
|
||||||
@ -308,19 +311,26 @@ ISR(TIMER1_COMPA_vect)
|
|||||||
|
|
||||||
// Then pulse the stepping pins
|
// Then pulse the stepping pins
|
||||||
#ifdef STEP_PULSE_DELAY
|
#ifdef STEP_PULSE_DELAY
|
||||||
|
#error not implemented
|
||||||
st.step_bits = (STEP_PORT & ~STEP_MASK) | st.step_outbits; // Store out_bits to prevent overwriting.
|
st.step_bits = (STEP_PORT & ~STEP_MASK) | st.step_outbits; // Store out_bits to prevent overwriting.
|
||||||
#else // Normal operation
|
#else // Normal operation
|
||||||
|
delay_loop(get_time(), st.step_setup_time);
|
||||||
STEP_PORT = (STEP_PORT & ~STEP_MASK) | st.step_outbits;
|
STEP_PORT = (STEP_PORT & ~STEP_MASK) | st.step_outbits;
|
||||||
|
// Mark time step bits were set
|
||||||
|
uint32_t step_start_time = get_time();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable step pulse reset timer so that The Stepper Port Reset Interrupt can reset the signal after
|
// Enable step pulse reset timer so that The Stepper Port Reset Interrupt can reset the signal after
|
||||||
// exactly settings.pulse_microseconds microseconds, independent of the main Timer1 prescaler.
|
// exactly settings.pulse_microseconds microseconds, independent of the main Timer1 prescaler.
|
||||||
TCNT0 = st.step_pulse_time; // Reload Timer0 counter
|
// Disabled. This ISR now resets the step pins at the end.
|
||||||
TCCR0B = (1<<CS01); // Begin Timer0. Full speed, 1/8 prescaler
|
// TCNT0 = st.step_pulse_time; // Reload Timer0 counter
|
||||||
|
// TCCR0B = (1<<CS01); // Begin Timer0. Full speed, 1/8 prescaler
|
||||||
|
|
||||||
busy = true;
|
busy = true;
|
||||||
sei(); // Re-enable interrupts to allow Stepper Port Reset Interrupt to fire on-time.
|
|
||||||
// NOTE: The remaining code in this ISR will finish before returning to main program.
|
// Can no longer re-enable interrupts since this ISR resets the step pins at the end.
|
||||||
|
// sei(); // Re-enable interrupts to allow Stepper Port Reset Interrupt to fire on-time.
|
||||||
|
// // NOTE: The remaining code in this ISR will finish before returning to main program.
|
||||||
|
|
||||||
// If there is no step segment, attempt to pop one from the stepper buffer
|
// If there is no step segment, attempt to pop one from the stepper buffer
|
||||||
if (st.exec_segment == NULL) {
|
if (st.exec_segment == NULL) {
|
||||||
@ -330,12 +340,13 @@ ISR(TIMER1_COMPA_vect)
|
|||||||
st.exec_segment = &segment_buffer[segment_buffer_tail];
|
st.exec_segment = &segment_buffer[segment_buffer_tail];
|
||||||
|
|
||||||
#ifndef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
|
#ifndef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
|
||||||
|
#error not ported; AMASS is required
|
||||||
// With AMASS is disabled, set timer prescaler for segments with slow step frequencies (< 250Hz).
|
// With AMASS is disabled, set timer prescaler for segments with slow step frequencies (< 250Hz).
|
||||||
TCCR1B = (TCCR1B & ~(0x07<<CS10)) | (st.exec_segment->prescaler<<CS10);
|
TCCR1B = (TCCR1B & ~(0x07<<CS10)) | (st.exec_segment->prescaler<<CS10);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Initialize step segment timing per step and load number of steps to execute.
|
// Initialize step segment timing per step and load number of steps to execute.
|
||||||
OCR1A = st.exec_segment->cycles_per_tick;
|
LPC_TIM1->MR0 = st.exec_segment->cycles_per_tick;
|
||||||
st.step_count = st.exec_segment->n_step; // NOTE: Can sometimes be zero when moving slow.
|
st.step_count = st.exec_segment->n_step; // NOTE: Can sometimes be zero when moving slow.
|
||||||
// If the new segment starts a new planner block, initialize stepper variables and counters.
|
// If the new segment starts a new planner block, initialize stepper variables and counters.
|
||||||
// NOTE: When the segment data index changes, this indicates a new planner block.
|
// NOTE: When the segment data index changes, this indicates a new planner block.
|
||||||
@ -368,6 +379,9 @@ ISR(TIMER1_COMPA_vect)
|
|||||||
if (st.exec_block->is_pwm_rate_adjusted) { spindle_set_speed(SPINDLE_PWM_OFF_VALUE); }
|
if (st.exec_block->is_pwm_rate_adjusted) { spindle_set_speed(SPINDLE_PWM_OFF_VALUE); }
|
||||||
#endif
|
#endif
|
||||||
system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end
|
system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end
|
||||||
|
// Reset stepping pins after delay
|
||||||
|
delay_loop(step_start_time, st.step_pulse_time);
|
||||||
|
STEP_PORT = (STEP_PORT & ~STEP_MASK) | (step_port_invert_mask & STEP_MASK);
|
||||||
return; // Nothing to do but exit.
|
return; // Nothing to do but exit.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,6 +439,11 @@ ISR(TIMER1_COMPA_vect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
st.step_outbits ^= step_port_invert_mask; // Apply step port invert mask
|
st.step_outbits ^= step_port_invert_mask; // Apply step port invert mask
|
||||||
|
|
||||||
|
// Reset stepping pins after delay
|
||||||
|
delay_loop(step_start_time, st.step_pulse_time);
|
||||||
|
STEP_PORT = (STEP_PORT & ~STEP_MASK) | (step_port_invert_mask & STEP_MASK);
|
||||||
|
|
||||||
busy = false;
|
busy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,6 +456,8 @@ ISR(TIMER1_COMPA_vect)
|
|||||||
cause issues at high step rates if another high frequency asynchronous interrupt is
|
cause issues at high step rates if another high frequency asynchronous interrupt is
|
||||||
added to Grbl.
|
added to Grbl.
|
||||||
*/
|
*/
|
||||||
|
/* Not ported; the main ISR assumes short pulse widths and handles it. Stepper drivers with
|
||||||
|
long pulse widths may need this instead if they cause the main ISR to consume too much time.
|
||||||
// This interrupt is enabled by ISR_TIMER1_COMPAREA when it sets the motor port bits to execute
|
// This interrupt is enabled by ISR_TIMER1_COMPAREA when it sets the motor port bits to execute
|
||||||
// a step. This ISR resets the motor port after a short period (settings.pulse_microseconds)
|
// a step. This ISR resets the motor port after a short period (settings.pulse_microseconds)
|
||||||
// completing one step cycle.
|
// completing one step cycle.
|
||||||
@ -457,6 +478,7 @@ ISR(TIMER0_OVF_vect)
|
|||||||
STEP_PORT = st.step_bits; // Begin step pulse.
|
STEP_PORT = st.step_bits; // Begin step pulse.
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Generates the step and direction port invert masks used in the Stepper Interrupt Driver.
|
// Generates the step and direction port invert masks used in the Stepper Interrupt Driver.
|
||||||
@ -506,21 +528,13 @@ void stepper_init()
|
|||||||
DIRECTION_DDR |= DIRECTION_MASK;
|
DIRECTION_DDR |= DIRECTION_MASK;
|
||||||
|
|
||||||
// Configure Timer 1: Stepper Driver Interrupt
|
// Configure Timer 1: Stepper Driver Interrupt
|
||||||
TCCR1B &= ~(1<<WGM13); // waveform generation = 0100 = CTC
|
LPC_TIM1->TCR = 0; // disable
|
||||||
TCCR1B |= (1<<WGM12);
|
LPC_TIM1->CTCR = 0; // timer mode
|
||||||
TCCR1A &= ~((1<<WGM11) | (1<<WGM10));
|
LPC_TIM1->PR = 0; // no prescale
|
||||||
TCCR1A &= ~((1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0)); // Disconnect OC1 output
|
LPC_TIM1->MCR = 0b011; // MR0: !stop, reset, interrupt
|
||||||
// TCCR1B = (TCCR1B & ~((1<<CS12) | (1<<CS11))) | (1<<CS10); // Set in st_go_idle().
|
LPC_TIM1->CCR = 0; // no capture
|
||||||
// TIMSK1 &= ~(1<<OCIE1A); // Set in st_go_idle().
|
LPC_TIM1->EMR = 0; // no external match
|
||||||
|
NVIC_EnableIRQ(TIMER1_IRQn); // Enable Stepper Driver Interrupt
|
||||||
// Configure Timer 0: Stepper Port Reset Interrupt
|
|
||||||
TIMSK0 &= ~((1<<OCIE0B) | (1<<OCIE0A) | (1<<TOIE0)); // Disconnect OC0 outputs and OVF interrupt.
|
|
||||||
TCCR0A = 0; // Normal operation
|
|
||||||
TCCR0B = 0; // Disable Timer0 until needed
|
|
||||||
TIMSK0 |= (1<<TOIE0); // Enable Timer0 overflow interrupt
|
|
||||||
#ifdef STEP_PULSE_DELAY
|
|
||||||
TIMSK0 |= (1<<OCIE0A); // Enable Timer0 Compare Match A interrupt
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -948,9 +962,9 @@ void st_prep_buffer()
|
|||||||
cycles >>= prep_segment->amass_level;
|
cycles >>= prep_segment->amass_level;
|
||||||
prep_segment->n_step <<= prep_segment->amass_level;
|
prep_segment->n_step <<= prep_segment->amass_level;
|
||||||
}
|
}
|
||||||
if (cycles < (1UL << 16)) { prep_segment->cycles_per_tick = cycles; } // < 65536 (4.1ms @ 16MHz)
|
prep_segment->cycles_per_tick = cycles;
|
||||||
else { prep_segment->cycles_per_tick = 0xffff; } // Just set the slowest speed possible.
|
|
||||||
#else
|
#else
|
||||||
|
#error not ported; AMASS is required
|
||||||
// Compute step timing and timer prescalar for normal step generation.
|
// Compute step timing and timer prescalar for normal step generation.
|
||||||
if (cycles < (1UL << 16)) { // < 65536 (4.1ms @ 16MHz)
|
if (cycles < (1UL << 16)) { // < 65536 (4.1ms @ 16MHz)
|
||||||
prep_segment->prescaler = 1; // prescaler: 0
|
prep_segment->prescaler = 1; // prescaler: 0
|
||||||
|
@ -28,28 +28,14 @@ extern DummyReg EECR;
|
|||||||
extern DummyReg EEDR;
|
extern DummyReg EEDR;
|
||||||
extern DummyReg EEMPE;
|
extern DummyReg EEMPE;
|
||||||
extern DummyReg EEPE;
|
extern DummyReg EEPE;
|
||||||
extern DummyReg OCIE0A;
|
|
||||||
extern DummyReg OCIE0B;
|
|
||||||
extern DummyReg OCIE1A;
|
|
||||||
extern DummyReg OCR1A;
|
|
||||||
extern DummyReg OCR2A;
|
extern DummyReg OCR2A;
|
||||||
extern DummyReg PCICR;
|
extern DummyReg PCICR;
|
||||||
extern DummyReg PCIE0;
|
extern DummyReg PCIE0;
|
||||||
extern DummyReg PCIE1;
|
extern DummyReg PCIE1;
|
||||||
extern DummyReg PCMSK0;
|
extern DummyReg PCMSK0;
|
||||||
extern DummyReg PCMSK1;
|
extern DummyReg PCMSK1;
|
||||||
extern DummyReg SREG;
|
|
||||||
extern DummyReg TCCR0A;
|
|
||||||
extern DummyReg TCCR0B;
|
|
||||||
extern DummyReg TCCR1A;
|
|
||||||
extern DummyReg TCCR1B;
|
|
||||||
extern DummyReg TCCRA;
|
|
||||||
extern DummyReg TCCR2A;
|
extern DummyReg TCCR2A;
|
||||||
extern DummyReg TCCR2B;
|
extern DummyReg TCCR2B;
|
||||||
extern DummyReg TCNT0;
|
|
||||||
extern DummyReg TIMSK0;
|
|
||||||
extern DummyReg TIMSK1;
|
|
||||||
extern DummyReg TOIE0;
|
|
||||||
|
|
||||||
extern DummyReg UCSR0A;
|
extern DummyReg UCSR0A;
|
||||||
extern DummyReg UCSR0B;
|
extern DummyReg UCSR0B;
|
||||||
@ -68,11 +54,7 @@ static const int COM2A1 = 0;
|
|||||||
static const int COM2B0 = 0;
|
static const int COM2B0 = 0;
|
||||||
static const int COM2B1 = 0;
|
static const int COM2B1 = 0;
|
||||||
|
|
||||||
static const int CS01 = 0;
|
static const int CS22 = 0;
|
||||||
static const int CS10 = 0;
|
|
||||||
static const int CS11 = 0;
|
|
||||||
static const int CS12 = 0;
|
|
||||||
static const int CS22 = 0;
|
|
||||||
static const int EEMWE = 0;
|
static const int EEMWE = 0;
|
||||||
static const int EERE = 0;
|
static const int EERE = 0;
|
||||||
static const int EEWE = 0;
|
static const int EEWE = 0;
|
||||||
|
@ -24,15 +24,25 @@
|
|||||||
|
|
||||||
void delay_init();
|
void delay_init();
|
||||||
|
|
||||||
|
// Get current time in clock cycles
|
||||||
|
inline uint32_t get_time()
|
||||||
|
{
|
||||||
|
return LPC_TIM3->TC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until get_time() is numCycles past startTime. Handles timer wrap.
|
||||||
|
inline void delay_loop(uint32_t startTime, uint32_t numCycles)
|
||||||
|
{
|
||||||
|
while (get_time() - startTime < numCycles)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
inline void delay_us(uint32_t us)
|
inline void delay_us(uint32_t us)
|
||||||
{
|
{
|
||||||
uint32_t start = LPC_TIM3->TC;
|
delay_loop(get_time(), uint32_t(uint64_t(SystemCoreClock) * us / 1'000'000));
|
||||||
uint32_t cycles = uint32_t(uint64_t(SystemCoreClock) * us / 1000000);
|
|
||||||
while (LPC_TIM3->TC - start < cycles)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void delay_ms(uint32_t ms)
|
inline void delay_ms(uint32_t ms)
|
||||||
{
|
{
|
||||||
return delay_us(ms * 1000);
|
delay_loop(get_time(), uint32_t(uint64_t(SystemCoreClock) * ms / 1000));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user