[?] Subscribe To This Site

XML RSS
Add to Google
Add to My Yahoo!
Add to My MSN
Subscribe with Bloglines

Home
Forum
Project Ideas
C Course
Projects Showcase
LCD-KEYS OnePort
PIC Introduction
PIC Programmer
Schematic Tool
PIC Projects
Tips & Techniques
PIC Tutorials
Digital Downloads
Store
My SECRET
Oscilloscopes
About Me
Contact
Terms of Use
Search This Site
Freebies
Articles
Books
Resource Links
Site Map
Video du Jour
Rant/Rave
Privacy Policy
Problem?-Solution
Programmer Types

PIC16F628A : Using delays for PIC16F628A @ 4MHz

by Nicolae
(City)

Hi, I have a PIC16F628A set on internal clock (4MHz). I tried with an external 4MHz clock with the same result.

I use the compiler PICC-Lite from Hi_Tech. I intend to generate a 40kHz train of pulses for an ultrasonic application. Therefore I need a 25us period, which split in half gives 13us and 12us.

I tried using various methods, but each one seems to be worse than the other ones. First I tried using DelayUs(13) and Delay(12), which gives me a delay or about 18us and 13us. The code is extremely simple, all I have is:

main()
{
        TRISA = 0b00000000;
        TRISB = 0b00000000;
        PORTA = 0;
        PORTB = 0;
        PORTA = 0b00000000;
        while(1)
        {
                PORTA = 0b11111111;
                DelayUs(12); //takes 10us
                PORTA = 0b00000000;
                DelayUs(13); //takes 13us
        }
}

Now, the strange thing is about these delays:

If I set first delay to DelayUs(10), I get 5us of delay, for DelayUs(11), I get 10us, for DelayUs(12) I get 18us.


If I set the second delay to DelayUs(6 to 10), I get 13us. What is worse, the value set in one delay seems to affect both delays!

I tried using assembly i.e. asm("nop") - because I am within the while() loop. But when I have assembly in the code, the 12us delay takes about 300ms. I turned on all the optimisations I could find, but no luck.

For the delay, I got some code generated by http://www.piclist.com/cgi-bin/delay.exe

Delay
                        ;9 cycles
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        nop

                        ;4 cycles (including call)
        return

Unfortunately, I've been unable to embed it into my program - if I embed it, I get a delay hundreds of times longer than I expect!
Could you please explain how to embed the above code within a C project?

Regards,
Nicolae



Comments for
PIC16F628A : Using delays for PIC16F628A @ 4MHz

Click here to add your own comments

Nov 11, 2010
its like ..
by: alik

it şsnt good sample.I think you dont know any think.You must improve yourself .. Duty cycle must not always %50..I want to %1 and 3 and 5 and 7 ...

Oct 02, 2007
Use The Hardware Modules!
by: circuited

Do you intend to do anything else with your PIC while your sending 40KHz pulses? If so, your approach is wrong, since all your code is tied up doing software delays.

The 16F628A has a hardware module that will output various frequencies while you do other code processes. I recommend the CCP module which does PWM.

You can set up PWM for a variety of frequencies based on Timer2, its prescaler setting, and the PR2 compare register value. You would likely want 50% duty cycle and that can be set up in CCPR1L and CCPCON<5..4> bits.

Assuming a 4MHz oscillator, 40KHz at 50% duty cycle can be set up with these registers:

PR2 = 0x18 // load PR2 register
CCP1CON.5 = 1 // load for 50% duty cycle
CCP1CON.4 = 0
CCPR1L = 0x0C
T2CON = 0x01 // Timer2 Prescaler & Start
CCP1CON = 0x0C // enable PWM output
TRISB.3 // set PORTB.3 as output

PORTB, pin3 is the PWM output. You can easily turn off the output by CCP1CON = 0.

Refer to the datasheet for more information on this hardware feature.

Oct 01, 2007
PIC Microcontroller assembler delay fixes and debug
by: John Main

Hi Nicolae,

The way to solve these kinds of problems is always to go to the lowest level i.e. assembler so you need to generate the assembler code output - there is usually an option or it is generated in the same directory as the source.



When you do this you'll be able to see the exact code generated by the delayUs(12) functions etc. It sounds like this routine is no good for low delay values (you have to be very careful i.e. the compiler creators ;-) must be careful) when creating these types of functions. MikroC ones seem good but you should be able to sort it out using the assembler output. Note make a small change and compare the assembler outputs e.g. delayUs(13).



I don't know why you get 300ms but just looking at the assembler will help.



The delay routine you have won't work because the dollar sign is the current program counter position and is not usually available in embedded assembler (in C code). To get round it either create a new label for each statement and use goto label on each line or replace each goto with two nops (the delay uses goto as it is a jump and takes two instructon cycles so it is more efficient).



Note: loops take different amounts of time depending on whether they continue or exit.



See also the ultrasonic range finder on this site - the code does exactly as you are trying to do (with MikroC compiler though)



Best Regards John Main

Click here to add your own comments

Join in and write your own page! It's easy to do. How?
Simply click here to return to Ask for a Solution to your microcontroller problem