📄 ect_pwm.c
字号:
if (duty > 100) {
return (ECT_PWM_ERR_DUTY); /* Return an error if the duty cycle is invalid (> 100%) */
}
/* Determine if the specified frequency is possible */
ECT_prescaler = TSCR2 & TSCR2_PR_MASK; /* Get the prescaler value in the control register */
ECT_prescaler = (1 << ECT_prescaler); /* Calculate the correct prescaler value from the reg val */
busclk_frq = BSP_CPU_ClkFreq(); /* Get the current CPU frequency (Hz) */
busclk_frq /= 2; /* Divide the CPU frequency by 2 to get the BUSCLK freq */
ECT_curr_frq = busclk_frq / (ECT_prescaler); /* Determine the frequency of the ECT timer */
if (ECT_curr_frq < frq_hz) {
return (ECT_PWM_ERR_FRQ); /* Desired PWM frequency is not obtainable given the */
} /* current ECT prescaler and bus clock frequency */
CPU_CRITICAL_ENTER(); /* Disable interrupts when modifying global shared data */
Period[channel] = (busclk_frq / (ECT_prescaler * frq_hz)); /* Calculate necessary PWM settings */
Mark[channel] = ((Period[channel] * duty) / 100);
Space[channel] = (Period[channel] - Mark[channel]);
CPU_CRITICAL_EXIT(); /* Re-enable interrupts */
if (duty <= 3) { /* 0-3 percent, PWM off. See note 1) */
ECT_PWM_Dis(channel, ECT_PWM_LAST_LOW); /* Stop the PWM with the output LOW */
} else if (duty >= 98) { /* 98-100 percent, PWM off. See note 1) */
ECT_PWM_Dis(channel, ECT_PWM_LAST_HIGH); /* Stop the PWM with the output HIGH */
} else {
ECT_PWM_DisLast[channel][ECT_DIS] = 0; /* Re-enable the PWM channel if currently discabled */
TIE |= (1 << channel); /* Re-enable interrupts if the PWM is currently disabled */
}
return (ECT_PWM_ERR_NONE); /* Return without error */
}
/*
*********************************************************************************************************
* ECT_PWM_Dis()
*
* Description : This function safely stops the specified PWM channel with the output pin
* in the specified state.
*
* Arguments : channel, The ECT and SW PWM channel to stop (0-7)
* or (4-7) depending on the derivative
*
* last, The state of the output pin after the last transition has ooccured.
* (ECT_PWM_LAST_LOW = logic low, ECT_PWM_LAST_HIGH = logic high)
*
* Returns : ECT_PWM_ERR_NONE, No error has occured.
* ECT_PWM_ERR_CHA, Error. An invalid channel number was specified
* ECT_PWM_ERR_RESV, Error. The reserved channel number was specified
* ECT_PWM_ERR_LAST, Error. An invalid value for 'last' has been specified
* ECT_PWM_ERR_OFF, Error. The PWM channel is already disabled.
*********************************************************************************************************
*/
CPU_INT08U ECT_PWM_Dis (CPU_INT08U channel, CPU_INT08U last)
{
if (channel > 7) {
return (ECT_PWM_ERR_CHA); /* Channel number > 7 is invalid */
}
if ((ECT_NBR_CHANNELS == 4) && (channel < 4)) { /* Only 4 channels, 4-7, supported on this derivative */
return (ECT_PWM_ERR_CHA);
}
if ((channel == 7) && (ECT_PWM_ERR_RESV > 0)) {
return (ECT_PWM_ERR_RESV); /* Invalid channel number. Channel 7 is reserved */
}
if ((last != ECT_PWM_LAST_LOW) && (last != ECT_PWM_LAST_HIGH)) { /* Invalid value for last. Must be 0 or 1 */
return (ECT_PWM_ERR_LAST);
}
if ((TIE & (1 << channel)) == 0) { /* Disabling the PWM has no meaning if it is already off */
return (ECT_PWM_ERR_OFF); /* Return an error code indicating this condition */
}
CPU_CRITICAL_ENTER();
ECT_PWM_DisLast[channel][ECT_DIS] = 1;
ECT_PWM_DisLast[channel][ECT_LAST] = last;
CPU_CRITICAL_EXIT();
return (ECT_PWM_ERR_NONE); /* Return without error */
}
/*
*********************************************************************************************************
* ECT_PWM_ISR()
*
* Description : This function serves as the interrupt service routine for ALL PWM channels. The
* interrupting channel is identified and reconfigured for the next Mark or Space
* depending on the current level of the output pin. The application programmer
* MUST set an interrupt vector to this function for each channel of PWM that they
* wish to implement in their application.
*
* Arguments : None.
*
* Returns : None.
*
* Notes : This function MUST be located in NON_BANKED memory.
*********************************************************************************************************
*/
#pragma CODE_SEG NON_BANKED
interrupt CPU_VOID ECT_PWM_ISR (CPU_VOID)
{
CPU_INT08U flags;
CPU_INT08U oln_bit;
CPU_INT08U i;
CPU_INT16U *ptcn_base;
CPU_INT16U *ptcn;
CPU_INT08U last_channel;
ptcn_base = ((CPU_INT08U *)(&TC4)) - 8; /* All derivatives have TC4. Get the address of TC4 and */
flags = TFLG1; /* Read the flags reg, determine which channel interrupted */
if (ECT_PWM_RESV_TC7 > 0) { /* Check for channels 4-6 and possibly 7 if not rsvd */
last_channel = 6; /* If ECT TC7 is reserved, then final loop value is 6 */
} else {
last_channel = 7; /* If ECT TC7 not reserved, then final loop value is 7 */
}
#if (ECT_NBR_CHANNELS == 8) /* If 8 channels available, test flags for channels 0-4 */
for (i = 0; i < 4; i++) {
if ((flags & (1 << i)) > 0) { /* If channel 'i' interrupted */
ptcn = (ptcn_base + i); /* Determine address of TCn register to modify */
oln_bit = (i * 2); /* Determine OLn bit position of channel 'i' */
if ((TCTL2 & (1 << oln_bit)) > 0) { /* If channel is set to generate rising edge */
*ptcn += Mark[i]; /* Set up timer compare for mark (on) time, clear TCn flag */
TCTL2 &= ~(1 << oln_bit); /* Set pin action to falling edge */
if ((ECT_PWM_DisLast[i][ECT_DIS] == 1) && /* If stopping PWM channel 'i' with pin polarity high */
(ECT_PWM_DisLast[i][ECT_LAST] == ECT_PWM_LAST_HIGH)) {
TIE &= ~(1 << i); /* Disable interrupts for PWM channel 'i' */
}
} else { /* Channel is set to generate a falling edge */
*ptcn += Space[i]; /* Set up timer compare for space (off) time */
TCTL2 |= (1 << oln_bit); /* Set pin action to rising edge */
if ((ECT_PWM_DisLast[i][ECT_DIS] == 1) && /* If stopping PWM channel 'i' with pin polarity low */
(ECT_PWM_DisLast[i][ECT_LAST] == ECT_PWM_LAST_LOW)) {
TIE &= ~(1 << i); /* Disable interrupts for PWM channel 'i' */
}
}
TFLG1 |= (1 << i); /* Clear the interrupt flag for TCn, where n = i. */
}
}
#endif
for (i = 4; i <= last_channel; i++) {
if ((flags & (1 << i)) > 0) { /* If channel 'i' interrupted */
ptcn = (ptcn_base + i); /* Determine address of TCn register to modify */
oln_bit = ((i - 4) * 2); /* Determine OLn bit position of channel 'i' */
if ((TCTL1 & (1 << oln_bit)) > 0) { /* If channel is set to generate rising edge */
*ptcn += Space[i]; /* Set up timer compare for space (off) time */
TCTL1 &= ~(1 << oln_bit); /* Set pin HIGH for Mark # of ticks. Next compare set LOW */
if ((ECT_PWM_DisLast[i][ECT_DIS] == 1) && /* If stopping PWM channel 'i' with pin polarity high */
(ECT_PWM_DisLast[i][ECT_LAST] == ECT_PWM_LAST_HIGH)) {
TIE &= ~(1 << i); /* Disable interrupts for PWM channel 'i' */
}
} else { /* Channel is set to generate a falling edge */
*ptcn += Mark[i]; /* Set up timer compare for mark (on) time, clear TCn flag */
TCTL1 |= (1 << oln_bit); /* Set pin LOW for Space # of ticks. Next compare set HIGH */
if ((ECT_PWM_DisLast[i][ECT_DIS] == 1) && /* If stopping PWM channel 'i' with pin polarity low */
(ECT_PWM_DisLast[i][ECT_LAST] == ECT_PWM_LAST_LOW)) {
TIE &= ~(1 << i); /* Disable interrupts for PWM channel 'i' */
}
}
TFLG1 |= (1 << i); /* Clear the interrupt flag for TCn, where n = i. */
}
}
}
#pragma CODE_SEG DEFAULT_ROM
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -