(31 intermediate revisions by the same user not shown)
Line 10: Line 10:
 
*16 bit Capture Register
 
*16 bit Capture Register
 
*16 bit Compare Register
 
*16 bit Compare Register
*10-bit PWM Regsietrs .
+
*10-bit PWM Register.
  
 
In this tutorial we will be discussing only the PWM part of CCP. PIC has 2PWM module with a resolution of 10-bits.
 
In this tutorial we will be discussing only the PWM part of CCP. PIC has 2PWM module with a resolution of 10-bits.
Line 18: Line 18:
 
{| class="table table-striped table-hover table-condensed table-bordered"
 
{| class="table table-striped table-hover table-condensed table-bordered"
 
|-class="info"
 
|-class="info"
!PWM Channel || Port Pin ||  Control Register || Duty Cycle Register
+
!PWM Channel || Port Pin ||  Control Register || Duty Cycle Register || Period Register
 
|-
 
|-
|PWM1|| PC.2  || CCP1CON || CCPR1L
+
|PWM1|| PC.2  || CCP1CON || CCPR1L || PR2
 
|-
 
|-
|PWM2|| PC.1  || CCP2CON || CCPR2L
+
|PWM2|| PC.1  || CCP2CON || CCPR2L || PR2
|}<br><br><br><br><br><br>
+
|}<br><br>
  
=LPC7168 PWM Registers=
 
The below table shows the registers associated with LPC1768 PWM.<br>
 
{| class="table table-striped table-hover table-condensed table-bordered"
 
|-class="info"
 
!Register || Description
 
|-
 
|IR|| Interrupt Register: The IR can be read to identify which of eight possible interrupt sources are pending. Writing Logic-1 will clear the corresponding interrupt.
 
|-class="active"
 
|TCR|| Timer Control Register: The TCR is used to control the Timer Counter functions(enable/disable/reset).
 
|-
 
|TC|| Timer Counter: The 32-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR.
 
|-class="active"
 
|PR|| Prescalar Register: This is used to specify the Prescalar value for incrementing the TC.
 
|-
 
|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.
 
|-class="active"
 
|MCR|| Match Control Register: The MCR is used to control the reseting of TC and generating of interrupt whenever a Match occurs.
 
|-
 
|MR0|| Match Register: This register hold the max cycle Time(Ton+Toff).
 
|-class="active"
 
|MR1-MR6|| Match Registers: These registers holds the Match value(PWM Duty) for corresponding PWM channels(PWM1-PWM6).
 
|-
 
|PCR|| PWM Control Register: PWM Control Register. Enables PWM outputs and selects PWM channel types as either single edge or double edge controlled.
 
|-class="active"
 
|LER|| Load Enable Register: Enables use of new PWM values once the match occurs.
 
|}
 
<br><br><br><br>
 
  
 +
=PWM Working=
  
=Register Configuration=
+
Before going to the PIC PWM module lets understand few terminologies wrt below image:<br><br>
The below table shows the registers associated with LPC1768 PWM.<br>
+
[[FILE:Pwm.png]]
{| class="table table-striped table-hover table-condensed table-bordered"
+
|-class="info"
+
!TCR
+
|-
+
|31:4|| 3 || 2|| 1 || 0
+
|-class="active"
+
|Reserved|| PWM Enable || Reserved || Counter Reset || Counter Enable
+
|}
+
  
'''Bit 0 – Counter Enable'''<br>
+
<b>Ton:</b> Time for which the signal is ON/HIGH.<br>
This bit is used to Enable or Disable the PWM Timer and PWM Prescalar Counters<br>
+
<b>Toff:</b> Time for which the signal is OFF/LOW.<br>
0- Disable the Counters<br>
+
<b> Period:</b>  The cycle time of the signal which is nothing but the sum of Ton and Toff period.<br>
1- Enable the Counter incrementing.
+
Period= Ton+Toff<br>
 +
Freq of Pwm signal = 1/Period.<br>
  
'''Bit 1 – Counter reset'''<br>
+
<b>Duty Cycle:</b> The percentage of time for which the PWM signal will be ON/HIGH.
This bit is used to clear the PWM Timer and PWM Prescalar Counter values.<br>
+
$$DutyCycle = (Ton/(Ton+Toff))*100 = (Ton/Period) * 100 $$
0- Do not Clear.<br>
+
<br><br>
1- The PWM Timer Counter and the PWM Prescale Counter are synchronously reset on the next positive edge of PCLK.
+
 
+
'''Bit 3 – PWM Enable'''<br> 
+
Used to Enable or Disable the PWM Block.<br>
+
0- PWM Disabled<br>
+
1- PWM Enabled
+
<br><br><br>
+
  
  
{| class="table table-striped table-hover table-condensed table-bordered"
+
Below diagram shows the PIC16f877a PWM block diagram and output signal generation.
|-class="info"
+
[[FILE:Pic16f877a_Pwm.png]]<br>
!MCR
+
|-
+
|31:21||20||19||18||-||5||4||3||2||1||0
+
|-class="active"
+
|Reserved||PWMMR6S||PWMMR6R||PWMMR6I||-||PWMMR1S||PWMMR1R||PWMMR1I||PWMMR0S||PWMMR0R||PWMMR0I
+
|}
+
  
'''PWMMRxI'''<br>
+
PIC uses TIMER2 for generating the PWM signals. Lets relate the above concepts with the PIC registers.<br>
This bit is used to Enable or Disable the PWM interrupts when the PWMTC matches PWMMRx (x:0-6)<br>
+
<b>Period:</b>PR2 register is used to specify the PWM Period. The PWM period can be calculated using the following formula.
0- Disable the PWM Match interrupt<br>
+
$$PWM Period = [(PR2) + 1] * 4 * TOSC * (TMR2 Prescale Value)$$
1- Enable the PWM Match interrupt.
+
  
'''PWMMRxR'''<br>
+
<b>DutyCycle:</b>CCPR1L and CCP1CON<5:4> are used to specify the DutyCycle.The CCPR1L contains the eight MSbs and the CCP1CON<5:4> contains the two LSbs.
This bit is used to Reset PWMTC whenever it Matches PWMRx(x:0-6)<br>
+
0- Do not Clear.<br>
+
1- Reset the PWMTC counter value whenever it matches PWMRx.
+
 
+
'''PWMMRxS'''<br> 
+
This bit is used to Stop the PWMTC,PWMPC whenever the PWMTC matches PWMMRx(x:0-6).<br>
+
0- Disable the PWM stop o match feature<br>
+
1- Enable the PWM Stop feature. This will stop the PWM whenever the PWMTC reaches the Match register value.
+
<br><br><br>
+
  
 +
<b>PWM Signal Generation:</b> Once the PWM is configured and Timer2 is enabled, TMR2 starts incrementing depending on the prescalar.
 +
Once the <b>TMR2</b> value is equal to dutyCycle<b>(CCPR1L+CCP1CON<5:4>)</b> the PWM pin will be pulled LOW. The timer still continues to increment till it matches with the period <b>PR2</b>. After which the PWM pin will be pulled HIGH and TMR2 is reset for next cycle.
 +
<br><br><br><br>
  
 +
=PIC16F877A PWM Registers=
 +
The below table shows the registers associated with PIC16F877A PWM.<br>
 
{| class="table table-striped table-hover table-condensed table-bordered"
 
{| class="table table-striped table-hover table-condensed table-bordered"
 
|-class="info"
 
|-class="info"
!PCR
+
!Register || Description
 
|-
 
|-
|31:15||     14-9    ||   8-7  ||        6-2         ||1-0
+
|CCPxCON|| This register is used to Configure the CCP module for Capture/Compare/PWM opertaion.
|-class="active"
+
|-  
|Unused||PWMENA6-PWMENA1||Unused||PWMSEL6-PWMSEL2||Unused
+
|CCPRxL|| This register holds the 8-Msb bits of PWM, lower 2-bits will be part of CCPxCON register.
|}
+
|-
 
+
|TMR2|| Free running counter which will be compared with CCPR1L and PR2 for generating the PWM output.
'''PWMSELx'''<br>
+
|}<br><br>
This bit is used to select the single edged and double edge mode form PWMx (x:2-6)<br>
+
0- Single Edge mode for PWMx<br>
+
1- Double Edge Mode for PWMx.
+
 
+
'''PWMENAx'''<br>
+
This bit is used to enable/disable the PWM output for PWMx(x:1-6)<br>
+
0- PWMx Disable.<br>
+
1- PWMx Enabled.
+
<br><br><br>
+
 
+
  
 +
=Register Configuration=
 +
The below table shows the registers associated with PIC16f877a PWM.<br>
 
{| class="table table-striped table-hover table-condensed table-bordered"
 
{| class="table table-striped table-hover table-condensed table-bordered"
 
|-class="info"
 
|-class="info"
!LER
+
|CCPxCON
 
|-
 
|-
|31-7||6||5||4||3||2||1||0
+
|7 || 6 || 5 || 4 || 3 || 2 || 1 || 0
|-class="active"
+
|-
|Unused||LEN6||LEN5||LEN4||LEN3||LEN2||LEN1||LEN0
+
||| || CCPxX || CCPxY || CCPxM3 || CCPxM2 || CCPxM1 || CCPxM0
 
|}
 
|}
'''LENx'''<br>
 
This bit is used Enable/Disable the loading of new Match value whenever the PWMTC is reset(x:0-6)<br>
 
PWMTC will be continously incrementing whenever it reaches the PWMMRO, timer will be reset depeding on PWMTCR configuraion.
 
Once the Timer is reset the New Match values will be loaded from MR0-MR6 depending on bits set in this register.<br>
 
0- Disable the loading of new Match Values<br>
 
1- Load the new Match values from MRx when the timer is reset.
 
<br><br><br><br><br>
 
  
=PWM Working=
+
<b>CCPxX:CCPxY:</b>  PWM Least Significant bits<br>
After looking into the PWM registers, its time to see how the LPC1768 PWM module works.
+
These bits are the two LSbs of the PWM duty cycle. The eight MSbs are found in CCPRxL.
  
The TC is continuously incremented and once it matches the MR1(Duty Cycle) the PWM pin is pulled Low. TC still continues to increment and once it reaches the Cycle time(Ton+Toff) the PWM module does the following things:
+
<b>CCPxM3:CCPxM0:</b> CCPx Mode Select bits<br>
*Reset the TC value.
+
0000 - Capture/Compare/PWM disabled (resets CCPx module)<br>
*Pull the PWM pin High.
+
0100 - Capture mode, every falling edge<br>
*Loads the new Match register values.
+
0101 - Capture mode, every rising edge<br>
 
+
0110 - Capture mode, every 4th rising edge<br>
[[File:LPC1768_PWM.gif]]
+
0111 - Capture mode, every 16th rising edge<br>
<br><br>
+
1000 - Compare mode, set output on match (CCPxIF bit is set)<br>
 
+
1001 - Compare mode, clear output on match (CCPxIF bit is set)<br>
Summary of PWM operations for the above image:
+
1010 - Compare mode, generate software interrupt on match (CCPxIF bit is set, CCPx pin is unaffected)<br>
*Slide1: The TC is being incremented as per the Pre-scalar configuration. The PWM output is high as the TC is still less that duty cycle.
+
1011 - Compare mode, trigger special event (CCPxIF bit is set, CCPx pin is unaffected);<br>
*Slide2: TC is incremented to 40 and still the PWM pin as HIGH.
+
<b>11xx - PWM mode</b>
*Slide3: TC is incremented to 60 and it matches the Duty Cycle(MR1=60).
+
*Slide4: Now the Comparator1(Green) will trigger the R of SR latch and Pulls the PWM output to Zero(Q=0). TC still continues to increment.
+
*Slide5: TC is incremented to 80 and PWM pin is low as TC>Duty Cycle.
+
*Slide6: Now TC is 100 and it matches the Cycle time(MR0==100).
+
*Slide7: Now the Comparator2(Red) will trigger the S of SR latch and pulls the PWM output to ONE(Q==1). It also resets the TC to zero. It updates Shadow buffers with new Match values from MRO,MR1.
+
 
<br><br>
 
<br><br>
  
 
=Steps to Configure PWM=
 
=Steps to Configure PWM=
#Configure the GPIO pins for PWM operation in respective PINSEL register.  
+
#Configure the CCP1 module for PWM operation.
#Configure TCR to enable the Counter for incrementing the TC, and Enable the PWM block.
+
#Set the PWM period by writing to the PR2 register.
#Set the required pre-scalar value in PR. In our case it will be zero.
+
#Set the PWM duty cycle by writing to the CCPR1L register and CCP1CON<5:4> bits.
#Configure MCR to reset the TC whenever it matches MR0.
+
#Make the CCP1 pin an output by clearing the TRISC<2> bit.
#Update the Cycle time in MR0. In our case it will be 100.
+
#Set the TMR2 prescale value and enable Timer2 by writing to T2CON.
#Load the Duty cycles for required PWMx channels in respective match registers MRx(x: 1-6).
+
#Enable the bits in LER register to load and latch the new match values.
+
#Enable the required pwm channels in PCR register.
+
 
<br><br>
 
<br><br>
  
=Example=
+
=Code=
Program to demonstrates the variable PWM signal generation on PWM_1-PWM_4(P2_0 - P2_3).<br>
+
Program to demonstrates the LED fading using PWM signals.
Connect the Leds to the pins P2_0 to P2_3 and observe the led brigthness change depending on the dutycycle.
+
[[File:0_LPC1768_PWM.gif]]
+
 
<html>
 
<html>
<script src="https://gist.github.com/SaheblalBagwan/c721588560b77ad30396.js"></script>
+
<script src="https://gist.github.com/SaheblalBagwan/2d9ab8cbf840407b7248fef40fc56e21.js"></script>
 
</html>
 
</html>
<br><br><br>
+
<br>
 +
 
 +
 
 +
=Using ExploreEmbedded Libraries=
 +
Progarm to generate the PWM signals of 25% & 75% duty cycle using explore embedded libraries.
 +
<html>
 +
<script src="https://gist.github.com/SaheblalBagwan/5a49f953cd43f136fe954777c4373128.js"></script>
 +
</html>
 +
 
 +
Ouptut measured using CRO:
 +
[[FILE:PwmOutput.png]]
 +
<br><br>
 +
 
 +
=Downloads=
 +
Download the complete project folder from the below link:<br>
 +
[https://github.com/ExploreEmbedded/Pic16f877a_ExploreUltraPicDevKit/archive/master.zip Hardware design Files and Code Library]
 +
 
 +
 
 +
Have a opinion, suggestion , question or feedback about the article let it out here!
 +
{{DISQUS}}

Latest revision as of 13:02, 27 July 2016

In this tutorial we are going to discuss the PWM module of PIC16F877A.
First we will see how to configure the PWM registers to generate signals of required PWM, At the end we will see how to use the ExploreEmdedded PWM library.


0 LPC1768 PWM.gif

PIC16F877A PWM Module

PIC16F877A microcontroller has two independent CCP(Capture/Compare/PWM) modules, named as CCP1 and CCP2. Each CCP module has two 8-bit resistors(CCPxH,CCPxL) that can be use as:

  • 16 bit Capture Register
  • 16 bit Compare Register
  • 10-bit PWM Register.

In this tutorial we will be discussing only the PWM part of CCP. PIC has 2PWM module with a resolution of 10-bits. The 8-Msb bits are stored in CCPRxL and remeining 2-bits in CCPxCON register. Below tables shows the PWM module of PIC.

PWM Channel Port Pin Control Register Duty Cycle Register Period Register
PWM1 PC.2 CCP1CON CCPR1L PR2
PWM2 PC.1 CCP2CON CCPR2L PR2



PWM Working

Before going to the PIC PWM module lets understand few terminologies wrt below image:

Pwm.png

Ton: Time for which the signal is ON/HIGH.
Toff: Time for which the signal is OFF/LOW.
Period: The cycle time of the signal which is nothing but the sum of Ton and Toff period.
Period= Ton+Toff
Freq of Pwm signal = 1/Period.

Duty Cycle: The percentage of time for which the PWM signal will be ON/HIGH. $$DutyCycle = (Ton/(Ton+Toff))*100 = (Ton/Period) * 100 $$


Below diagram shows the PIC16f877a PWM block diagram and output signal generation. Pic16f877a Pwm.png

PIC uses TIMER2 for generating the PWM signals. Lets relate the above concepts with the PIC registers.
Period:PR2 register is used to specify the PWM Period. The PWM period can be calculated using the following formula. $$PWM Period = [(PR2) + 1] * 4 * TOSC * (TMR2 Prescale Value)$$

DutyCycle:CCPR1L and CCP1CON<5:4> are used to specify the DutyCycle.The CCPR1L contains the eight MSbs and the CCP1CON<5:4> contains the two LSbs.

PWM Signal Generation: Once the PWM is configured and Timer2 is enabled, TMR2 starts incrementing depending on the prescalar. Once the TMR2 value is equal to dutyCycle(CCPR1L+CCP1CON<5:4>) the PWM pin will be pulled LOW. The timer still continues to increment till it matches with the period PR2. After which the PWM pin will be pulled HIGH and TMR2 is reset for next cycle.



PIC16F877A PWM Registers

The below table shows the registers associated with PIC16F877A PWM.

Register Description
CCPxCON This register is used to Configure the CCP module for Capture/Compare/PWM opertaion.
CCPRxL This register holds the 8-Msb bits of PWM, lower 2-bits will be part of CCPxCON register.
TMR2 Free running counter which will be compared with CCPR1L and PR2 for generating the PWM output.


Register Configuration

The below table shows the registers associated with PIC16f877a PWM.

CCPxCON
7 6 5 4 3 2 1 0
CCPxX CCPxY CCPxM3 CCPxM2 CCPxM1 CCPxM0

CCPxX:CCPxY: PWM Least Significant bits
These bits are the two LSbs of the PWM duty cycle. The eight MSbs are found in CCPRxL.

CCPxM3:CCPxM0: CCPx Mode Select bits
0000 - Capture/Compare/PWM disabled (resets CCPx module)
0100 - Capture mode, every falling edge
0101 - Capture mode, every rising edge
0110 - Capture mode, every 4th rising edge
0111 - Capture mode, every 16th rising edge
1000 - Compare mode, set output on match (CCPxIF bit is set)
1001 - Compare mode, clear output on match (CCPxIF bit is set)
1010 - Compare mode, generate software interrupt on match (CCPxIF bit is set, CCPx pin is unaffected)
1011 - Compare mode, trigger special event (CCPxIF bit is set, CCPx pin is unaffected);
11xx - PWM mode

Steps to Configure PWM

  1. Configure the CCP1 module for PWM operation.
  2. Set the PWM period by writing to the PR2 register.
  3. Set the PWM duty cycle by writing to the CCPR1L register and CCP1CON<5:4> bits.
  4. Make the CCP1 pin an output by clearing the TRISC<2> bit.
  5. Set the TMR2 prescale value and enable Timer2 by writing to T2CON.



Code

Program to demonstrates the LED fading using PWM signals.


Using ExploreEmbedded Libraries

Progarm to generate the PWM signals of 25% & 75% duty cycle using explore embedded libraries.

Ouptut measured using CRO: PwmOutput.png

Downloads

Download the complete project folder from the below link:
Hardware design Files and Code Library


Have a opinion, suggestion , question or feedback about the article let it out here!