|
|
View previous topic :: View next topic |
Author |
Message |
halilemirhankara
Joined: 13 Dec 2024 Posts: 8
|
PIC16F1846 PWM GENERATION WITH SETUP_PWM1 |
Posted: Fri Dec 13, 2024 2:17 am |
|
|
Hi, this is my first post on the CCS forum. I tried to solve this problem on my own but reading datasheets or surfing the net didn't help me.
I am trying to generate PWM 50Hz through the PWM peripheral. However, there is no PWM output from the pins I selected. Below is my full code.
I always check the pins I use for PWM generation with an oscilloscope.
Things I tried:
- Setup timer 2
- Disable ccp, cwg
main.h
Code: | #ifndef MAIN_H
#define MAIN_H
#include <16F18146.h>
#include <stdint.h>
#fuses PUT_1MS, NOBROWNOUT, PROTECT
#use delay(internal=32MHz)
#define pwm_1 PIN_C6
#define pwm_2 PIN_A4
#pin_select PWM1S1P1 = pwm_1
#pin_select PWM1S1P2 = pwm_2
#endif |
main.c
Code: | #include <main.h>
void main() {
setup_pwm1(PWM_ENABLE | PWM_CLK_FOSC | PWM_CLK_DIV_BY_16);
setup_pwm1_slice(0, PWM_PUSH_PULL);
set_pwm1_period(10000);
set_pwm1_duty(0, 5000,0);
PWM1LD = 1;
PWM1EN = 1;
while (TRUE) {
}
}
|
I want to use that setup because I want to generate low frequency PWM with high mcu frequency.
Last edited by halilemirhankara on Sun Dec 15, 2024 10:32 pm; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Sat Dec 14, 2024 6:48 am |
|
|
I'm curious as to the application for 50Hz PWM.
If say for RC servo control, you may be able to use a slower PIC clock speed, if nothing else is 'time critical'.
Another option may be to just use delay(). While this dedicates the PIC to doing the inline delays. again it may work for you. |
|
|
halilemirhankara
Joined: 13 Dec 2024 Posts: 8
|
|
Posted: Sat Dec 14, 2024 7:47 am |
|
|
It is for a full-bridge driver.
I already got it working with other methods but I am curious about this one because with this method I can use 32 MHz mcu clock and 50 Hz PWM at the same time as I thought.
I also have more coding for this project. I have not added it yet.
And also I am trying to run the code this way because there will be other projects where I will use this method. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Sat Dec 14, 2024 8:13 am |
|
|
depending on what the bridge driver is driving, you may be able to speed up the PWM ?? |
|
|
halilemirhankara
Joined: 13 Dec 2024 Posts: 8
|
|
Posted: Sun Dec 15, 2024 1:35 am |
|
|
I tried increasing the PWM frequency, but that didn't work.
I also tried decreasing the frequency of the MCU, but that didn't work either. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Sun Dec 15, 2024 4:57 am |
|
|
Key is one error in your setup.
You are telling the PWM, to clock of Fosc, so off 32MHz.
32000000/16/10001 =199.98Hz. just under 4* what you want.
More, the internal prescaler only supports /1, /2, /4, or /8, so the compiler
will try to synthesise larger prescalers by extending the division factor
This will run out, before you get to 50Hz.
The minimum frequency that can be developed by the PWM on this chip
fed off 32MHz, is:
32000000/65536/8 = 61Hz.
Why for just use the internal oscillator?
setup_pwm1(PWM_ENABLE | PWM_CLK_MFINTOSC_500KHZ | PWM_CLK_DIV_BY_1);
Then a period of 9999, will give 50Hz.
Remember the division is by one more than the period factor selected. |
|
|
halilemirhankara
Joined: 13 Dec 2024 Posts: 8
|
|
Posted: Sun Dec 15, 2024 5:32 am |
|
|
Thank you for information. I will try it tomorrow and i will tell the results. |
|
|
Pubse2002
Joined: 06 May 2024 Posts: 2
|
|
Posted: Sun Dec 15, 2024 9:09 pm |
|
|
Welcome to the CCS forum! Generating PWM can be tricky, especially when you're setting up peripherals like timers and CCP modules. Here are a few suggestions that might help debug your issue:
Things to Check:
Timer Configuration:
Ensure Timer 2 is configured correctly. The frequency and period calculations for a 50Hz PWM signal need to align with your timer's clock source. Double-check your PR2 and prescaler settings.
CCP Configuration:
Make sure the CCP module is properly set to PWM mode and that the CCPxCON register is configured for the desired duty cycle and PWM operation.
Pin Selection:
Verify that the pins you've selected for PWM output support PWM functionality. Not all pins support PWM, even if they're part of the CCP module. Check your microcontroller's datasheet for PWM-capable pins.
Peripheral Pin Select (PPS):
If your microcontroller uses PPS (Peripheral Pin Select), ensure you've mapped the CCP output to the correct physical pin.
Pin Tristate Configuration:
Confirm that the TRIS register for your PWM pin is set to output (TRISx = 0).
Interrupts:
If you're using interrupts, ensure they're not interfering with the Timer or CCP module.
Debugging Steps:
Use the Oscilloscope: You've mentioned this already, which is great. Check if there's any activity on the selected pin when the PWM is enabled. If not, the issue might be in the configuration rather than hardware.
Test with Simple Code: Start with a minimal setup to ensure the Timer and PWM are working, and gradually build up to your full code.
Sample Checklist:
Check T2CON, PR2, and CCPRxL values.
Ensure CCPxCON is set to PWM mode (0b1100).
Ensure the PWM module is enabled by setting TMR2ON in the T2CON register.
Validate your PWM duty cycle calculations.
If you can share your code or specific register values, the community can offer more targeted advice! _________________ I strive to continuously improve the internal processes of my business, recently implemented the OKR App and it helped improve business performance. |
|
|
halilemirhankara
Joined: 13 Dec 2024 Posts: 8
|
|
Posted: Sun Dec 15, 2024 10:35 pm |
|
|
Ttelmah wrote: | Key is one error in your setup.
You are telling the PWM, to clock of Fosc, so off 32MHz.
32000000/16/10001 =199.98Hz. just under 4* what you want.
More, the internal prescaler only supports /1, /2, /4, or /8, so the compiler
will try to synthesise larger prescalers by extending the division factor
This will run out, before you get to 50Hz.
The minimum frequency that can be developed by the PWM on this chip
fed off 32MHz, is:
32000000/65536/8 = 61Hz.
Why for just use the internal oscillator?
setup_pwm1(PWM_ENABLE | PWM_CLK_MFINTOSC_500KHZ | PWM_CLK_DIV_BY_1);
Then a period of 9999, will give 50Hz.
Remember the division is by one more than the period factor selected. |
I tried what you say but it didn't work. I can't get PWM. |
|
|
halilemirhankara
Joined: 13 Dec 2024 Posts: 8
|
|
Posted: Sun Dec 15, 2024 10:39 pm |
|
|
Pubse2002 wrote: | Welcome to the CCS forum! Generating PWM can be tricky, especially when you're setting up peripherals like timers and CCP modules. Here are a few suggestions that might help debug your issue:
Things to Check:
Timer Configuration:
Ensure Timer 2 is configured correctly. The frequency and period calculations for a 50Hz PWM signal need to align with your timer's clock source. Double-check your PR2 and prescaler settings.
CCP Configuration:
Make sure the CCP module is properly set to PWM mode and that the CCPxCON register is configured for the desired duty cycle and PWM operation.
Pin Selection:
Verify that the pins you've selected for PWM output support PWM functionality. Not all pins support PWM, even if they're part of the CCP module. Check your microcontroller's datasheet for PWM-capable pins.
Peripheral Pin Select (PPS):
If your microcontroller uses PPS (Peripheral Pin Select), ensure you've mapped the CCP output to the correct physical pin.
Pin Tristate Configuration:
Confirm that the TRIS register for your PWM pin is set to output (TRISx = 0).
Interrupts:
If you're using interrupts, ensure they're not interfering with the Timer or CCP module.
Debugging Steps:
Use the Oscilloscope: You've mentioned this already, which is great. Check if there's any activity on the selected pin when the PWM is enabled. If not, the issue might be in the configuration rather than hardware.
Test with Simple Code: Start with a minimal setup to ensure the Timer and PWM are working, and gradually build up to your full code.
Sample Checklist:
Check T2CON, PR2, and CCPRxL values.
Ensure CCPxCON is set to PWM mode (0b1100).
Ensure the PWM module is enabled by setting TMR2ON in the T2CON register.
Validate your PWM duty cycle calculations.
If you can share your code or specific register values, the community can offer more targeted advice! |
I have tried this before. I can get PWM with this method, but I want to get PWM with the PWM peripheral. I'm just wondering why I can't get any output with this peripheral. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Dec 16, 2024 1:56 am |
|
|
Big question.
What compiler version?????
This is vital, since some compiler version do not correctly setup options
like the MFINTOSC source.
Two comments. Get rid of PROTECT, till you have the code working. Having
this set, uses up lives on the chip pointlessly when doing development.
Add NOPPS1WAY. If I remember correctly, this chip uses a separate
operation for both selects, so will refuse to do the second one unless this
fuse is turned off.
Get rid of the slice options in your duty settings. The 0 as the first entry
in this will be disabling the PWM.
So:
set_pwm1_duty(5000);
The slice number value is 1 to 4...... |
|
|
halilemirhankara
Joined: 13 Dec 2024 Posts: 8
|
|
Posted: Mon Dec 16, 2024 7:02 am |
|
|
Ttelmah wrote: | Big question.
What compiler version?????
This is vital, since some compiler version do not correctly setup options
like the MFINTOSC source.
Two comments. Get rid of PROTECT, till you have the code working. Having
this set, uses up lives on the chip pointlessly when doing development.
Add NOPPS1WAY. If I remember correctly, this chip uses a separate
operation for both selects, so will refuse to do the second one unless this
fuse is turned off.
Get rid of the slice options in your duty settings. The 0 as the first entry
in this will be disabling the PWM.
So:
set_pwm1_duty(5000);
The slice number value is 1 to 4...... |
Thank you for your comment. My compiler version is 5.113. I tried another code from a friend's computer with version 5.118 compiler, it was not working because it was compiled with 5.113 on my computer before, but now it works because it is compiled with my friend's version 5.118. I think the compiler version has a big importance. I also noticed that there are differences in 16f18146.h files. The code is available below.
With the following code, I get 50 Hz PWM frequency and 32 MHz MCU clock frequency.
Code: | void main() {
setup_timer_2(T2_DIV_BY_64 | T2_CLK_MFINTRC_500KHZ, 155, 1);
setup_ccp1(CCP_PWM | CCP_USE_TIMER1_AND_TIMER2);
set_pwm1_duty(78);
setup_cwg(CWG_ENABLED | CWG_MODE_HALF_BRIDGE | CWG_INPUT_CCP1, CWG_NO_AUTO_SHUTDOWN, 0, 0);
while (TRUE) {
}
} |
Now I am trying to generate PWM with PWM peripheral instead of timer 2, add dead time with cwg and run it. Because I will need timer 2 for other applications. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Dec 16, 2024 7:21 am |
|
|
Good.
I think it was 5.115, that fixed the setups for your chip. I realised you had
not said the version, and that there was a problem a while back.
Obviously you can use the slice option, but it does need to be 1...4, not 0!...
Glad you have it working now. |
|
|
halilemirhankara
Joined: 13 Dec 2024 Posts: 8
|
|
Posted: Mon Dec 16, 2024 11:43 pm |
|
|
I finally got all the methods working. There is all example code below for 50 Hz square complementary wave. You can adjust the dead time with 3 code examples.
These codes work with compiler version 5.115 or over!!!
CCP-CWG Peripherals
Code: |
#include <16F18146.h>
#fuses PUT_1MS, NOBROWNOUT, NOPPS1WAY //PROTECT
#use delay(internal=32MHz)
#define pwm_1 PIN_C6
#define pwm_2 PIN_A4
#pin_select CWG1OUTA = pwm_2
#pin_select CWG1OUTB = pwm_1
void main() {
setup_timer_2(T2_DIV_BY_64 | T2_CLK_MFINTRC_500KHZ, 155, 1);
setup_ccp1(CCP_PWM | CCP_USE_TIMER1_AND_TIMER2);
set_pwm1_duty(78);
setup_cwg(CWG_ENABLED | CWG_MODE_HALF_BRIDGE | CWG_INPUT_CCP1, CWG_NO_AUTO_SHUTDOWN, 0, 0);
while (TRUE) {
}
}
|
PWM Peripheral
Code: |
#include <16F18146.h>
#fuses PUT_1MS, NOBROWNOUT, NOPPS1WAY //PROTECT
#use delay(internal=32MHz)
#define pwm_1 PIN_C6
#define pwm_2 PIN_A4
#pin_select PWM1S1P1 = pwm_1
#pin_select PWM1S1P2 = pwm_2
void main() {
setup_pwm1(PWM_ENABLE | PWM_CLK_MFINTOSC_500KHZ | PWM_CLK_DIV_BY_1);
setup_pwm1_slice(1, PWM_STANDARD | PWM_SLICE_P1_OUTPUT_ACTIVE_HIGH | PWM_SLICE_P2_OUTPUT_ACTIVE_LOW);
set_pwm1_period(9999);
set_pwm1_duty(1, 5000, 5000);
PWM1LD = 1;
PWM1EN = 1;
while (TRUE) {
}
}
|
PWM-CWG Peripheral
Code: |
#include <16F18146.h>
#fuses PUT_1MS, NOBROWNOUT, NOPPS1WAY //PROTECT
#use delay(internal=32MHz)
#define pwm_1 PIN_C6
#define pwm_2 PIN_A4
#pin_select CWG1OUTA = pwm_2
#pin_select CWG1OUTB = pwm_1
void main() {
setup_pwm1(PWM_ENABLE | PWM_CLK_MFINTOSC_500KHZ | PWM_CLK_DIV_BY_1);
set_pwm1_period(9999);
set_pwm1_duty(1, 5000);
PWM1LD = 1;
PWM1EN = 1;
setup_cwg(CWG_ENABLED | CWG_MODE_HALF_BRIDGE | CWG_INPUT_PWM1S1P1, CWG_NO_AUTO_SHUTDOWN, 2, 2);
while (TRUE) {
}
}
|
|
|
|
|
|
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
|