|
|
View previous topic :: View next topic |
Author |
Message |
apakSeO
Joined: 07 Dec 2016 Posts: 60 Location: Northeast USA
|
PWM module override & control |
Posted: Thu Jul 11, 2019 9:13 am |
|
|
CCS Compiler v5.081
PIC16F1779
I have an application where I need the PWM module configured as polarity active low ( so that the module idles high )
As expected, using the code:
Code: |
/ ************************************************************************************* //
// ****************************** SETUP PWM12 MODULE *********************************** //
// ************************************************************************************* //
#pin_select PWM12OUT = PIN_D0 // Route PWM12OUT to RD0/Pin 34
// Set period register
// 8MHz = 125ns per clock tick
pwm12_period = 2000;
pwm12_phase = 0;
pwm12_duty_ultralow = 20; // 1% duty
pwm12_duty_low = 40; // 2% duty
pwm12_duty_med = 1000; // 50% duty
pwm12_duty_high = 2001; // Will this trigger anything? NO! This works wonderfully. Never triggers because compare never >= period
pwm12_offset = 0;
// Clock & control
PWM12CLKCON = 0x00; // No prescaler; clock source is Fosc
//PWM12CON = 0b00000000; // Standard PWM mode polarity active high; PWM not enabled
PWM12CON = 0b00010000; // Standard PWM mode; polarity active low; PWM not enabled
// Period control
PWM12LDA = 1; // Must be '1' for immediate effect
PWM12PRH = HIBYTE(pwm12_period);
PWM12PRL = LOBYTE(pwm12_period);
// Phase control
PWM12LDA = 1; // Must be '1' for immediate effect
PWM12PHH = HIBYTE(pwm12_phase);
PWM12PHL = LOBYTE(pwm12_phase);
PWM12LDA = 1;
PWM12OFH = HIBYTE(pwm12_offset);
PWM12OFL = LOBYTE(pwm12_offset);
// Duty control
PWM12LDA = 1; // Must be '1' for immediate effect
PWM12DCH = HIBYTE(pwm12_duty_ultralow);
PWM12DCL = LOBYTE(pwm12_duty_ultralow);
|
the PWM12 module is active low, and idles at high level when I disable the PWM12 output by clearing the associated PWMEN bits.
Since control of PIN_D0 is entirely up to the PWM module, subsequent calls to output_high(PIN_D0) or output_low(PIN_D0) do nothing; they have no effect. Presumably this is because the PPS circuitry routes control only to the PWM module and at that point the GPIO control is not routed.
Now, during a sleep mode, I must pull this pin low for lowest current consumption. Is there a way to do this, other than to reconfigure register PWM12CON for polarity active high ( so that module idles low ) ?
I've noticed similar issues when using forced-hardware SPI, but the issue manifests itself differently, or at least, in reverse. In the SPI case, if I try to output_high() or output_low() on a defined SPI pin, SPI stops working because calls to output_high() or output_low() route control away from the EUSART module toward the GPIO's, and the EUSART module ceases to function.
For example, I set up my SPI as follows:
Code: |
//*********************************************************************************************//
// *************************** SPI SETUP **************************************************//
//*********************************************************************************************//
// Map PPS pins to default locations. (There are no default locations on this PIC)
#pin_select SCK1=PIN_C3
#pin_select SDO1=PIN_C4
#pin_select SDI1=PIN_C2
// Hardware pins @ SPI1 already spec'd above EXCEPT CS/SS pin, which
// is setup below as the ENABLE= pin
#use spi(MASTER, SPI1, FORCE_HW, ENABLE=PIN_C1, ENABLE_ACTIVE=0, IDLE=1, BITS=16, SAMPLE_RISE, BAUD=500000, STREAM=spiCh1)
|
If I want to pull PIN_C4 low during a sleep operation, or affect the states of any of the defined pins for whatever reason the circuitry requires, I cannot do this without ruining the link between the EUSART and the defined pin.
Why do calls to output_high/low() affect some modules ( like the EUSART ) and then do not affect other modules ( like the PWM module above ) ? Is there any rhyme or reason to this varying behavior, is it an internal design decision based on each PIC family? Is this behavior documented in some way?
Finally, how do you handle juggling control between various modules in a PIC when awake, and being able to control individual pin states when the PIC is asleep, without ruining the links between modules and pins?
Thanks for reading |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Thu Jul 11, 2019 12:19 pm |
|
|
setup_pwm(things | PWM_INVERT, otherthings);
where 'things' and 'otherthings' are your other PWM settings.
The PWM_INVERT constant configures the PWM so it drives active low.
You can disconnect PPS using:
(in the code)
pin_select(PIN, NULL, TRUE, TRUE);
where PIN is the pin you are using. This connects the PPS output routing for
the pin to the 'NULL' device, which then allows normal I/O.
Then to reconnect:
pin_select(PIN, PWM12, TRUE, TRUE);
Connects the pin back to PWM12.
The need to disconnect, is actually down to the device in the PIC (read
data sheet). Some override the I/O functions when they are connected
to the pins, while others require the TRIS set in specific directions to work. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|