Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

dsPIC30F4011

Status
Not open for further replies.
dsPIC30F4011 Not Seeming To Do Anything

Hey guys. Im working on some code for my midterm tomorrow. Basically, it has to find the duty cycle of an input clock and set the pwm duty cycle to that value.

Here's the code Im using:
Code:
#include <p30f4011.h>

int count = 0; // counts number of edges (if 1, if 2, if 3, etc)
float dutyCycle = 0; // holds calculated duty cycle value
float a = 0, b = 0, c = 0; // holds timer values at rise/fall

int main(void);
void __attribute__((__interrupt__)) _IC1Interrupt(void); // ic1 isr
void initIC1(void); // init ic1 stuff and set to capture on rising edge
void initPWM(void); // init pwm stuff
void setPWM(float); // set pwm1 duty register to freq
void delay(long); // delay for i cycles

int main(void)
{  
	//timer
	T3CON = 0x8000; // timer3 control register
	TMR3 = 0; // clear timer3 register
	PR3 = 0xFFFF;
	IPC1bits.T3IP = 5; // timer3 interrupt priority
	IEC0bits.T3IE = 1; // timer3 interrupt enable
	IFS0bits.T3IF = 0; // timer3 interrupt flag

	// pin cfg	
	TRISB = 0x00; // make port B all outputs
	TRISE = 0x00; // specifically make E0 an output
	ADPCFG = 0xFF; // disable ADC on portb

	initPWM(); // initialize pwm regs

	while(1) // loop
	{
		if (count == 0 && IEC0bits.IC1IE == 0) // if we're starting fresh 
			initIC1(); // 		   		(count = 0, and IC1 is off, enable IC1
		if (dutyCycle > 0)
			setPWM(dutyCycle); // set pwm freq to dutyCycle (updated in ISR)
		PORTB++; // inc portb (just to show activity)
		Nop();
		if (PORTB == 0xFF)
			PORTB = 0; // rollover at max
		delay(10000);
	}
	return 0;
}

void __attribute__((__interrupt__, __auto_psv__))_IC1Interrupt(void)
{
	if (count == 0)
	{
		a = IC1BUF; // store timer value in a
		IC1CON = 0x02; // change IC to store on falling edge
		count++; // increment count
	} 
	else if(count == 1)
	{
		b = IC1BUF; // store timer value in b
		IC1CON = 0x03; // change IC to store on rising edge
		count++; // increment count
	} 
	else if(count == 2)
	{
		c = IC1BUF; // store timer value in c
		count = 0; // reset count
		TMR3 = 0; // clear timer
		dutyCycle = ((b-a)/(c-a)) * 100; // calculate duty cycle
		IEC0bits.IC1IE = 0; // disable IC1
	}
	IFS0bits.IC1IF = 0; // clear interrupt flag
}

void initIC1(void)
{	
	IC1CON = 0x03; // change IC to store on every rising edge, tmr3 contents captured
	IEC0bits.IC1IE = 1; // enable IC1 interrupts
	IPC0bits.IC1IP = 7; // set IC1 priority
	IFS0bits.IC1IF = 0; // clear IC1 interrupt flag
}

void initPWM(void)
{
	PTPER = 1600;
	PWMCON1bits.PEN1L = 1; // enable pwm1L pin
	PWMCON1bits.PEN1H = 1; // enable pwm1H pin
	OVDCONbits.POVD1L = 1; // output on pwm1L controlled by pwm generator
	OVDCONbits.POVD1H = 1; // output on pwm1H controlled by pwm generator
	PTCONbits.PTEN = 1; // pwm time base is on
}

void setPWM(float freq)
{
	freq = freq * 4000; // multiply by 4000
	PWMCON2bits.UDIS = 1; // updates from duty cycle and period registers are disabled
	PDC1 = freq; // move frequency into pwm duty cycle register 1
	PWMCON2bits.UDIS = 0; // updates from duty cycle and period registers are enabled
}

void delay(long i)
{
	long abc;
	for(abc = 0; abc < i; abc++)
	{
		Nop(); // kill a cycle
	}		
}

Ive added PORTB++; to the main loop just so that I can see activity on the port (on an LED board - a board with a driver and leds to indicate the status of each bit), but when I program and take MCLR to Vdd, I get 0x01 on PORTB and it never increases. But in the sim, it works fine. What am I doing wrong?

Im using FRC w/ PLL x4 and the internal fast RC for a clock, a PICKit2, and MPLAB with the C30 compiler.

EDIT Also, if I load up the PICKit2 as a debugger, and animate, it works properly (or the LEDs count anyways - more than before). If I click Run though, the Output window shows:

Running Target
PICkit 2 Ready

Target Halted

and all the LEDs come on (indicating FF on portb)

EDIT 2 With this code, the LEDs count as I expect them to, so my hardware is correct at least

Code:
#include <p30f4011.h>

int main(void);
void delay(long i);

int main(void)
{
	TRISB = 0x00;
	ADPCFG = 0xFF;

	while(1)
	{
		PORTB++;
		if (PORTB == 0xFF)
			PORTB = 0;
		delay(10000);
	}
}

void delay(long i)
{
	long a;
	for (a = 0; a < i; a++)
	{
		Nop();
	}
}
 
Last edited:
Fixed my own problem. With these three lines:

IPC1bits.T3IP = 5; // timer3 interrupt priority
IEC0bits.T3IE = 1; // timer3 interrupt enable
IFS0bits.T3IF = 0; // timer3 interrupt flag

I was enabling an interrupt but I didnt have an ISR to handle it. Doh! Case closed.
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top