Hi guys...I'm a newbie in ARM7 programming.I have a readymade hardware board of LPC2148.I'm doing a simple blinking action on it.I'm supplying the processor with 12MHz frequency as its processor clock.And i hve read in net somewhere tht each for loop [for(x=0;x<1;x++)] takes 12-13 cycles to execute.So by rough calculation the value of the delay counter should be 1000000 for 1sec delay.But my delay turns out to be 4-5sec. I have deactivated the MAM block and also PLL0 i.e., I'm using the external supplied oscillator as the clock source for the processor. I havn't used the timer module to get the desired delay till now..as i need to brush up the theories behind it first.But whether it is absolutely necessary to use the timer block to produce the 1sec delay?? plz answer my post some one..thanks in advance.My code is given below --
#include "LPC214x.H" /* Fosc = external supplied crystal frequency Fcclk = Processor clock or o/p of PLL0 Pclk = The VPB clock frquency.The o/p of the VPB driver Fcco = the frequency of the PLL current controlled oscillator */ void init_clock() { /* PLL0CON = 0x03; // PLL0 is enabled & connected as the clock source of the microcontroller PLL0CFG = 0x24; // The i/p crystal oscillator frequency is multiplied in the PLL0 block by a fator of 5(=4+1) PLL0FEED == 0xAA; // 0xAA and 0x55 should be feed into this register for the PLL0FEED == 0x55; // changes in PLL0CON and PLL0CFG to take place actively VPBDIV = 0x01; // The Pclk frequency = Fcclk frequecy..not necessary. // by default the GPIO are selacted as legacy ports */ PLL0CON=0x0; // these 4 lins are as given by blink.c.Though the result is nt coming as expected.the above commented out result are my first try to supply the processor with 60MHz clock supply // the PLL is nt connected as the clock source for the processor PLL0FEED=0xAA; PLL0FEED=0x55; VPBDIV=0x00; MAMCR = 0x00; // Any MAM function is disabled..i.e } void delay() { unsigned long int i; for(i=0;i<250000;i++); } // with 12MHZ clock supply the time delay is cmng as 1sec if the delay value is 250000 but it should be 1000000 according to my calculation // in this void main(void) { unsigned long dword=0x00000000; unsigned char min_hand=0; init_clock(); PINSEL1 &= 0x00000000; // all the pins of port1 are selected as GPIO IODIR1 = 0x00FF0000; // the pin 16 to 23 are configuered as the o/p pins. IOCLR1 = 0xFFFFFFFF; while(1) { min_hand++; dword = dword>>16; dword++; dword = dword <<16; IOSET1 |= dword; // IOPIN1 = IOSET1; delay(); if(min_hand /60 == 0) { min_hand=0; delay(); } IOCLR1 = 0xFFFFFFFF; delay(); } }
Don't just believe eveything you read "in net"!
That statement might apply in some very specific situation but it is absolutely worthless as a general, unqualified statement!
See: www.8052.com/.../162556 And: www.8052.com/.../150987 And: www.8052.com/.../98544 etc...
It is a general principle of all high-level languages that you do not have precise control of the specific machine implementation - therefore, you you do not have precise control of the execution timing.
If you need such control, you must use assembler or some hardware means...
Time to brush up on the timers. They are not so hard to use, and you don't need to use interrupts - you can use them in polling mode too.
this is my next code that i tried..the code is self explanatory as i have documented it along side.The fact is its not working....I have tries to implement the timer0 block to count a 1sec delay while the supply is 12MHz as the Pclk..Hope u all will point out my fault..thanks in advance..
/* Clock cycle timing as described in the Datasheet is 40-100ns */ #include "LPC214x.H" /* clock part ta thik thak kaj krche na according to back calculation ja processor value dekhache tate kare processor clk i/p 6643963.0834673182341845067034648 HZ asche i.e., ~ 6.6MHz asche */ /* Fosc = external supplied crystal frequency Fcclk = Processor clock or o/p of PLL0 Pclk = The VPB clock frquency.The o/p of the VPB driver Fcco = the frequency of the PLL current controlled oscillator */ void init_clock() { PLL0CON=0x0; // the PLL is nt connected as the clock source for the processor PLL0FEED=0xAA; PLL0FEED=0x55; VPBDIV=0x00; MAMCR = 0x00; // Any MAM function is disabled..i.e } /* the prescaler register is set to have the value 9999(=0x270f),so that the TC register is incremented after every 10000 clock cycles.So it should count upto 1200(=0x4B0) for 1sec delay with 12MHz supply as the Pclk. */ void delay() { T0PR = 0x0000270F; T0MR0 = 0x000004B0 ; T0TCR = 0x01; // the timer0 is activated while(T0TC != T0MR0); T0MCR = 0x00000002; // Timer Counter will be in reset condition if the match between the MR0 and TC happens. T0TCR = 0x02; /* when the match happens the Timer0 is resetted and it is again activated while the next delay is called */ } // with 12MHZ clock supply the time delay is cmng as 1sec if the delay value is 250000 // in this void main(void) { unsigned long dword=0x00000000; unsigned char min_hand=0; init_clock(); PINSEL1 &= 0x00000000; // all the pins of port1 are selected as GPIO IODIR1 = 0x00FF0000; // the pin 16 to 23 are configuered as the o/p pins. IOCLR1 = 0xFFFFFFFF; while(1) { min_hand++; dword = dword>>16; dword++; dword = dword <<16; IOSET1 |= dword; // IOPIN1 = IOSET1; delay(); if(min_hand /60 == 0) { min_hand=0; delay(); } IOCLR1 = 0xFFFFFFFF; delay(); } } </prev>
Not sure I agree that your code is self-explanatory.
A variable named dword is a variable with a very bad name. It seems like some form of second ticks, but not limited to 0..59 as normal for a clock but instead emitting modulo 0..255.
Instead of a shift down + a shift up for the increment - store the value without a shift, and perform a shift in the output assign instead.
Modulo is not needed when your minute counter is only expected to count 0..59 and then restart. Instead just test:
if (++minutes >= 60) { minutes = 0; ... }
This is extra important when you have a processor without hardware divider.
Are your delay() function intended to generate a 1s delay, or is the intention that your program should tick with 1Hz? If the goal is to implement a clock, then you should not perform a 1s delay by constantly starting/stopping the timer. You should have the timer auto-reset but to continue to tick. Then your clock will not drift from the machine cycles consumed by the loop around the delay() call.
If you can't afford more than three characters for mentioning direction of a port pin, I would recommend that you use "out" instead of "o/p".
It is often advantageous to use english for all comments and variable names. A very large percentage of the worlds programmers are able to understand english comments or variable names.
I think you made the rounding of the year here ;) 6643963.0834673182341845067034648 HZ => ~ 6.6MHz
Note that no oscillator you will be able to buy would be even close to the precision of the first figure you wrote, except possibly for a very, very, very short time when drifting past that frequency ;)
But back to the real problem - exactly what happens, and what did you expect to happen? No delay at all? Too fast? Too slow? Hangs in the loop? Any thing else not as you expected?
First of all thank you sir for pointing the right way of posting a query and documenting it.I have done it clearly this time and hope that there will be no problem of understanding.I want to produce a simple blink and wait program where the waiting phase is for 1sec between each blink. I didn't want to use the timer block initially but later after seeing much postings in net i assume that it's impossible to create a 1sec delay without the timer0 block taking into action.So i rewritten the code and posted here..but the problem is after the first LED blinks..i.e., after 00000001,the state remains in that condition for 34 sec(almost) and as soon as the TC is matched with the MR0 value the next state it shows is 00001111 and the TC is resetted and the counting starts again.I havnt waited to see the next state..and i aborted the simulator.Now this is my problem...Plz help me thanx in advance. I'm posting the code again below....
<prev> /* Clock cycle timing as described in the Datasheet is 40-100ns */
/* My primary aim is to blink the LEDs connected to pin1.16-pin1.23 in a pattern 00000000,00000001,00000010... and so on with an interval of 1sec between each blinking.Thus measuring 60seconds i.e, 1min.*/ #include "LPC214x.H" /* Fosc = external supplied crystal frequency Fcclk = Processor clock or o/p of PLL0 Pclk = The VPB clock frquency.The o/p of the VPB driver Fcco = the frequency of the PLL current controlled oscillator */ void init_clock() {
PLL0CON=0x0; // the PLL is nt connected as the clock source for the processor PLL0FEED=0xAA; PLL0FEED=0x55; VPBDIV=0x01; // the VPB clock is same as that of the processor clock. MAMCR = 0x00; // Any MAM function is disabled..i.e }
/* This is the delay block where the timer0 register are configuered to count upto a certain value so that 1sec delay is produced.After each such case the timer block is deactivated and agin when the delay() function will be called it will be activated and configuered to produce 1sec delay.
the prescaler register is set to have the value 9999(=0x270F),so that the TC register is increased after every 10000 clock cycles.So it should count upto 1200(=0x4B0) for 1sec delay since the supply is 12MHz i.e., 12,000,000 clocks per second.Hence I have put the value 0x04B0 in MR0,which is compared with the TC and as soon as the match happens the Timer counter is being reset..and along with the timer block is deactivated. */ void delay() { T0PR = 0x0000270F; T0MR0 = 0x000004B0 ; T0TCR = 0x01; // the timer0 is activated while(T0TC != T0MR0); T0MCR = 0x00000002; // Timer Counter will be in reset condition if the match between the MR0 and TC happens.
T0TCR = 0x02; /* when the match happens the Timer0 is resetted and deactivated and it is again activated while the next delay is called */
} void main(void) { unsigned long dword=0x00000000; unsigned char min_hand=0; init_clock(); PINSEL1 &= 0x00000000; // all the pins of port1 are selected as GPIO IODIR1 = 0x00FF0000; // the pin 16 to 23 are configuered as the output pins. IOCLR1 = 0xFFFFFFFF; while(1) { min_hand++; dword = dword>>16; dword++; dword = dword <<16; IOSET1 |= dword; // IOPIN1 = IOSET1; delay(); if(min_hand /60 == 0) { min_hand=0; delay(); } IOCLR1 = 0xFFFFFFFF; delay(); }
} </prev>
the program---
/* Clock cycle timing as described in the Datasheet is 40-100ns */ /* My primary aim is to blink the LEDs connected to pin1.16-pin1.23 in a pattern 00000000,00000001,00000010... and so on with an interval of 1sec between each blinking.Thus measuring 60seconds i.e, 1min.*/ #include "LPC214x.H" /* Fosc = external supplied crystal frequency Fcclk = Processor clock or o/p of PLL0 Pclk = The VPB clock frquency.The o/p of the VPB driver Fcco = the frequency of the PLL current controlled oscillator */ void init_clock() { PLL0CON=0x0; // the PLL is nt connected as the clock source for the processor PLL0FEED=0xAA; PLL0FEED=0x55; VPBDIV=0x01; // the VPB clock is same as that of the processor clock. MAMCR = 0x00; // Any MAM function is disabled..i.e } /* This is the delay block where the timer0 register are configuered to count upto a certain value so that 1sec delay is produced.After each such case the timer block is deactivated and agin when the delay() function will be called it will be activated and configuered to produce 1sec delay. the prescaler register is set to have the value 9999(=0x270F),so that the TC register is increased after every 10000 clock cycles.So it should count upto 1200(=0x4B0) for 1sec delay since the supply is 12MHz i.e., 12,000,000 clocks per second.Hence I have put the value 0x04B0 in MR0,which is compared with the TC and as soon as the match happens the Timer counter is being reset..and along with the timer block is deactivated. */ void delay() { T0PR = 0x0000270F; T0MR0 = 0x000004B0 ; T0TCR = 0x01; // the timer0 is activated while(T0TC != T0MR0); T0MCR = 0x00000002; // Timer Counter will be in reset condition if the match between the MR0 and TC happens. T0TCR = 0x02; /* when the match happens the Timer0 is resetted and deactivated and it is again activated while the next delay is called */ } void main(void) { unsigned long dword=0x00000000; unsigned char min_hand=0; init_clock(); PINSEL1 &= 0x00000000; // all the pins of port1 are selected as GPIO IODIR1 = 0x00FF0000; // the pin 16 to 23 are configuered as the output pins. IOCLR1 = 0xFFFFFFFF; while(1) { min_hand++; dword = dword>>16; dword++; dword = dword <<16; IOSET1 |= dword; // IOPIN1 = IOSET1; delay(); if(min_hand /60 == 0) { min_hand=0; delay(); } IOCLR1 = 0xFFFFFFFF; delay(); } }
Simulator? Remember that the simulator may not run at 100% speed of the real hardware.
its ok...but in the hardware also its nt cmng 1sec delay as expected by me..its cmng much greater than 1sec..and onr thing that i forgot to mention in the last post is that i havn't incorporated any interrupt system here as i dont want the interrupt handling to run for creating a delay of 1sec...
VPBDIV or APBDIV
Please check the address of APB Divider
My LPC214x.h header file doesnt cntain APBDIV but it contains the VPBDIV and its defined in the header file as #define VPBDIV (*((volatile unsigned char *) 0xE01FC100))
I checked two user manuals, one for LPC21xx/22xx, one for LPC214x; the address for your VLSI Peripheral Bus Divider should be correct.
But I think that, you didn't properly configure your CCLK and PCLK.
Don't know what your startup code does, but the several versions of the void init_clock() you provided, look strange to me.
Please use the [Peripherals] menu of the KEIL IDE to confirm your CCLK/PCLK settings first.
i dont know why the void init_clock() is looking strange to you.I have disabled the PLL0 and have used the external 12MHz supplied frequency as the processor clock source i.e., the Fcclk.VPB clock(Pclk) is also adjusted to be equal to that of Fcclk.At the same time the MAM functional block is disabled...as I dont want the MAM action to be taken here.I'm more worried about producing a 1sec delay using the timer0 block.Plz check it and let me know the error as the time delay is coming much greater than 1sec..I'm cant post my start-up code here as the size is too long..but i assure u its the standard starp-up code that is available for ARM processors in keil.
You need to check your startup code to make sure how it configures your PLL0, FCCLK, CCLK, PCLK.
Your LPC2148 has two PLL.
Proper PLL handle procedure should look like the below:
void TargetResetInit(void) { #ifdef __DEBUG_RAM MEMMAP = 0x2; /* set remap register */ #endif #ifdef __DEBUG_FLASH MEMMAP = 0x1; /* set remap register */ #endif #ifdef __IN_CHIP MEMMAP = 0x1; /* set remap register */ #endif /* Set system timers for each component */ PLLCON = 1; #if (Fpclk / (Fcclk / 4)) == 1 VPBDIV = 0; #endif #if (Fpclk / (Fcclk / 4)) == 2 VPBDIV = 2; #endif #if (Fpclk / (Fcclk / 4)) == 4 VPBDIV = 1; #endif #if (Fcco / Fcclk) == 2 PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5); #endif #if (Fcco / Fcclk) == 4 PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5); #endif #if (Fcco / Fcclk) == 8 PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5); #endif #if (Fcco / Fcclk) == 16 PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5); #endif PLLFEED = 0xaa; PLLFEED = 0x55; while((PLLSTAT & (1 << 10)) == 0); PLLCON = 3; PLLFEED = 0xaa; PLLFEED = 0x55; /* Set memory accelerater module*/ MAMCR = 0; #if Fcclk < 20000000 MAMTIM = 1; #else #if Fcclk < 40000000 MAMTIM = 2; #else MAMTIM = 3; #endif #endif MAMCR = 2; /* Add your codes here */ return; }
thanks to ur sir....I dont want to activate the PLL0 block as i want to use the frquency of the external crystal oscillator so i dont find any justification for all those calculation involving the Fcclk.Moreover I want to equate the processor clock and the VPB clock hence i have set VPBDIV =1. I have checked the PLL0 system block while simulating the code...and its coming as i have configuered.The PLL0 block gets deactivated and the processor clock is 12MHz just as the external crystal frequency.
Next thing is that i dont find any justification to activate the MAM block so i deactivate it and that is also evident during the simulator that it is deactivated..I'm facing problem mainly i the timer0 block..as its nt giving a 1sec delay..but what it should give according to the value loaded to PR,TC and MR0 registers by me....plz comment on this..