Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] mikroC PIC32MX150 PWM and PPS - can't start PWM

Status
Not open for further replies.

Alloy

Advanced Member level 4
Joined
Apr 3, 2016
Messages
116
Helped
0
Reputation
0
Reaction score
0
Trophy points
16
Activity points
1,003
Hey
I want to run PWM on PIC32MX.
I know that I must:
- select PPS (Peripheral Pin Select) for PWM
- setup PWM
I think I did that but it does not work, what have I missed?

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
unsigned int current_duty, old_duty, current_duty1, old_duty1;
unsigned int pwm_period1, pwm_period2;
 
void main() {
  JTAGEN_bit = 0;        // Disable JTAG
  /* ADC Digital Mode */
  ANSELA = 0;
  ANSELB = 0;
  TRISA = 0;             // Initialize PORTA as output
  TRISB = 0;             // Initialize PORTB as output
  LATA = 0;              // Set PORTA to zero
  LATB = 0;              // Set PORTB to zero
 
  Unlock_IOLOCK();
 
  PPS_Mapping(_RPA0, _OUTPUT, _C1OUT);
  PPS_Mapping(_RPA1, _OUTPUT, _C2OUT);
 
  Lock_IOLOCK();
  
  current_duty  = 100;                        // initial value for current_duty
  current_duty1 = 100;                        // initial value for current_duty1
 
  pwm_period1 = PWM_Init(5000 , 1, 1, 2);
  pwm_period2 = PWM_Init(10000, 2, 1, 3);
 
  PWM_Start(1);
  PWM_Start(2);
 
  PWM_Set_Duty(current_duty,  1);            // Set current duty for PWM1
  PWM_Set_Duty(current_duty1, 2);            // Set current duty for PWM2
 
 
  while(1) {
    Delay_ms(1);
    current_duty = current_duty + 5;       // increment current_duty
    if (current_duty > pwm_period1) {      // if we increase current_duty greater then possible pwm_period1 value
        current_duty = 0;                    // reset current_duty value to zero
    }
    PWM_Set_Duty(current_duty,  1);       // set newly acquired duty ratio
    current_duty1 = current_duty1 + 5;       // increment current_duty
    if (current_duty1 > pwm_period2) {      // if we increase current_duty greater then possible pwm_period1 value
        current_duty1 = 0;                    // reset current_duty value to zero
    }
    PWM_Set_Duty(current_duty1,  2);       // set newly acquired duty ratio
  }
}



PS: The blink LED code is working, I just can't get PWMs to work.
 

What makes you think it is not working?
Are you sure that the MCU is running at all?
Is this release or debug mode?
Also the default config setting for the IOLOCK bit is '0' which means that it is unlocked. Also the IOL1WAY config bit defauls to 1. Therefore 1: you don't need to unlock the PPS registers to start with - unlocked is the power on default setting; 2: if you don't alter the IOL1WAY config bit, then lockign them will lock them until the next power cycle an therefoer 3: until you have everything sorted and really knwo what you are doing then don't play with the IOLOCK bit.
But the answer is that you have the PPS mapping all wrong. You need to look at table 11-2 in the data sheet and also look at exactly what peripheral hardware is actually providing the PWM function. On that chip it is the Output Compare which means the output pins that need mapping are "OCx".
Also, you cannot just assign any function pin to any physical pin - you have to stick with the combinations available in Table 11-2. Even using your (incorrect) example, C1OUT cannot map to RPA0 - the nearest you could get is RPA3 and there are several alternatives in RPB and RPC.
Susan
 

Try this

Code:
AD1PCFG = 0xFFFFFFFF;

or

ADPCFG = 0xFFFFFFFF;
 

I don't fully get what you mean guys, but thanks for replies.
The solution was:

Code C - [expand]
1
PPS_Mapping(_RPA0, _OUTPUT, _C1OUT); // assign OC1 (PWM output) to pin RPA0


change to:

Code C - [expand]
1
PPS_Mapping(_RPA0, _OUTPUT, _OC1); // assign OC1 (PWM output) to pin RPA0





Try this

Code:
AD1PCFG = 0xFFFFFFFF;

or

ADPCFG = 0xFFFFFFFF;
both expressions are unknown to compiler, they do not compile.



Are you sure that I can't map to any PPS pin? I tought that's the idea of PPS to map to any pn.

Now, next question....
Why this dont work? It works with _RPA0, but not with _RPA1.

Code C - [expand]
1
PPS_Mapping(_RPA1, _OUTPUT, _OC1); // assign OC1 (PWM output) to pin RPA0

 

Last question first: for the very reason I mention in my previous reply. PPS can be implemented in any way that Microchip want to - there is absolutely no reason why they should allow mapping from any peripheral output to any physical pin. That is why they publish the table in the data sheet that tells you which combinations are valid.
In this case OC1 can be mapped to RPA0 but not RPA1(but OC2 can be!).
It just so happens that Microchip DO allow any peripheral output to be mapped to any pin in many of the other families of devices but NOT the PIC32MX1xx family.
@okada - you need to look at the data sheets as well. What you are suggesting is that the physical pins are still in 'analog' mode but the registers that control the mode for this family of devices are ANSELx. That is why the OP cannot compile the source that contains references to those registers - they do not exist in his device. However for output pins, being in analog mode won't stop them from being driven by the peripheral. It might be hard on the analog circuitry to be driven to one limit or the other but that is not generally a problem. On the other hand, trying to read a pin that is set to analog mode will result in it always reading as '0' - this is the cause of many a question about why my 'xyz' peripheral is not reading serial data (or whatever).
Susan
 

Ok I looked at the:
"TABLE 11-2: OUTPUT PIN SELECTION".
and kinda realized how it works.

So I can map OC2 to RPA1, you say?


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void main() {
  unsigned int current_duty, old_duty;
  unsigned int pwm_period;
  unsigned int current_duty2, old_duty2;
  unsigned int pwm_period2;
  JTAGEN_bit = 0;        // Disable JTAG
  /* ADC Digital Mode */
  ANSELA = 0;
  ANSELB = 0;
  TRISA = 0;             // Initialize PORTA as output
  TRISB = 0;             // Initialize PORTB as output
  LATA = 0;              // Set PORTA to zero
  LATB = 0;              // Set PORTB to zero
 
  Unlock_IOLOCK();
  PPS_Mapping(_RPA0, _OUTPUT, _OC1); // assign OC1 (PWM output) to pin RPA0
  PPS_Mapping(_RPA1, _OUTPUT, _OC2); // assign OC2 (PWM output) to pin RPA1
  Lock_IOLOCK();
  
  current_duty = 0;    // initial value for current_duty
  current_duty2 = 0;    // initial value for current_duty
  pwm_period = PWM_Init(5000 , 1, 1, 2);
  PWM_Start(1);
  pwm_period2 = PWM_Init(5000 , 2, 1, 2);
  PWM_Start(2);
 
 
  while(1) {
    PWM_Set_Duty(current_duty,  1);       // set newly acquired duty ratio
    PWM_Set_Duty(current_duty2,  2);       // set newly acquired duty ratio
    Delay_ms(1);
    current_duty = current_duty + 2;       // increment current_duty
    if (current_duty > pwm_period) {      // if we increase current_duty greater then possible pwm_period1 value
        current_duty = 0;                    // reset current_duty value to zero
    }
    current_duty2 = current_duty2 + 2;       // increment current_duty
    if (current_duty2 > pwm_period2) {      // if we increase current_duty greater then possible pwm_period1 value
        current_duty2 = 0;                    // reset current_duty value to zero
    }
  }
}


Then why such code does not work? I mean, only RPA0 is dimming.
 

I'm not sure I understnad what you mean by "...only RPA0 is dimming". Does that mean that the brightness of the LED on RPA0 is changing but the brightness of the LED on RPA1 is not? If so then try only enabling the PWM on RPA1 and see if that is working.
I really have no idea what the library functions are doing (this is the ever-present danger in using library functions, especially for controlling peripherals that are really very simple). I've done a quick Google for 'mikroc pwm_init' and looked at a link about the "PWM Library" (no idea if that is relevant or not) but I see that the last parameter says which timer to use (Timer2 or Timer3) and you have both calls to the function with Timer2. As I say, I have no idea what the functions actually do (and this might be important here - or not) but the use of the same timer might be causing interference between the two PWMs.
Susan
 

I will put it other way, beause I have tested more.


Code C - [expand]
1
2
PPS_Mapping(_RPA0, _OUTPUT, _OC1); // assign OC1 (PWM output) to pin RPA0
  PPS_Mapping(_RPA1, _OUTPUT, _OC2); // assign OC2 (PWM output) to pin RPA1


_RPA0 is dimming, RPA1 is dark (no PWM)

and if i change the order:

Code C - [expand]
1
2
PPS_Mapping(_RPA1, _OUTPUT, _OC2); // assign OC2 (PWM output) to pin RPA1
  PPS_Mapping(_RPA0, _OUTPUT, _OC1); // assign OC1 (PWM output) to pin RPA0


_RPA1 is dimming, RPA0 is dark (no PWM)

What's wrong? Only first mapping actually works... first call only.
 

Not sure but the thread at https://forum.mikroe.com/viewtopic.php?f=111&t=49990#p194807 might be relevant. This also goes back to my previous comment about the IOL1WAY bit - make sure that this is set to 0 in the CONFIG bits.
(If this is the problem then this is evern more reason why I hate library functions to do things that are basically very straight forward to do directly.)
Susan
PS - I found this with a simple Google search in less than 1 minute!!!!!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top