NANO102/112 BSP V3.03.003
The Board Support Package for Nano102/112 Series
pwm.c
Go to the documentation of this file.
1/**************************************************************************/
12#include "Nano1X2Series.h"
13
38 uint32_t u32ChannelNum,
39 uint32_t u32Frequency,
40 uint32_t u32DutyCycle)
41{
42 uint32_t i;
43 uint32_t u32PWM_Clock = SystemCoreClock;
44 uint8_t u8Divider = 1, u8Prescale = 0xFF;
45 uint16_t u16CNR = 0xFFFF;
46
47 switch ((CLK->CLKSEL1 & (CLK_CLKSEL1_PWM0_CH01_S_Msk << (u32ChannelNum & 2))) >> (CLK_CLKSEL1_PWM0_CH01_S_Pos + (u32ChannelNum & 2)))
48 {
49 case 0:
50 u32PWM_Clock = __HXT;
51 break;
52 case 1:
53 u32PWM_Clock = __LXT;
54 break;
55 case 2:
56 u32PWM_Clock = SystemCoreClock;
57 break;
58 case 3:
59 if (CLK->PWRCTL & CLK_PWRCTL_HIRC_FSEL_Msk)
60 u32PWM_Clock = __HIRC16M;
61 else
62 u32PWM_Clock = __HIRC12M;
63 break;
64 }
65
66 for(; u8Divider < 17; u8Divider <<= 1) // clk divider could only be 1, 2, 4, 8, 16
67 {
68 i = (u32PWM_Clock / u32Frequency) / u8Divider;
69 // If target value is larger than CNR * prescale, need to use a larger divider
70 if(i > (0x10000 * 0x100))
71 continue;
72
73 // CNR = 0xFFFF + 1, get a prescaler that CNR value is below 0xFFFF
74 u8Prescale = (i + 0xFFFF)/ 0x10000;
75
76 // u8Prescale must at least be 2, otherwise the output stop
77 if(u8Prescale < 3)
78 u8Prescale = 2;
79
80 i /= u8Prescale;
81
82 if(i <= 0x10000)
83 {
84 if(i == 1)
85 u16CNR = 1; // Too fast, and PWM cannot generate expected frequency...
86 else
87 u16CNR = i;
88 break;
89 }
90
91 }
92 // Store return value here 'cos we're gonna change u8Divider & u8Prescale & u16CNR to the real value to fill into register
93 i = u32PWM_Clock / (u8Prescale * u8Divider * u16CNR);
94
95 u8Prescale -= 1;
96 u16CNR -= 1;
97 // convert to real register value
98 if(u8Divider == 1)
99 u8Divider = 4;
100 else if (u8Divider == 2)
101 u8Divider = 0;
102 else if (u8Divider == 4)
103 u8Divider = 1;
104 else if (u8Divider == 8)
105 u8Divider = 2;
106 else // 16
107 u8Divider = 3;
108
109 // every two channels share a prescaler
111 pwm->PRES = (pwm->PRES & ~(PWM_PRES_CP01_Msk << ((u32ChannelNum >> 1) * 8))) | (u8Prescale << ((u32ChannelNum >> 1) * 8));
112 pwm->CLKSEL = (pwm->CLKSEL & ~(PWM_CLKSEL_CLKSEL0_Msk << (4 * u32ChannelNum))) | (u8Divider << (4 * u32ChannelNum));
113 pwm->CTL |= (PWM_CTL_CH0MOD_Msk << (u32ChannelNum * 8));
114 while((pwm->INTSTS & (PWM_INTSTS_Duty0Syncflag_Msk << u32ChannelNum)) == (PWM_INTSTS_Duty0Syncflag_Msk << u32ChannelNum));
115 if(u32DutyCycle == 0)
116 *(__IO uint32_t *) (&pwm->DUTY0 + 3 * u32ChannelNum) &= ~PWM_DUTY0_CM_Msk;
117 else
118 {
119 *(__IO uint32_t *) (&pwm->DUTY0 + 3 * u32ChannelNum) &= ~PWM_DUTY0_CM_Msk;
120 *(__IO uint32_t *) (&pwm->DUTY0 + 3 * u32ChannelNum) |= ((u32DutyCycle * (u16CNR + 1) / 100 - 1) << PWM_DUTY0_CM_Pos);
121 }
122 *(__IO uint32_t *) (&pwm->DUTY0 + 3 * u32ChannelNum) &= ~PWM_DUTY0_CN_Msk;
123 *(__IO uint32_t *) (&pwm->DUTY0 + 3 * u32ChannelNum) |= u16CNR;
124
125 return(i);
126}
127
139 uint32_t u32ChannelNum,
140 uint32_t u32UnitTimeNsec,
141 uint32_t u32CaptureEdge)
142{
143 uint32_t i;
144 uint32_t u32PWM_Clock = SystemCoreClock;
145 uint8_t u8Divider = 1, u8Prescale = 0xFF;
146 uint16_t u16CNR = 0xFFFF;
147
148 switch ((CLK->CLKSEL1 & (CLK_CLKSEL1_PWM0_CH01_S_Msk << (u32ChannelNum & 2))) >> (CLK_CLKSEL1_PWM0_CH01_S_Pos + (u32ChannelNum & 2)))
149 {
150 case 0:
151 u32PWM_Clock = __HXT;
152 break;
153 case 1:
154 u32PWM_Clock = __LXT;
155 break;
156 case 2:
157 u32PWM_Clock = SystemCoreClock;
158 break;
159 case 3:
160 if (CLK->PWRCTL & CLK_PWRCTL_HIRC_FSEL_Msk)
161 u32PWM_Clock = __HIRC16M;
162 else
163 u32PWM_Clock = __HIRC12M;
164 break;
165 }
166
167 for(; u8Divider < 17; u8Divider <<= 1) // clk divider could only be 1, 2, 4, 8, 16
168 {
169 i = ((long long)(u32PWM_Clock / u8Divider) * u32UnitTimeNsec) / 1000000000;
170
171 // If target value is larger than 0xFF, need to use a larger divider
172 if(i > (0xFF))
173 continue;
174
175 u8Prescale = i;
176
177 // u8Prescale must at least be 2, otherwise the output stop
178 if(u8Prescale < 3)
179 u8Prescale = 2;
180
181 break;
182 }
183
184 // Store return value here 'cos we're gonna change u8Divider & u8Prescale & u16CNR to the real value to fill into register
185 i = (long long) (u8Prescale * u8Divider) * 1000000000 / u32PWM_Clock;
186
187 u8Prescale -= 1;
188 u16CNR -= 1;
189 // convert to real register value
190 if(u8Divider == 1)
191 u8Divider = 4;
192 else if (u8Divider == 2)
193 u8Divider = 0;
194 else if (u8Divider == 4)
195 u8Divider = 1;
196 else if (u8Divider == 8)
197 u8Divider = 2;
198 else // 16
199 u8Divider = 3;
200
201 // every two channels share a prescaler
203 pwm->PRES = (pwm->PRES & ~(PWM_PRES_CP01_Msk << ((u32ChannelNum >> 1) * 8))) | (u8Prescale << ((u32ChannelNum >> 1) * 8));
204 pwm->CLKSEL = (pwm->CLKSEL & ~(PWM_CLKSEL_CLKSEL0_Msk << (4 * u32ChannelNum))) | (u8Divider << (4 * u32ChannelNum));
205 pwm->CTL |= (PWM_CTL_CH0MOD_Msk << (u32ChannelNum * 8));
206 while((pwm->INTSTS & (PWM_INTSTS_Duty0Syncflag_Msk << u32ChannelNum)) == (PWM_INTSTS_Duty0Syncflag_Msk << u32ChannelNum));
207 *(__IO uint32_t *) (&pwm->DUTY0 + 3 * u32ChannelNum) &= ~PWM_DUTY0_CN_Msk;
208 *(__IO uint32_t *) (&pwm->DUTY0 + 3 * u32ChannelNum) |= u16CNR;
209
210 return(i);
211}
212
220void PWM_Start (PWM_T *pwm, uint32_t u32ChannelMask)
221{
222 uint8_t i;
223 uint32_t u32Mask = 0;
224
225 for (i = 0; i < PWM_CHANNEL_NUM; i++)
226 {
227 if ( u32ChannelMask & (1 << i))
228 u32Mask |= (PWM_CTL_CH0EN_Msk << (i * 8));
229 }
230
231 pwm->CTL |= u32Mask;
232}
233
241void PWM_Stop (PWM_T *pwm, uint32_t u32ChannelMask)
242{
243 uint32_t i;
244 for(i = 0; i < PWM_CHANNEL_NUM; i ++)
245 {
246 if(u32ChannelMask & (1 << i))
247 {
248 *(__IO uint32_t *) (&pwm->DUTY0 + 3 * i) &= ~PWM_DUTY0_CN_Msk;
249 }
250 }
251
252}
253
261void PWM_ForceStop (PWM_T *pwm, uint32_t u32ChannelMask)
262{
263 uint32_t i;
264 for (i = 0; i < PWM_CHANNEL_NUM; i++)
265 {
266 if ( u32ChannelMask & (1 << i))
267 pwm->CTL &= ~(PWM_CTL_CH0EN_Msk << (i * 8));
268 }
269}
270
278void PWM_EnableADCTrigger (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
279{
280 pwm->ADTRGEN |= (PWM_ADTRGEN_TRGCH0EN_Msk << u32ChannelNum);
281}
282
289void PWM_DisableADCTrigger (PWM_T *pwm, uint32_t u32ChannelNum)
290{
291 pwm->ADTRGEN &= ~(PWM_ADTRGEN_TRGCH0EN_Msk << u32ChannelNum);
292}
293
301void PWM_ClearADCTriggerFlag (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
302{
303 pwm->ADTRGSTS |= (PWM_ADTRGSTS_ADTRG0Flag_Msk << u32ChannelNum);
304}
305
314uint32_t PWM_GetADCTriggerFlag (PWM_T *pwm, uint32_t u32ChannelNum)
315{
316 return ((pwm->ADTRGSTS & (PWM_ADTRGSTS_ADTRG0Flag_Msk << u32ChannelNum)) >> u32ChannelNum);
317}
318
319
327void PWM_EnableCapture (PWM_T *pwm, uint32_t u32ChannelMask)
328{
329 uint8_t i;
330 uint32_t u32Mask = 0;
331
332 for (i = 0; i < PWM_CHANNEL_NUM; i++)
333 {
334 if ( u32ChannelMask & (1 << i))
335 {
336 u32Mask |= ((PWM_CAPCTL_CAPCH0EN_Msk | PWM_CAPCTL_CAPCH0PADEN_Msk) << (i * 8));
337 }
338 }
339
340 pwm->CAPCTL |= u32Mask;
341}
342
350void PWM_DisableCapture (PWM_T *pwm, uint32_t u32ChannelMask)
351{
352 uint8_t i;
353 uint32_t u32CTLMask = 0;
354 uint32_t u32CAPCTLMask = 0;
355
356
357 for (i = 0; i < PWM_CHANNEL_NUM; i++)
358 {
359 if ( u32ChannelMask & (1 << i))
360 {
361 u32CTLMask |= (PWM_CTL_CH0EN_Msk << (i * 8));
362 u32CAPCTLMask |= ((PWM_CAPCTL_CAPCH0EN_Msk | PWM_CAPCTL_CAPCH0PADEN_Msk) << (i * 8));
363 }
364 }
365
366 pwm->CTL &= ~u32CTLMask;
367 pwm->CAPCTL &= ~u32CAPCTLMask;
368
369}
370
378void PWM_EnableOutput (PWM_T *pwm, uint32_t u32ChannelMask)
379{
380 pwm->OE |= u32ChannelMask;
381}
382
390void PWM_DisableOutput (PWM_T *pwm, uint32_t u32ChannelMask)
391{
392 pwm->OE &= ~u32ChannelMask;
393}
394
403void PWM_EnableDeadZone (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration)
404{
405 // every two channels shares the same setting
406 u32ChannelNum >>= 1;
407 // set duration
408 pwm->PRES = (pwm->PRES & ~(PWM_PRES_DZ01_Msk << (8 * u32ChannelNum))) | ((u32Duration << PWM_PRES_DZ01_Pos ) << (8 * u32ChannelNum));
409 // enable dead zone
410 pwm->CTL |= (PWM_CTL_DZEN01_Msk << u32ChannelNum);
411}
412
419void PWM_DisableDeadZone (PWM_T *pwm, uint32_t u32ChannelNum)
420{
421 // every two channels shares the same setting
422 u32ChannelNum >>= 1;
423 // enable dead zone
424 pwm->CTL &= ~(PWM_CTL_DZEN01_Msk << u32ChannelNum);
425}
426
437void PWM_EnableCaptureInt (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
438{
439 // enable capture interrupt
440 pwm->CAPINTEN |= (u32Edge << (u32ChannelNum * 8));
441}
442
453void PWM_DisableCaptureInt (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
454{
455 // disable capture interrupt
456 pwm->CAPINTEN &= ~(u32Edge << (u32ChannelNum * 8));
457}
458
469void PWM_ClearCaptureIntFlag (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
470{
471 // disable capture interrupt flag
472 pwm->CAPINTSTS = (u32Edge + 1) << (u32ChannelNum * 8);
473}
474
485uint32_t PWM_GetCaptureIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
486{
487 return ((pwm->CAPINTSTS >> (u32ChannelNum * 8)) & (PWM_RISING_FALLING_LATCH_INT_FLAG));
488}
489
496void PWM_ClearDutyIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
497{
498 // write 1 clear
499 pwm->INTSTS = (PWM_INTEN_TMIE0_Msk << u32ChannelNum);
500}
501
510uint32_t PWM_GetDutyIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
511{
512 return ((pwm->INTSTS & (PWM_INTEN_TMIE0_Msk << u32ChannelNum)) ? 1 : 0);
513}
514
523void PWM_EnablePeriodInt (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType)
524{
525 // enable period interrupt
526 pwm->INTEN |= (PWM_INTEN_TMIE0_Msk << u32ChannelNum);
527}
528
535void PWM_DisablePeriodInt (PWM_T *pwm, uint32_t u32ChannelNum)
536{
537 pwm->INTEN &= ~(PWM_INTEN_TMIE0_Msk << u32ChannelNum);
538}
539
546void PWM_ClearPeriodIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
547{
548 // write 1 clear
549 pwm->INTSTS = (PWM_INTSTS_TMINT0_Msk << u32ChannelNum);
550}
551
560uint32_t PWM_GetPeriodIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
561{
562 return ((pwm->INTSTS & (PWM_INTSTS_TMINT0_Msk << u32ChannelNum)) ? 1 : 0);
563}
564
578void PWM_EnablePDMA(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32RisingFirst, uint32_t u32Mode)
579{
580 if (u32ChannelNum == 0)
581 pwm->CAPCTL = (pwm->CAPCTL & ~(PWM_CAPCTL_PDMACAPMOD0_Msk | PWM_CAPCTL_CH0RFORDER_Msk)) | u32Mode | u32RisingFirst | PWM_CAPCTL_CH0PDMAEN_Msk;
582 else
583 pwm->CAPCTL = (pwm->CAPCTL & ~(PWM_CAPCTL_PDMACAPMOD2_Msk | PWM_CAPCTL_CH2RFORDER_Msk)) | (u32Mode << 16)| (u32RisingFirst << 16)| PWM_CAPCTL_CH2PDMAEN_Msk;
584}
585
592void PWM_DisablePDMA(PWM_T *pwm, uint32_t u32ChannelNum)
593{
594 if (u32ChannelNum == 0)
595 pwm->CAPCTL &= ~PWM_CAPCTL_CH0PDMAEN_Msk;
596 else
597 pwm->CAPCTL &= ~PWM_CAPCTL_CH2PDMAEN_Msk;
598}
599
600 /* end of group NANO1X2_PWM_EXPORTED_FUNCTIONS */
602 /* end of group NANO1X2_PWM_Driver */
604 /* end of group NANO1X2_Device_Driver */
606
607/*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
Nano102/112 peripheral access layer header file. This file contains all the peripheral register's def...
#define PWM_CAPCTL_PDMACAPMOD0_Msk
#define PWM_INTEN_TMIE0_Msk
#define PWM_CAPCTL_CH0RFORDER_Msk
#define PWM_ADTRGEN_TRGCH0EN_Msk
#define PWM_PRES_CP01_Msk
#define PWM_INTSTS_PresSyncFlag_Msk
#define PWM_CLKSEL_CLKSEL0_Msk
#define PWM_PRES_DZ01_Msk
#define PWM_CAPCTL_PDMACAPMOD2_Msk
#define PWM_CAPCTL_CH2RFORDER_Msk
#define PWM_DUTY0_CM_Pos
#define PWM_CAPCTL_CAPCH0EN_Msk
#define PWM_CAPCTL_CH0PDMAEN_Msk
#define PWM_CTL_CH0MOD_Msk
#define PWM_CTL_CH0EN_Msk
#define PWM_CTL_DZEN01_Msk
#define PWM_ADTRGSTS_ADTRG0Flag_Msk
#define PWM_PRES_DZ01_Pos
#define PWM_INTSTS_Duty0Syncflag_Msk
#define PWM_INTSTS_TMINT0_Msk
#define PWM_CAPCTL_CAPCH0PADEN_Msk
#define PWM_CAPCTL_CH2PDMAEN_Msk
#define CLK_CLKSEL1_PWM0_CH01_S_Pos
#define CLK_CLKSEL1_PWM0_CH01_S_Msk
#define CLK_PWRCTL_HIRC_FSEL_Msk
#define CLK
Pointer to CLK register structure.
#define PWM_RISING_FALLING_LATCH_INT_FLAG
Definition: pwm.h:53
#define PWM_CHANNEL_NUM
Definition: pwm.h:32
void PWM_ForceStop(PWM_T *pwm, uint32_t u32ChannelMask)
This function stop PWM generation immediately by clear channel enable bit.
Definition: pwm.c:261
void PWM_Stop(PWM_T *pwm, uint32_t u32ChannelMask)
This function stop PWM module.
Definition: pwm.c:241
void PWM_EnableCapture(PWM_T *pwm, uint32_t u32ChannelMask)
This function enables PWM capture of selected channels.
Definition: pwm.c:327
void PWM_EnablePDMA(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32RisingFirst, uint32_t u32Mode)
This function enable capture PDMA of selected channel.
Definition: pwm.c:578
void PWM_EnableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration)
This function enable Dead zone of selected channel.
Definition: pwm.c:403
void PWM_ClearCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
This function clear capture interrupt flag of selected channel.
Definition: pwm.c:469
void PWM_ClearADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
This function clear selected channel trigger ADC flag.
Definition: pwm.c:301
void PWM_DisableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum)
This function disable selected channel to trigger ADC.
Definition: pwm.c:289
uint32_t PWM_ConfigCaptureChannel(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge)
This function config PWM capture and get the nearest unit time.
Definition: pwm.c:138
void PWM_DisablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum)
This function disable period interrupt of selected channel.
Definition: pwm.c:535
void PWM_DisableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
This function disable capture interrupt of selected channel.
Definition: pwm.c:453
uint32_t PWM_ConfigOutputChannel(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle)
This function config PWM generator and get the nearest frequency in edge aligned auto-reload mode.
Definition: pwm.c:37
uint32_t PWM_GetADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function get selected channel trigger ADC flag.
Definition: pwm.c:314
void PWM_DisableCapture(PWM_T *pwm, uint32_t u32ChannelMask)
This function disables PWM capture of selected channels.
Definition: pwm.c:350
void PWM_ClearDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function clears duty interrupt flag of selected channel.
Definition: pwm.c:496
void PWM_EnablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType)
This function enable period interrupt of selected channel.
Definition: pwm.c:523
uint32_t PWM_GetDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function get duty interrupt flag of selected channel.
Definition: pwm.c:510
void PWM_DisableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum)
This function disable Dead zone of selected channel.
Definition: pwm.c:419
void PWM_DisableOutput(PWM_T *pwm, uint32_t u32ChannelMask)
This function disables PWM output generation of selected channels.
Definition: pwm.c:390
void PWM_DisablePDMA(PWM_T *pwm, uint32_t u32ChannelNum)
This function disable capture PDMA of selected channel.
Definition: pwm.c:592
void PWM_Start(PWM_T *pwm, uint32_t u32ChannelMask)
This function start PWM module.
Definition: pwm.c:220
void PWM_ClearPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function clear period interrupt of selected channel.
Definition: pwm.c:546
void PWM_EnableOutput(PWM_T *pwm, uint32_t u32ChannelMask)
This function enables PWM output generation of selected channels.
Definition: pwm.c:378
uint32_t PWM_GetCaptureIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function get capture interrupt flag of selected channel.
Definition: pwm.c:485
uint32_t PWM_GetPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function get period interrupt of selected channel.
Definition: pwm.c:560
void PWM_EnableCaptureInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Edge)
This function enable capture interrupt of selected channel.
Definition: pwm.c:437
void PWM_EnableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
This function enable selected channel to trigger ADC.
Definition: pwm.c:278
__IO uint32_t CTL
__IO uint32_t CAPINTSTS
__IO uint32_t DUTY0
__IO uint32_t INTEN
__IO uint32_t ADTRGSTS
__IO uint32_t CLKSEL
__IO uint32_t CAPINTEN
__IO uint32_t OE
__IO uint32_t PRES
__IO uint32_t ADTRGEN
__IO uint32_t INTSTS
__IO uint32_t CAPCTL
#define __HXT
uint32_t SystemCoreClock
#define __HIRC16M
#define __LXT
#define __HIRC12M