Continue to Site

# Advice for Pic c compiler

Status
Not open for further replies.

#### abdoalghareeb

##### Member level 4
What is the most reliable PIC compiler using C language ?
I have started with MIKROC compile (version 5.0), but I have some problems in time calculation .

#### Tahmid

Among the numerous compilers available, mikroC is quite a popular compiler. There is no single best compiler. It ultimately comes down to preference. I recommend mikroC but not everyone likes mikroC or feels comfortable using it.

Can you please explain what time calculation problems you are experiencing?

#### abdoalghareeb

##### Member level 4
I use PIC 18F452 , Mikroc compiler , winpic800 with serial JDM programmer

My simple program is about flashing LED on PORTA.B0 with frequency = 1 HZ .
My problem is : the output frequency is more than 1Hz

I use external crystal = 20 MHz
this is my code And my method of time calculation :

Code:
////////////////////////////////////////////////////////////////////////////
/////////   crystal friquncy = 20000000 Hz                         /////////
/////////                                                          /////////
/////////                      1                                   /////////
/////////   1 Sec = -------------------------  x (256-61) x 100    /////////
/////////                 (20MHz /4) / 256                         /////////
////////////////////////////////////////////////////////////////////////////

unsigned int count = 0;
//=============================================
//=============================================
void interrupt()
{
if (TMR0IF_bit)
{
TMR0IF_bit=0;
TMR0H=0;
TMR0L=61;
if (++count==100)
{
count=0;
PORTA.B0 ^= 1;
}
}
}
//==================================================
//==================================================
void main()
{
//--------------------
//--------------------
TRISA=0b11000000;
PORTA=0b00000000;
//--------------------
INTCON.GIE=1;
//--------------------
T0CON = 0b11000111;
INTCON.TMR0IE=1;
INTCON1.TMR0IP=1;
TMR0H=0;
TMR0L=61;
//--------------------
while(1)
{

}
}
//=============================================
//=============================================

#### Attachments

• 1.rar
328.9 KB · Views: 26

#### Tahmid

With your code, I get a time of 998.66ms (through simulation). What issue are you facing?

After a little modification, I used this code to get a time of 998.84ms:
Code:
////////////////////////////////////////////////////////////////////////////
/////////   crystal friquncy = 20000000 Hz                         /////////
/////////                                                          /////////
/////////                      1                                   /////////
/////////   1 Sec = -------------------------  x (256-61) x 100    /////////
/////////                 (20MHz /4) / 256                         /////////
////////////////////////////////////////////////////////////////////////////

unsigned int count = 0;
//=============================================
//=============================================
void interrupt()
{
if (TMR0IF_bit)
{
TMR0H=0;
if (++count==100)
{
count=0;
PORTA.B0 ^= 1;
}
TMR0IF_bit=0;
TMR0L=61;
}
}
//==================================================
//==================================================
void main()
{
//--------------------
//--------------------
TRISA=0b11000000;
PORTA=0b00000000;
//--------------------
SWDTEN_bit=0;
//--------------------
INTCON.GIE=1;
//--------------------
T0CON = 0b11000111;
INTCON.TMR0IE=1;
INTCON1.TMR0IP=1;
TMR0H=0;
TMR0L=61;
//--------------------
while(1)
{

}
}
//=============================================
//=============================================

I noticed you are using configuration setting of HS+PLL. What is the frequency of the oscillator are you using? If you are using a 20MHz crystal, then you should use just HS instead of HS+PLL.

Hope this helps.
Tahmid.

Last edited:

#### abdoalghareeb

##### Member level 4
Code:
////////////////////////////////////////////////////////////////////////////
/////////   crystal friquncy = 20000000 Hz                         /////////
/////////                                                          /////////
/////////                      1                                   /////////
/////////   1 Sec = -------------------------  x (256-61) x 100    /////////
/////////                 (20MHz /4) / 256                         /////////
////////////////////////////////////////////////////////////////////////////

unsigned int Sec_count = 0;
unsigned int Min_count = 0;
//=============================================
//=============================================
void interrupt()
{
if (TMR0IF_bit)
{
TMR0H=0;
if (++Sec_count==100)
{
Sec_count=0;
PORTA.B0 ^= 1;
if (++Min_count == 60)
{
Min_count=0;
PORTA.B1 ^= 1;
}
}
TMR0IF_bit=0;
TMR0L=61;
}
}
//==================================================
//==================================================
void main()
{
//--------------------
//--------------------
TRISA=0b11000000;
PORTA=0b00000000;
//--------------------
SWDTEN_bit=0;
//--------------------
INTCON.GIE=1;
//--------------------
T0CON = 0b11000111;
INTCON.TMR0IE=1;
INTCON1.TMR0IP=1;
TMR0H=0;
TMR0L=61;
//--------------------
while(1)
{

}
}
//=============================================

1- The oscillator configuration HS + PLL is the only one mode witch make the micro controller run

2- Your time calculation is correct and I use the same but the result was 0.38 Sec. because I make another led
blinking after one minute and it toggle after 23 Sec (on my JOVIAL watch)

3- What is simulation software do you use ?

#### betwixt

##### Super Moderator
Staff member
There is nothing wrong with the program and it should be fairly accurate in timing but there are a few things you could do to optimize it. One thing you miss is the execution time of the interrupt itself which adds to the delay but this makes it slower which is the opposite of what you see. I agree the PLL should not be used and you may be seeing a combination of effects due to the PLL and other software delays.

Hints:
1. Most compilers cannot optimize a statement like "if(++sec_count==100)", try to count a variable down to zero rather than up to a value. The reason is that a decrement and check for zero will compile to a single instruction.
For example you could use something like "if (sec_count--)" or even "sec_count--; if (sec_count)" and reload your 100 only when it has passed the 'if' check.

2. The timer runs continuously, even while you are inside the interrupt routine so reload it's value as soon as possible when you enter the routine or you add the length of the routine to the interval each time.

3. Reduce the code by using 'unsigned char' rather than 'int' for the counters, otherwise the PIC has to do more calculations when the upper half of the number is always zero anyway.

I'm using a different PIC and compiler but with similar code I get an accuracy of about 10 seconds per month.

Brian.

#### Tahmid

I simulated on Proteus.

What is the frequency of the crystal you are using?

#### abdoalghareeb

##### Member level 4
I use 20 MHz

Status
Not open for further replies.