Mini51 BSP  V3.02.002
The Board Support Package for Mini51 Series
pwm.c
Go to the documentation of this file.
1 /**************************************************************************/
12 #include "Mini51Series.h"
13 
38  uint32_t u32ChannelNum,
39  uint32_t u32Frequency,
40  uint32_t u32DutyCycle)
41 {
42  uint32_t i = SystemCoreClock / u32Frequency;
43  uint8_t u8Divider = 1, u8Prescale = 0xFF;
44  uint16_t u16CNR = 0xFFFF;
45 
46  for(; u8Divider < 17; u8Divider <<= 1) // clk divider could only be 1, 2, 4, 8, 16
47  {
48  i = (SystemCoreClock / u32Frequency) / u8Divider;
49  // If target value is larger than CNR * prescale, need to use a larger divider
50  if(i > (0x10000 * 0x100))
51  continue;
52 
53  // CNR = 0xFFFF + 1, get a prescaler that CNR value is below 0xFFFF
54  u8Prescale = (i + 0xFFFF)/ 0x10000;
55 
56  // u8Prescale must at least be 2, otherwise the output stop
57  if(u8Prescale < 3)
58  u8Prescale = 2;
59 
60  i /= u8Prescale;
61 
62  if(i <= 0x10000)
63  {
64  if(i == 1)
65  u16CNR = 1; // Too fast, and PWM cannot generate expected frequency...
66  else
67  u16CNR = i;
68  break;
69  }
70 
71  }
72  // Store return value here 'cos we're gonna change u8Divider & u8Prescale & u16CNR to the real value to fill into register
73  i = SystemCoreClock / (u8Prescale * u8Divider * u16CNR);
74 
75  u8Prescale -= 1;
76  u16CNR -= 1;
77  // convert to real register value
78  if(u8Divider == 1)
79  u8Divider = 4;
80  else if (u8Divider == 2)
81  u8Divider = 0;
82  else if (u8Divider == 4)
83  u8Divider = 1;
84  else if (u8Divider == 8)
85  u8Divider = 2;
86  else // 16
87  u8Divider = 3;
88 
89  // every two channels share a prescaler
90  PWM->PPR = (PWM->PPR & ~(PWM_PPR_CP01_Msk << ((u32ChannelNum >> 1) * 8))) | (u8Prescale << ((u32ChannelNum >> 1) * 8));
91  PWM->CSR = (PWM->CSR & ~(PWM_CSR_CSR0_Msk << (4 * u32ChannelNum))) | (u8Divider << (4 * u32ChannelNum));
92  PWM->PCR = (PWM->PCR & ~PWM_PCR_PWMTYPE_Msk) | (PWM_PCR_CH0MOD_Msk << (4 * u32ChannelNum));
93  if(u32DutyCycle == 0)
94  PWM->CMR[u32ChannelNum] = 0;
95  else
96  PWM->CMR[u32ChannelNum] = u32DutyCycle * (u16CNR + 1) / 100 - 1;
97  PWM->CNR[u32ChannelNum] = u16CNR;
98 
99  return(i);
100 }
101 
102 
110 void PWM_Start (PWM_T *pwm, uint32_t u32ChannelMask)
111 {
112  uint32_t u32Mask = 0, i;
113  for(i = 0; i < PWM_CHANNEL_NUM; i ++)
114  {
115  if(u32ChannelMask & (1 << i))
116  {
117  u32Mask |= (PWM_PCR_CH0EN_Msk << (i * 4));
118  }
119  }
120 
121  PWM->PCR |= u32Mask;
122 }
123 
131 void PWM_Stop (PWM_T *pwm, uint32_t u32ChannelMask)
132 {
133  uint32_t i;
134  for(i = 0; i < PWM_CHANNEL_NUM; i ++)
135  {
136  if(u32ChannelMask & (1 << i))
137  {
138  PWM->CNR[i] = 0;
139  }
140  }
141 
142 }
143 
151 void PWM_ForceStop (PWM_T *pwm, uint32_t u32ChannelMask)
152 {
153  uint32_t u32Mask = 0, i;
154  for(i = 0; i < PWM_CHANNEL_NUM; i ++)
155  {
156  if(u32ChannelMask & (1 << i))
157  {
158  u32Mask |= (PWM_PCR_CH0EN_Msk << (i * 4));
159  }
160  }
161 
162  PWM->PCR &= ~u32Mask;
163 }
164 
176 void PWM_EnableADCTrigger (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
177 {
178  if(u32ChannelNum < 4)
179  {
180  PWM->TRGCON0 = (PWM->TRGCON0 & ~((PWM_TRIGGER_ADC_CNTR_IS_0 |
183  PWM_TRIGGER_ADC_CNTR_IS_CMR_U ) << (8 * u32ChannelNum))) | (u32Condition << (8 * u32ChannelNum));
184  }
185  else
186  {
187  PWM->TRGCON1 = (PWM->TRGCON1 & ~((PWM_TRIGGER_ADC_CNTR_IS_0 |
190  PWM_TRIGGER_ADC_CNTR_IS_CMR_U ) << (8 * (u32ChannelNum - 4)))) | (u32Condition << (8 * (u32ChannelNum - 4)));
191 
192  }
193 }
194 
201 void PWM_DisableADCTrigger (PWM_T *pwm, uint32_t u32ChannelNum)
202 {
203  if(u32ChannelNum < 4)
204  {
205  PWM->TRGCON0 = (PWM->TRGCON0 & ~((PWM_TRIGGER_ADC_CNTR_IS_0 |
208  PWM_TRIGGER_ADC_CNTR_IS_CMR_U ) << (8 * u32ChannelNum)));
209  }
210  else
211  {
212  PWM->TRGCON1 = (PWM->TRGCON1 & ~((PWM_TRIGGER_ADC_CNTR_IS_0 |
215  PWM_TRIGGER_ADC_CNTR_IS_CMR_U ) << (8 * (u32ChannelNum - 4))));
216  }
217 }
218 
230 void PWM_ClearADCTriggerFlag (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
231 {
232  if(u32ChannelNum < 4)
233  {
234  PWM->TRGSTS0 |= (u32Condition << (8 * u32ChannelNum));
235  }
236  else
237  {
238  PWM->TRGSTS1 |= (u32Condition << (8 * (u32ChannelNum - 4)));
239  }
240 }
241 
252 uint32_t PWM_GetADCTriggerFlag (PWM_T *pwm, uint32_t u32ChannelNum)
253 {
254  uint32_t u32Ret;
255 
256  if(u32ChannelNum < 4)
257  {
258  u32Ret = PWM->TRGSTS0 >> (8 * u32ChannelNum);
259  }
260  else
261  {
262  u32Ret = PWM->TRGSTS1 >> (8 * (u32ChannelNum - 4 ));
263  }
264 
265  return (u32Ret & (PWM_TRIGGER_ADC_CNTR_IS_0 |
269 }
270 
286  uint32_t u32ChannelMask,
287  uint32_t u32LevelMask,
288  uint32_t u32BrakeSource)
289 {
290  PWM->PFBCON = (u32LevelMask << PWM_PFBCON_PWMBKO0_Pos) | u32BrakeSource;
291 }
292 
300 void PWM_ClearFaultBrakeFlag (PWM_T *pwm, uint32_t u32BrakeSource)
301 {
302  PWM->PFBCON = PWM_PFBCON_BKF_Msk;
303 }
304 
312 void PWM_EnableOutput (PWM_T *pwm, uint32_t u32ChannelMask)
313 {
314  PWM->POE |= u32ChannelMask;
315 }
316 
324 void PWM_DisableOutput (PWM_T *pwm, uint32_t u32ChannelMask)
325 {
326  PWM->POE &= ~u32ChannelMask;
327 }
328 
337 void PWM_EnableDeadZone (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration)
338 {
339  // every two channels shares the same setting
340  u32ChannelNum >>= 1;
341  // set duration
342  PWM->PDZIR = (PWM->PDZIR & ~(PWM_DZIR_DZI01_Msk << (8 * u32ChannelNum))) | (u32Duration << (8 * u32ChannelNum));
343  // enable dead zone
344  PWM->PCR |= (PWM_PCR_DZEN01_Msk << u32ChannelNum);
345 }
346 
353 void PWM_DisableDeadZone (PWM_T *pwm, uint32_t u32ChannelNum)
354 {
355  // every two channels shares the same setting
356  u32ChannelNum >>= 1;
357  // enable dead zone
358  PWM->PCR &= ~(PWM_PCR_DZEN01_Msk << u32ChannelNum);
359 }
360 
368 void PWM_EnableDutyInt (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType)
369 {
370  PWM->PIER |= (PWM_PIER_PWMDIE0_Msk << u32ChannelNum);
371 }
372 
379 void PWM_DisableDutyInt (PWM_T *pwm, uint32_t u32ChannelNum)
380 {
381  PWM->PIER &= ~(PWM_PIER_PWMDIE0_Msk << u32ChannelNum);
382 }
383 
390 void PWM_ClearDutyIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
391 {
392  PWM->PIIR = (PWM_PIIR_PWMDIF0_Msk << u32ChannelNum);
393 }
394 
403 uint32_t PWM_GetDutyIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
404 {
405  return(PWM->PIIR & (PWM_PIIR_PWMDIF0_Msk << u32ChannelNum) ? 1 : 0);
406 }
407 
414 void PWM_EnableFaultBrakeInt (PWM_T *pwm, uint32_t u32BrakeSource)
415 {
416  PWM->PIER |= PWM_PIER_BRKIE_Msk;
417 }
418 
425 void PWM_DisableFaultBrakeInt (PWM_T *pwm, uint32_t u32BrakeSource)
426 {
427  PWM->PIER &= ~PWM_PIER_BRKIE_Msk;
428 }
429 
438 void PWM_ClearFaultBrakeIntFlag (PWM_T *pwm, uint32_t u32BrakeSource)
439 {
440  PWM->PIIR = u32BrakeSource;
441 }
442 
453 uint32_t PWM_GetFaultBrakeIntFlag (PWM_T *pwm, uint32_t u32BrakeSource)
454 {
455  return (PWM->PIIR & u32BrakeSource ? 1 : 0);
456 }
457 
468 void PWM_EnablePeriodInt (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType)
469 {
470  PWM->PIER = (PWM->PIER & ~PWM_PIER_INT_TYPE_Msk) | (PWM_PIER_PWMPIE0_Msk << u32ChannelNum) | u32IntPeriodType;
471 }
472 
479 void PWM_DisablePeriodInt (PWM_T *pwm, uint32_t u32ChannelNum)
480 {
481  PWM->PIER &= ~(PWM_PIER_PWMPIE0_Msk << u32ChannelNum);
482 }
483 
490 void PWM_ClearPeriodIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
491 {
492  PWM->PIIR = (PWM_PIIR_PWMPIF0_Msk << u32ChannelNum);
493 }
494 
503 uint32_t PWM_GetPeriodIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
504 {
505  return(PWM->PIIR & (PWM_PIIR_PWMPIF0_Msk << u32ChannelNum) ? 1 : 0);
506 }
507 
508 
509  /* end of group MINI51_PWM_EXPORTED_FUNCTIONS */
511  /* end of group MINI51_PWM_Driver */
513  /* end of group MINI51_Device_Driver */
515 
516 /*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
#define PWM_PCR_CH0EN_Msk
#define PWM_CHANNEL_NUM
Definition: pwm.h:32
#define PWM_PIER_INT_TYPE_Msk
#define PWM_PFBCON_BKF_Msk
#define PWM_PFBCON_PWMBKO0_Pos
#define PWM_PIIR_PWMDIF0_Msk
uint32_t PWM_GetADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function get selected channel trigger ADC flag.
Definition: pwm.c:252
void PWM_ClearFaultBrakeFlag(PWM_T *pwm, uint32_t u32BrakeSource)
This function clear fault brake flag.
Definition: pwm.c:300
void PWM_EnableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration)
This function enable Dead zone of selected channel.
Definition: pwm.c:337
void PWM_ClearDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function clears duty interrupt flag of selected channel.
Definition: pwm.c:390
#define PWM_DZIR_DZI01_Msk
void PWM_DisableDeadZone(PWM_T *pwm, uint32_t u32ChannelNum)
This function disable Dead zone of selected channel.
Definition: pwm.c:353
#define PWM_PPR_CP01_Msk
#define PWM_TRIGGER_ADC_CNTR_IS_CMR_U
Definition: pwm.h:43
Mini51 series peripheral access layer header file. This file contains all the peripheral register's d...
void PWM_ForceStop(PWM_T *pwm, uint32_t u32ChannelMask)
This function stop PWM generation immediately by clear channel enable bit.
Definition: pwm.c:151
void PWM_EnableOutput(PWM_T *pwm, uint32_t u32ChannelMask)
This function enables PWM output generation of selected channels.
Definition: pwm.c:312
void PWM_DisableOutput(PWM_T *pwm, uint32_t u32ChannelMask)
This function disables PWM output generation of selected channels.
Definition: pwm.c:324
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
#define PWM_PCR_CH0MOD_Msk
void PWM_ClearFaultBrakeIntFlag(PWM_T *pwm, uint32_t u32BrakeSource)
This function clear fault brake interrupt of selected source.
Definition: pwm.c:438
void PWM_EnableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType)
This function enable duty interrupt of selected channel.
Definition: pwm.c:368
#define PWM_TRIGGER_ADC_CNTR_IS_CNR
Definition: pwm.h:42
#define PWM_TRIGGER_ADC_CNTR_IS_CMR_D
Definition: pwm.h:41
#define PWM_PIER_PWMPIE0_Msk
#define PWM_PCR_PWMTYPE_Msk
void PWM_EnableFaultBrake(PWM_T *pwm, uint32_t u32ChannelMask, uint32_t u32LevelMask, uint32_t u32BrakeSource)
This function enable fault brake of selected channels.
Definition: pwm.c:285
void PWM_ClearADCTriggerFlag(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
This function clear selected channel trigger ADC flag.
Definition: pwm.c:230
#define PWM_PIER_PWMDIE0_Msk
void PWM_EnablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType)
This function enable period interrupt of selected channel.
Definition: pwm.c:468
void PWM_DisableFaultBrakeInt(PWM_T *pwm, uint32_t u32BrakeSource)
This function disable fault brake interrupt.
Definition: pwm.c:425
void PWM_EnableFaultBrakeInt(PWM_T *pwm, uint32_t u32BrakeSource)
This function enable fault brake interrupt.
Definition: pwm.c:414
#define PWM_PCR_DZEN01_Msk
#define PWM_PIER_BRKIE_Msk
#define PWM
Pointer to PWM register structure.
void PWM_DisablePeriodInt(PWM_T *pwm, uint32_t u32ChannelNum)
This function disable period interrupt of selected channel.
Definition: pwm.c:479
void PWM_Start(PWM_T *pwm, uint32_t u32ChannelMask)
This function start PWM module.
Definition: pwm.c:110
#define PWM_PIIR_PWMPIF0_Msk
void PWM_Stop(PWM_T *pwm, uint32_t u32ChannelMask)
This function stop PWM module.
Definition: pwm.c:131
void PWM_ClearPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function clear period interrupt of selected channel.
Definition: pwm.c:490
#define PWM_CSR_CSR0_Msk
uint32_t PWM_GetDutyIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function get duty interrupt flag of selected channel.
Definition: pwm.c:403
void PWM_EnableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
This function enable selected channel to trigger ADC.
Definition: pwm.c:176
void PWM_DisableDutyInt(PWM_T *pwm, uint32_t u32ChannelNum)
This function disable duty interrupt of selected channel.
Definition: pwm.c:379
#define PWM_TRIGGER_ADC_CNTR_IS_0
Definition: pwm.h:40
uint32_t SystemCoreClock
uint32_t PWM_GetFaultBrakeIntFlag(PWM_T *pwm, uint32_t u32BrakeSource)
This function get fault brake interrupt of selected source.
Definition: pwm.c:453
void PWM_DisableADCTrigger(PWM_T *pwm, uint32_t u32ChannelNum)
This function disable selected channel to trigger ADC.
Definition: pwm.c:201
uint32_t PWM_GetPeriodIntFlag(PWM_T *pwm, uint32_t u32ChannelNum)
This function get period interrupt of selected channel.
Definition: pwm.c:503