chipKIT® Development Platform

Inspired by Arduino™

Toggle a i/o pin max speed using timer interupt on UNO32

Created Thu, 19 Apr 2012 08:15:40 +0000 by Mr Quincy


Mr Quincy

Thu, 19 Apr 2012 08:15:40 +0000

Hey, I'm trying to toggle a i/o pin on my UNO32 at 10MHz. I've been searching everywhere but I just can't toggle my pin over 400kHz. The UNO32 stats that it can go up to 80MHz so it should easily meet my required 10MHz. I'm pretty sure my clock speed settings are wrong but yeah i just can't find a way to alter it so it goes to 10MHz. SOMEONE HELP ME!!!

The following is my code, i've played a lot with this code but yeah at current, the pin toggles at 400KHz but i want 10MHz. THANK YOU in advance

#include <plib.h> #define SYS_FREQ (80000000)

void setup() { SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); T1CON = 0x0; // Stop the Timer and Reset Control register // Set prescaler at 1:1, internal clock source TMR1 = 0x0; // Clear timer register PR1 = 0x0001; // Load period register IPC1SET = 0x000C; // Set priority level=3 IPC1SET = 0x0001; // Set subpriority level=1 IFS0CLR = 0x0010; // Clear Timer interrupt status flag IEC0SET = 0x0010; // Enable Timer interrupts T1CONSET = 0x8000; // Start Time }

void loop(){}

extern "C" { void __ISR(_TIMER_1_VECTOR,ipl3) pwmOn(void) { digitalWrite( 13, ( digitalRead( 13 )^1 ) );
mT1ClearIntFlag(); // Clear interrupt flag } }


Mr Quincy

Sat, 21 Apr 2012 07:27:32 +0000

Anyone reading this, don't worry i found out the reason why to toggle speed was slow

The reason was because of ' digitalWrite( 13, ( digitalRead( 13 )^1 ) ); '

Ps i was using Mpide to program the UNO32, anywho, the digitalwrite and digitalread is a Mpide built in function, in order to use it, it'll significantly slow down the speed. thus why my toggle speed was slow.

in the end it'll be faster to use a C code direct from the pic32mxxxxxx something they toggle the pin

i used.... ' LATGSET = 0x40; ' and LATGSET = 0x00; ' and looped the 2,

for further more info go to http://www.hownottoengineer.com/reviews/chipkit-road-test.html

sorry for the bad english =]


pito

Sun, 22 Apr 2012 15:39:13 +0000

You may toggle the i/o pin max speed when the code is written in assembler, and no loop is used.. Do not expect digitalWrite() be fast ;)


gregcotten

Sun, 22 Apr 2012 17:33:09 +0000

HELP! This is SO CLOSE to what I am trying to do but a little different...

I need to interrupt every 20ms - I realize I might need an external crystal for this. Any thoughts?

Thanks, Greg


Mr Quincy

Sun, 22 Apr 2012 21:32:00 +0000

I havn't completely mastered interupts yet but i believe by changing the value of

PR1 = 0x0001;

to what you need in order for 20ms would do it. i know there is a formula u can use to calculate the exact value but i don't know it just yet. if u find out the formula plz reply back with it. for more info i recommend you read a book called "Newnes.Programming.32-bit.Microcontrollers.in.C.Exploring.the.PIC32" it really does help if u're fairly new to pic32 coding.

like i said i'm not too sure about this cause i havn't tested it myself cause i'm pretty busy with my other uni work

There is another option, and thats to use delays but i honestly don't recommend it unless whatever it is that you're trying to code is VERY simple and doesn't require SUPER accurate timing

Good luck and god speed


gregcotten

Mon, 23 Apr 2012 20:55:04 +0000

Took a look at the second post here: http://www.microchip.com/forums/m66033-print.aspx

And did some of my own calculations. To find the tick period I did this:

[( (timeInSeconds = how often you want the interrupt called)*(Clock Frequency = 80000000) ) / (PreScale = 256)] - 1

For me I wanted the interrupt every 20ms so I used .02 as timeInSeconds. I ended up with 6249. Can anyone explain the - 1 in the equation? The only reason I use it is because the guy on the other forum says to use it.

NOTE: I put the interrupt to priority 1. Not sure if that is kosher. SECOND NOTE: You can stop the timer by calling CloseTimer1();

long start;
volatile long counter = 0;

void setup()
{
	Serial.begin(1000000);
	OpenTimer1(T1_ON | T1_PS_1_256 | T1_SOURCE_INT, 6249);
	ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_1);
	INTEnableSystemMultiVectoredInt();
        WriteTimer1(0);
        start = millis();
}


void loop()
{
	if(millis() - start &gt; 1000){
		Serial.println(counter, DEC);
		start = millis();
		counter =0;
	}
	
}


extern "C"
{
	
	void __ISR(_TIMER_1_VECTOR,ipl1) pwmOn(void)
	{
		counter++;
		mT1ClearIntFlag(); // Clear interrupt flag
	}
	
	
}

Ryan K

Fri, 27 Apr 2012 00:24:22 +0000

Hello,

I'm pretty sure that the -1 in the equation has to do with the fact that the timer counter starts a 0. so that with a PR of 6249 you get a match every 6250 cycles of the prescaled clock.

80000000MHz / (256 * 6250) = 50 Hz (trigger for the interrupt)

As far as interrupt priority, you should be fine with a priority level of 1. You just have to be careful when using multiple interrupts and possibly with something running in the background. I remember using FreeRTOS on the PIC and since I didn't realize that FreeRTOS uses interrupts in the background, I had no idea why some of my interrupts weren't getting entered. I personally default to either 6 or 7 level priorities but unless you see weird behavior in your program I don't see any immediate reasons to change it.

Best Regards, Ryan K Digilent