To use the PWM functions of the PWM Output pins we have to modify the lpcopen library. Then we have to do four steps to configure the PWM:
1) modify the lpcopen library
2) configure the IO pins for pwm function
3) Initialise the PWM
4) set a match value for the PWM timer and with it the duty cycle.
Modify the lpcopen library:
For some reason the PIO_SWCLK_PIO0_10 register address is not added in the iocon_13xx.h, maybe because this pin has also the swclk function for the jtag interface. So if you want to use this pin as PWM make sure you do not need the jtag interface for reprogramming the chip. I am programming via the uart so I can change the pin configuration without a worry.
To add the register address to the iocon_13xx.h you have to modify the CHIP_IOCON_PIO enum which defines the address offsets and add
IOCON_SWCLK_PIO0_10 = (0x068 >> 2),
/**
* @brief 32-bit Standard timer register block structure
*/
typedef struct { /*!< TIMERn Structure */
__IO uint32_t IR; /*!< Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */
__IO uint32_t TCR; /*!< Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */
__IO uint32_t TC; /*!< Timer Counter. The 32 bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */
__IO uint32_t PR; /*!< Prescale Register. The Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */
__IO uint32_t PC; /*!< Prescale Counter. The 32 bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */
__IO uint32_t MCR; /*!< Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */
__IO uint32_t MR[4]; /*!< Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */
__IO uint32_t CCR; /*!< Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */
__IO uint32_t CR[4]; /*!< Capture Register. CR is loaded with the value of TC when there is an event on the CAPn.0 input. */
__IO uint32_t EMR; /*!< External Match Register. The EMR controls the external match pins MATn.0-3 (MAT0.0-3 and MAT1.0-3 respectively). */
__I uint32_t RESERVED0[12];
__IO uint32_t CTCR; /*!< Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */
__IO uint32_t PWMC; /*!< PWM Control Register */
} LPC_TIMER_T;
/**
* @brief Sets the PWM Control Register
* @param pTMR : Pointer to timer IP register address
* pwmval : value for the PWMC Register
* @return
* @note Sets the PWMC Register.
*/
STATIC INLINE void Chip_TIMER_PWMWrite(LPC_TIMER_T *pTMR, uint32_t pwmval)
{
pTMR->PWMC = pwmval;
}
/**
* @brief Returns the PWMC Register
* @param pTMR : Pointer to timer IP register address
* @return Current PWMC value
* @note Returns the current PWMC value.
*/
STATIC INLINE uint32_t Chip_TIMER_PWMRead(LPC_TIMER_T *pTMR)
{
return pTMR->PWMC;
}
/**
* @brief struct for pinmuxing on the bldc_board
*
* This struct contains the pinmuxing settings...
*
*/
const PINMUX_GRP_T pinmuxing[] = {
{(uint32_t)IOCON_PIO0_8,
(IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_RESERVED_BIT_6
| IOCON_RESERVED_BIT_7)}, /*PIO0_8 used for PWM (CT16B0_MAT0)*/
{(uint32_t)IOCON_PIO0_9,
(IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_RESERVED_BIT_6
| IOCON_RESERVED_BIT_7)}, /*PIO0_9 used for PWM (CT16B0_MAT0)*/
{(uint32_t)IOCON_SCKCLK_PIO0_10,
(IOCON_FUNC3 | IOCON_MODE_INACT | IOCON_RESERVED_BIT_6
| IOCON_RESERVED_BIT_7)}, /*PIO0_10 used for PWM (CT16B0_MAT0)*/
};
void Init_Board_PinMux(void)
{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);
Chip_IOCON_SetPinMuxing(LPC_IOCON,pinmuxing,
sizeof(pinmuxing)/sizeof(PINMUX_GRP_T));
}
void Init_PWM(uint16_t prescaler, uint16_t OnResetValue)
{
/* Setup Timer for PWM */
Chip_TIMER_Init(LPC_TIMER16_0);
// MR3 reset
Chip_TIMER_ResetOnMatchEnable(LPC_TIMER16_0, 3);
// Set the frequency prescaler for the timer
Chip_TIMER_PrescaleSet(LPC_TIMER16_0, prescaler-1);
// Set MR3 value for resetting the timer
Chip_TIMER_SetMatch(LPC_TIMER16_0, 3, OnResetValue);
// Set PWM Control Register
Chip_TIMER_PWMWrite(LPC_TIMER16_0,(1<<0 | 1<<1 | 1<<2));
// Enable Timer16_0
Chip_TIMER_Enable(LPC_TIMER16_0);
}
int main() {
uint16_t pwm = 1800;
Init_Board_PinMux();
// no prescaler, a reset value of 3600 is a pwm freq. of 20 kHz
Init_PWM(1,3600);
// set MATCH2(PIO0_10) to a duty cycle of 50%
Chip_TIMER_SetMatch(LPC_TIMER16_0,2,pwm_value);
}
Hello,
Thank you for posting the tutorial 🙂
When I try your sample code I get an error:
‚IOCON_PIO0_8‘ undeclared here (not in a function)
I have checked all my includes and I can see „iocon_13xx.h“ is included, where IOCON_PIO0_8 is defined.
If you have any suggestions I would be grateful.
Thanks.