12259 views|14 replies

6

Posts

0

Resources
The OP
 

There is a problem with the PWM waveform generated by the PIC microcontroller [Copy link]

 
This post was last edited by Sevenfee on 2018-11-6 20:32 Using PIC16F887 microcontroller to generate square wave, when I set the square wave frequency to 4KHz, the waveform is normal. When I change the frequency division value of TIMER2 from 4 to 16, the frequency should become 1KHz. At this time, the frequency is correct, but the waveform becomes very strange. I would like to ask for guidance from experienced experts! This is the normal waveform of 4KHZ, with a duty cycle of 50% [attach]385942 [/attach] This is a problematic waveform of 1KHZ, with a duty cycle of 60%. This high level will suddenly drop to a relatively low level and then rise again. 1KHz duty cycle 80% is normal

微信图片_20181105201023.jpg (180.56 KB, downloads: 0)

微信图片_20181105201023.jpg
This post is from MCU

Latest reply

I use the PIC16F677 microcontroller and use the PWM output of the TMR2 timer. The functional requirement is that the positive duty cycle is 100uS, and the frequency can be adjusted from 1k to 3k. Then I use timer 1 for 10ms timing, and process it in the interrupt service function. Directly change the value of PR2 to achieve frequency adjustment. In the main function, operate PSTRCONbits.STRB = 1; T2CONbits.TMR2ON = 1; to turn on the PWM output, and use PSTRCONbits.STRB = 0; T2CONbits.TMR2ON = 0; to turn off the PWM output. Then, when the PWM waveform is output, there will be a continuous low level of 1.3ms without output, as shown in the oscilloscope picture. /// ... In timer 1 operation, enter the interrupt service function once every 10ms unsigned char pr2num; unsigned char setp_num = 1; unsigned char PWM_FREQL = 249; //1Khz low frequency assignment unsigned char PWM_FREQH = 60; //3.5kHZ 3521hz high frequency assignment void TMR1_Initialize(void) { T1CON = 0x00; //T1 clock is not divided by fosc/4 formula 65536-(X/4) TMR1H = 0x00; //1S timing initial value 0 TMR1L = 0x00; PIE1bits.TMR1IE = 1; PIR1bits.TMR1IF = 0; INTCONbits.PEIE = 0; //Peripheral interrupt disabled } void TMR1_ISR (void) //Not used { TMR1H = 0xF6;//10ms TMR1L = 0x3C; flag_tick_count++; if(PWMOUT_on == 1) //If PWMOUT_on = 1 in the main function, the PWM output will be turned on and the change from 1k-3.3k will be PR2-decrease+ { if(PWMOUT_up_dowm == 0) { pr2num -= setp_num; if (pr2num <= PWM_FREQH) { PWMOUT_up_dowm = 1; } } else { pr2num += setp_num; if(pr2num >= PWM_FREQL) { PWMOUT_up_dowm = 0; } } PR2 = pr2num; } } /// ... if(pwm_start == 1)// PWM is on pwm_start =1, off =0 { if(PWMOUT_on == 0) { PWMOUT_on = 1; TMR2 = 0 ; pr2num= PWM_FREQL; PSTRCONbits.STRB = 1; T2CONbits.TMR2ON = 1; } } else { if(PWMOUT_on == 1) { PWMOUT_on = 0; TMR2 = 0; pr2num= PWM_FREQL; Here, PR2 is assigned an initial value to stop output, and PSTRCONbits.STRB = 0; T2CONbits.TMR2ON = 0; } }   Details Published on 2020-4-2 16:51
 

6

Posts

0

Resources
2
 
I've also posted the main program for you to take a look at /********Port initialization function********/ void init() { ANSELH=0x00; //Set port B as digital I/O portOPTION_REG=0x00; WPUB=0xFF; //Set port B weak pull-upINTCON=0x00; //Disable general interruptPIE1=0; //PIE1 interrupt disablePIE2=0; //PIE2 interrupt disableTRISB0=1; TRISB1=1; //Set RB1 as input port, press buttonTRISB2=1; //Set RB2 as input port, press buttonTRISB3=1; TRISB4=1; RC1=0; TRISC1=0; //Pulse width modulation output pin, set to output} /********PWM initialization function********/ void PWM_Init() { PR2=249; //The period of the pulse width modulation waveform is 1000us CCP2CON=0x0C; //CCP2 module works in PWM mode, the lower two bits of duty factor are 00 T2CON=0x02; //Disable TMR2, and the pre- and post-division value is 16, and start outputting PWM CCPR2L=0xB8; //Initial value of duty cycle of PWM waveform} /********Keyboard scanning function******* */ void keyscan() { if(RB1==0) //If RB1 key is pressed{ delay_ms(5); //Delay debounceif(RB1==0) //Confirm whether a key is pressed{ while(!RB1); //Wait for key release CCP2CON=0x0C; CCPR2L=0xB8; //80% duty cycle TMR2ON=1; } } if(RB2==0) //If RB2 key is pressed{ delay_ms(5); //Delay debounceif(RB2==0) //Confirm whether a key is pressed{ while(!RB2); //Wait for key release CCP2CON=0x0C; CCPR2L=0x96; //60% duty cycle TMR2ON=1; } } if(RB0==0) //If the RB0 key is pressed { delay_ms(5); //Delay de-bounce if(RB0==0) //Confirm whether a key is pressed { while(!RB0); //Wait for the key to be released CCP2CON=0x00; //Turn off PWM TMR2ON=0; //Disable TMR2 //delay_ms(5); RC1=0; } } } /********Main function********/ void main() { init(); //System initialization PWM_Init(); //Pulse width initialization while(1) { keyscan(); //Call key scan to process pulse width factor } }
This post is from MCU
 
 

578

Posts

0

Resources
3
 
It may be the jitter that occurs when switching the duty cycle.
This post is from MCU
 
Personal signature刻苦学习,共同进步
 
 

360

Posts

0

Resources
4
 
Does it have anything to do with keeping dogs?
This post is from MCU
 
 
 

5216

Posts

239

Resources
5
 
Help you call the moderator @dingzy_2002
This post is from MCU
Add and join groups EEWorld service account EEWorld subscription account Automotive development circle
 
 
 

637

Posts

2

Resources
6
 
The PWM output settings of PIC8-bit ordinary microcontrollers are indeed different from other 8-bit microcontrollers, and I have also taken similar detours. The main thing is to strictly follow the settings in the data sheet: Especially during initialization In addition, if you change the PWM cycle frequency, resolution, etc., you must also follow the settings in the above figure. If you have determined the PWM cycle frequency and resolution, and only want to change the point-to-space ratio, you only need to modify CCPR1L, and don't change the CCP1CON value at the same time, which will cause unnecessary exceptions.
This post is from MCU

Comments

I just tried not to modify CCP2ON, and the waveform still showed abnormality as shown in the figure  Details Published on 2018-11-6 20:15
 
 
 

637

Posts

2

Resources
7
 
In addition, if you turn off PWM and then turn it on again, you also need to set the initialization as shown in the previous figure. So, if you want to temporarily make PWM have no output (PWM still needs to work), just set CCPR1L=0 You don't need to initialize PWM again. (This is not good for low power consumption, because the PWM module is always working. Under low power consumption requirements, it can only be turned off and then initialized and turned on ).
This post is from MCU
 
 
 

637

Posts

2

Resources
8
 
This post was last edited by dingzy_2002 on 2018-11-6 11:37 Here is my example (based on PIC12F615): 1. Initialization part: //PWM: CCP1CON = 0x0C; //Normal PWM mode, CCP1 output high level is valid CCPR1L = (PWM_MAX); ... //Pin direction setting: TRISIO = 0b00001011; // PIE1=WPUA=IOCA =0; PR2 = (PWM_MAX-1); //2MHz/125=16kHz, when the post-division is 4, the interrupt frequency is 4KHz ... PIR1 = 0x00; PIE1 = 0x00; TMR2IE = 1; TMR2ON = 1; INTCON = 0xC0; //Turn on external, T2 interrupt... 2. Modify the point-to-duty ratio in the program (continuous adjustment): DA_TEMP=CCPR1L; if(I_AVE>Iset_value) { if(--DA_TEMP>=(PWM_MAX)) DA_TEMP = 0x00; } if(I_AVE=(PWM_MAX)) DA_TEMP = (PWM_MAX); } CCPR1L =DA_TEMP;


This post is from MCU
 
 
 

6

Posts

0

Resources
9
 
dingzy_2002 posted on 2018-11-6 11:36 Give me my example program (based on PIC12F615): 1. Initialization part: //PWM: CCP1CON = 0x0C; //Pu...
Thanks for the moderator's answer. Now my problem is that after I select a frequency, 80% duty cycle may be a normal waveform. When I adjust the duty cycle to 60%, the level will drop and then rise in the figure. I think there should be no problem with the main body of the program. Today I changed a 4MHZ crystal oscillator and re-edited several waveforms, and the result is still like this. Different duty cycles at the same frequency may cause the waveform to be messy. The problem is still not solved: Cry:
This post is from MCU
 
 
 

6

Posts

0

Resources
10
 
Posted by Mayer Fengsui on 2018-11-5 23:56 It may be the jitter that occurs when switching the duty cycle
At the same frequency, 80% duty cycle can get a normal waveform, 60% duty cycle will produce the same error as the above picture, it should not be caused by jitter. I changed a crystal oscillator today, and the result is still the same.  
This post is from MCU
 
 
 

6

Posts

0

Resources
11
 
dingzy_2002 posted on 2018-11-6 11:27 The PWM output settings of PIC8-bit ordinary microcontrollers are indeed different from those of other 8-bit microcontrollers, and I have also taken similar detours. The main thing is to be strict...
I just tried not to modify CCP2ON, and the waveform still showed abnormalities as shown in the figure
This post is from MCU
 
 
 

637

Posts

2

Resources
12
 
Then check whether there are other programs affecting PWM output, such as interrupts, pin operations, etc.
This post is from MCU
 
 
 

2

Posts

0

Resources
13
 
dingzy_2002 posted on 2018-11-6 11:36 Give me a routine (based on PIC12F615): 1. Initialization part: //PWM: CCP1CON = 0x0C; //Pu...

Can't I just change the PR2 register? If I stop PWM output and assign an initial value to PR2, why does the PWM output follow the frequency when it is stopped?

This post is from MCU

Comments

1. Generally, PR2 is used to set the PWM period/frequency. Under normal circumstances, the frequency range is determined according to the application requirements. Do not make any changes. 2. If PR2 is modified alone, the PWM period will change greatly and the resolution will be insufficient.  Details Published on 2020-4-2 12:50
 
 
 

637

Posts

2

Resources
14
 
DonaldH posted on 2020-4-1 10:54 Can't I just change the PR2 register? If I stop the PWM output and assign an initial value to PR2, why does the PWM output when I turn it on again follow the frequency when it was stopped?

1. Generally, PR2 is used to set the PWM period/frequency. Under normal circumstances, the frequency range is determined according to the application requirements; it is not changed.

2. Modifying PR2 alone will cause a large change in the PWM period and insufficient resolution.

This post is from MCU
 
 
 

2

Posts

0

Resources
15
 
dingzy_2002 posted on 2020-4-2 12:50 1. Generally, PR2 sets the PWM period/frequency. Under normal circumstances, this is determined according to the application requirements. The frequency range is not changed. 2. Separate...

I use the PIC16F677 microcontroller and
use the PWM output of the TMR2 timer. The functional requirement is that the positive duty cycle is 100uS, and the frequency can be adjusted from 1k to 3k. Then I use timer 1 for 10ms timing, and process it in the interrupt service function. Directly change the value of PR2 to achieve frequency adjustment. In the main function, operate PSTRCONbits.STRB = 1; T2CONbits.TMR2ON = 1; to turn on the PWM output, and use PSTRCONbits.STRB = 0; T2CONbits.TMR2ON = 0; to turn off the PWM output.

Then, when the PWM waveform is output, there will be a continuous low level of 1.3ms without output, as shown in the oscilloscope picture.

///
...















In timer 1 operation, enter the interrupt service function once every 10ms
unsigned char pr2num;
unsigned char setp_num = 1;
unsigned char PWM_FREQL = 249; //1Khz low frequency assignment
unsigned char PWM_FREQH = 60; //3.5kHZ 3521hz high frequency assignment

void TMR1_Initialize(void)
{
T1CON = 0x00; //T1 clock is not divided by fosc/4 formula 65536-(X/4)
TMR1H = 0x00; //1S timing initial value 0
TMR1L = 0x00;

PIE1bits.TMR1IE = 1;
PIR1bits.TMR1IF = 0;
INTCONbits.PEIE = 0; //Peripheral interrupt disabled
}
void TMR1_ISR (void) //Not used
{
TMR1H = 0xF6;//10ms
TMR1L = 0x3C;
flag_tick_count++;

if(PWMOUT_on == 1) //If PWMOUT_on = 1 in the main function, the PWM output will be turned on and the change from 1k-3.3k will be PR2-decrease+
{
if(PWMOUT_up_dowm == 0)
{
pr2num -= setp_num;
if (pr2num <= PWM_FREQH)
{ PWMOUT_up_dowm
= 1;
}
}
else
{
pr2num += setp_num;
if(pr2num >= PWM_FREQL)
{
PWMOUT_up_dowm = 0;
}
}
PR2 = pr2num;
}
}

/// ...

if(pwm_start == 1)// PWM is on pwm_start =1, off =0
{
if(PWMOUT_on == 0)
{
PWMOUT_on = 1;
TMR2 = 0 ;
pr2num= PWM_FREQL;
PSTRCONbits.STRB = 1;
T2CONbits.TMR2ON = 1;
}
}
else
{
if(PWMOUT_on == 1)
{
PWMOUT_on = 0;
TMR2 = 0;
pr2num= PWM_FREQL; Here, PR2 is assigned an initial value to stop output, and
PSTRCONbits.STRB = 0;
T2CONbits.TMR2ON = 0;
}
}

PWM.jpg (535.28 KB, downloads: 0)

PWM.jpg
This post is from MCU
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list