Pic24 pwm - Page 1
Forum section: electronics / general

author: meerweten
author_rank: Contributor
timestamp: March 26, 2014, 09:16:25 pm
content: i'm trying to get a pwm working on my pic24fj256bg106from what i understand i need to map this to a sertain RPn pin, but it seems thats not working for me (or i made a mistake somewhere else ofc)i can't find whats wrong with my coding (using mikroC pro for pic24, not mplab)Code:#define led LATE5_bitvoid InitMain() {//ADPCFG = 0xFFFF; // Configure AN pins as digital I/OTRISB = 0x0000; // configureall ports as OutputTRISD = 0x0000;TRISF = 0x0000;TRISG = 0x0000;TRISE = 0x0000;LATE5_bit = 0x00;//TRISC = 0x0000;Unlock_IOLOCK();PPS_Mapping_NoLock(0, _OUTPUT, _OC1); // Sets pin 0 to be OutputLock_IOLOCK();}int current_duty,maxi,chanel;void main() {InitMain();current_duty = 5000; //16 bit pwmchanel = 1;PWM_Init(100,chanel,0,0);PWM_Start(chanel); //Start pwm1maxi = 65536;PWM_Set_Duty(maxi, chanel); // Set current duty for PWM1while(1){while(current_duty < maxi){PWM_Set_Duty(current_duty,chanel);current_duty++;led = !led;delay_ms(100);}current_duty = 0;}}

author: dannyf
author_rank: Super Contributor
timestamp: March 26, 2014, 10:58:08 pm
content: QuoteReally? Where is the main loop?

author: lewis
author_rank: Frequent Contributor
timestamp: March 26, 2014, 11:06:39 pm
content: Quote from: dannyf on March 26, 2014, 10:58:08 pmWhy would you need a loop? And what would go in it?meerweten:Have a look in MikroC's help documentation (which is very good). You may need to call PWM1_Init(...) first:Code://this is from MikroC for PIC, I don't have the 16-bit version installed on this machine.//PIC24 should be similarvoid PWM1_Init(long freq);// For Enhanced Mid-Range Core 145x/150x MCUsvoid PWM1_Init(unsigned long PWM_Freq, unsigned int timer_prescaler);

author: senso
author_rank: Frequent Contributor
timestamp: March 26, 2014, 11:55:45 pm
content: Without a main loop the PC will just increase until it overflows and starts over at 0x0000, this is the best scenario assuming that an erased flash will contain what will be executed as nops, worst case, it will be random junk and you can't understand what the micro is doing.

author: miguelvp
author_rank: Super Contributor
timestamp: March 27, 2014, 12:29:36 am
content: Quote from: senso on March 26, 2014, 11:55:45 pmI hope the code that calls main doesn't allow that to happen. main will end and return to c0 or whatever it's nowadays and hopefully it puts the processor to sleep after returning from main.Edit: apparently on a PIC it doesn't go to sleep, it calls the main initialization (setting all the constant values etc) and then calls main, so it re-initializes and runs the code over and over including re-initializing the static variable values.

author: dannyf
author_rank: Super Contributor
timestamp: March 27, 2014, 12:56:03 am
content: QuoteNothing. Absolutely nothing.And that's the point of it.

author: miguelvp
author_rank: Super Contributor
timestamp: March 27, 2014, 01:17:49 am
content: end main on his compiler just loops forever when the end is reachedCode:L_end_main:0x002C 0xD7FF BRA $+0

author: lewis
author_rank: Frequent Contributor
timestamp: March 27, 2014, 09:04:40 am
content: Quote from: dannyf on March 27, 2014, 12:56:03 amIt doesn't take a vast leap of logic to realise the code the OP posted was a snippet. And yes, the compiler generates a 'goto $' equivalent at the end of main(). It does not overflow back to 0x00. We know this because if it did, that's a loop! And we haven't defined any loops in the C source.

author: hans
author_rank: Super Contributor
timestamp: March 27, 2014, 10:14:54 am
content: Just always place while(1) on your code. Heck, I even have programs with 2 while(1) loops, just in case the first fails.Some compilers may run through code memory (makes no sense). Sensible compilers will treat main() as any other function from the init code, and after main has ended (which it should never do btw), reset the software by jumping back to zero.Anyway, as per standard debugging on MCU's "this pin doesn't work":- Check your TRIS register settings (all outputs seems to be OK)- Check your analog functions (analog by default, overrides digital functons).- Check your re mappable I/O ( something like "PPS_Mapping_NoLock(0, _OUTPUT, _OC1);" makes no sense - where is the remappable pin number? Is it 0? Your comment says 5)- Check your timer/PWM configuration. (Did you initialize before start?)I don't have/use mikroC, so I don't know their library and how much it takes care of it's own, but I suspect you need to check your analog functions, PPS, and timer initialization.

author: meerweten
author_rank: Contributor
timestamp: March 27, 2014, 10:33:16 am
content: Quote from: hans on March 27, 2014, 10:14:54 amyes i forgot to change my comment back to 0

author: dannyf
author_rank: Super Contributor
timestamp: March 27, 2014, 12:25:56 pm
content: QuoteThis particular chip is part of the 1xx family that has DEDICATED timers to the OC (and IC) modules - this effectively has added 5 - 9 timers to the chip. Really nice.The pwm set-up is actually quite simple - if you follow the datasheet. You set up OCxCON1/2 - the key there is to select system clock and synchronize to itself, and then write to OCxR and OCxRS.

author: mazurov
author_rank: Frequent Contributor
timestamp: March 27, 2014, 03:56:13 pm
content: Pasted from the source I'm working on at the moment. Substitute serial with your function. To understand it better, take a look inside pps.h headerCode:#include "pps.h"...//Set serial console pinsPPSUnLock;PPSOutput( PPS_RP21, PPS_U2TX ); //hardcodedPPSInput( PPS_U2RX, PPS_RP26 ); //todo - make less crypticPPSLock;

author: meerweten
author_rank: Contributor
timestamp: March 28, 2014, 03:38:44 pm
content: so i added the main loop.added the pwm init i forgotbut still can't start the pwmtimer: sould be initialized by the pwm functionso for my own sake tried a simple blinking led and that worsk so the chip is def workingCode:#define led LATE5_bitvoid InitMain() {//ADPCFG = 0xFFFF; // Configure AN pins as digital I/OTRISB = 0x0000; // configureall ports as OutputTRISD = 0x0000;TRISF = 0x0000;TRISG = 0x0000;TRISE = 0x0000;LATE5_bit = 0x00;//TRISC = 0x0000;Unlock_IOLOCK();PPS_Mapping_NoLock(0, _OUTPUT, _OC1); // Sets pin 0 to be OutputLock_IOLOCK();}int current_duty,maxi,chanel;void main() {InitMain();current_duty = 5000; //16 bit pwmchanel = 1;PWM_Init(100,chanel,0,0);PWM_Start(chanel); //Start pwm1maxi = 65536;PWM_Set_Duty(maxi, chanel); // Set current duty for PWM1while(1){while(current_duty < maxi){PWM_Set_Duty(current_duty,chanel);current_duty++;led = !led;delay_ms(100);}current_duty = 0;}}

author: dannyf
author_rank: Super Contributor
timestamp: March 28, 2014, 08:01:41 pm
content: I think people can only offer limited help as it is unlikely that many people have the same set-up as yours. So I would suggest that you go through the compiler manual and / or sample code and make sure that they are as much "similar" as possible.Code:while(current_duty < maxi){PWM_Set_Duty(current_duty,chanel);current_duty++;led = !led;delay_ms(100);}current_duty = 0;Do you observe led's timing?That will at least tell you if the loop is running.

author: dannyf
author_rank: Super Contributor
timestamp: March 28, 2014, 08:05:01 pm
content: Also, you didn't specify the datatype for current_duty and maxi.With the wrong type,Code:maxi = 65536;makes zero sense and may cause the comparison to fail. Thus the importance to see if led's being flipped at the right frequency.Read a good C book for that.