?
Solved

how insert a delay in microseconds in C under  VC++

Posted on 2003-03-19
24
Medium Priority
?
32,914 Views
Last Modified: 2011-08-18
Hi experts,

I'm lookiing for a function that allow me to insert delays in Microseconds. I tried Sleep but it's not possible. i didn't test yet the clock() function to do that.
thanks in advance
Said
0
Comment
Question by:saido
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 6
  • 5
  • +3
24 Comments
 
LVL 4

Expert Comment

by:n_fortynine
ID: 8167857
sleep() does do this in milliseconds does it?
(for UNIX) #include <unistd.h>)
for Visual and MFC stuff I know of the default
::sleep() function that does the same trick.
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 8167860
::Sleep() my bad
0
 
LVL 22

Expert Comment

by:nietod
ID: 8167916
What sort of accuracy do you need?   Remeber that windows is a pre-emptive multitasking OS.  Accuracy can be very ellusive as you are sharing CPU time with dozens of other processes.   What exactly are you doing that you might want this?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:Salte
ID: 8167940
Yes, I believe ::Sleep() sleep in milliseconds.

You can also use select():

struct tv time;
time.tv_sec = num_seconds_to_sleep;
time.tv_usec = num_microseconds_to_sleep;

select(NULL,NULL,NULL,& time);

This will sleep for time.tv_sec seconds and time.tv_usec microseconds.

Setting tv_sec to 0 and tv_usec to 1000 will wait for one millisecond. setting tv_usec to 500 will wait for 500 microseconds or half a millisecond. Not sure if that is meaningful to do though, sleep(x) only guarantees that you will not wake up BEFORE x time units has passed, you may wait longer than that and if you specify a very short time interval, for example 1 microsecond you will probably in reality wait much longer than you specify.

Alf
0
 

Author Comment

by:saido
ID: 8168299
what i'm doing is that i'm develloping  bus protocols working on different timing (100khz, 200khz,1Mhz...), so when generating clock to write or read i need some delays to enable the data to be stable on the line.
Sleep doesn't work.
i will test select(), but what is the g=header file to include for this.
Said
0
 
LVL 12

Expert Comment

by:Salte
ID: 8168647
depends on your system. If you're on a windows system you can get it from

#include <windows.h>

or

#include <winsock2.h>

or some such.

Write select() in the edit window and then press F1 and see what comes up.

Alf
0
 
LVL 12

Expert Comment

by:Salte
ID: 8168654
If you're on a unix or linux system you can do:

man select

and get the name of the #include file to use.

Alf
0
 
LVL 22

Expert Comment

by:nietod
ID: 8168810
>> what i'm doing is that i'm develloping  bus protocols working on
>> different timing (100khz, 200khz,1Mhz...),
Usually this sort of work has to be done via interrupt mechanisms.  Your program can easily be suspended for intervals that last 1/20th of a  second, and possibly much more.  that is 50 millisecond.  That means that no matter what you do, accuracy of better than 50 milliseconds is almost certainly impossible, accuracy of 100 millisconds is probably unlikely.   You can't reliably use these sorts of techniques for preccise timing in a preemptive multi-tasking OS.  This sort of thing is typically done by writting device drivers that are then invoked by interrypts as soon as some critical condition occurs, like if the bus goes quiet.   You almost certainly have to completely rethink your approach.
0
 
LVL 1

Expert Comment

by:d_iego
ID: 8171187
does any of you know how to delay or pause system in a win api aplication?
0
 
LVL 22

Expert Comment

by:nietod
ID: 8171225
>> does any of you know how to delay or pause system in a win api aplication?
Accurately?  No.  you can't
0
 

Author Comment

by:saido
ID: 8172408
what i'm doing is that i'm develloping  bus protocols working on different timing (100khz, 200khz,1Mhz...), so when generating clock to write or read i need some delays to enable the data to be stable on the line.
Sleep doesn't work.
i will test select(), but what is the g=header file to include for this.
Said
0
 

Author Comment

by:saido
ID: 8172604
sorry for the previous message, it's duplicated.

About select(), I include windows.h, but still doesn't know  select as function for delay, nor the structure tv.
can you give me a complete example?
0
 
LVL 12

Expert Comment

by:Salte
ID: 8172906
Unfortunatley I am sitting on a Unix machine right now and I don't have Visual C++ installed on my windows machine at home - I use CYGWIN and gcc at home for my windows programming :-)

However, I am very sure that if you just type select() in your source code somewhere, place the cursor on that word (select) and then press the F1 key you should get some info and if you follow the hyperlinks there it will tell you which include file to use etc.

Alf
0
 
LVL 12

Expert Comment

by:Salte
ID: 8173043
btw,

I agree with nietod that you most likely have to completely rethink your approach.

If you're working on some bus thing which has to be very accurate you most likely have to use specific hardware to test that bus. Such hardware can then send interrupts to the PC etc and you have to use a driver which can hook itself unto those interrupts and respond to them.

Trying to run as a regular application will most likely not lead anywhere. Even a sleep on microseconds level as select() will only guarantee that you won't wake up BEFORE the specified time. It might take a very long time after and if you have a very short time specified (such as a couple of microseconds) you will most likely have an actual sleep time of several 100 times the time you specified. That is way too inaccurate to be reliable in any way. The thing is there's nothing you can do about that. As long as you run as application, your application can be stopped and set to wait in a multi tasking system.

In this way it is probably better if you just reboot the machine in MS-DOS 6.22 and take over some interrupts and handle it from there. Running MS-DOS 6.22 gives you full control over the CPU and you can do what you want. Of course, you don't get multi-tasking but that is exactly what you don't want in your case so that should be fine.

If you let the PC run MS-DOS you can just do RDTSC to read the timer and loop until the time has elapsed. The RDTSC timer ticks once every 100th nanosecond and is available on pentiums. If you use Borland C++ 3.1 or some such compiler you can do code like this:

struct sysclock_t {
   int LL, LH, HL, HH;
};

void sleep(long ns)
{
   // make the sleep in 100th nanoseconds.
   ns = (ns + 99)/100;
   ns -= FACTOR;

   __asm {
      rdtsc
      // clock in EDX:EAX
      // we ignore EDX since we asume ns is
      // of shorter duration than that.
      add eax,dword ptr ns
      mov ebx,eax // save eax into ebx.
      jnc loop2

      // new time is after wrapping around
loop1:
      rdtsc
      // again we ignore EDX
      // wait for time to wrap around.
      cmp eax,ebx
      jae loop1

// Time has wrapped around and present time < wait time.
loop2:
      rdtsc
      // again we ignore EDX
      cmp eax,ebx
      jb loop2
    }
}

Several notes here:

First, It is quite possible that an old Borland C++ compiler or old version of MSVC won't understand 'rdtsc'. However, these compilers have ways that you can specify ways to emit specific codes as instructions and rdtsc is a simple 2 byte instruction if I rmeember correctly. It has no operands so it should be easy enough. Just look it up in Intel's instruction set for pentium.

Second, The result is a 64 bit counter counting time since midnight January 1st 1601 or something like that. We are not interested in long durations here so I ignore the upper 32 bits and only uses the lower 32 bits.

Third, I also subtract a FACTOR. This FACTOR is a value you must find by running your sleep function. It is suppoed to subtract for the time you take doing the rdtsc and adding the value etc. These things also take time and exactly how much time I don't know. However, if you run sleep on 1 microsecond a million times that should take approx 1 second and tuning FACTOR so that it takes more or less exactly one second is a way to get the value that. The more times you do a wait the more accurate you can tune FACTOR.

Fourth, the function gets a long argument giving count in nanoseconds. This is way too accurate and the function already at beginning turns it into a count of 100th nanoseconds, it is quite possible that even that is too accurate and so you might want to consider using microseconds as your unit yourself or even higher.

Changing it to microseconds is easy:

void sleep(long ms)
{
   ms *= 10;
   // ms is now in 100th of nanoseconds and can be added
   // to clock value.
   ....proceed as before...
}

Although it is possible that the compiler doesn't know about rdtsc it does know about 32 bit programming (32 bit mode has been available since 386) so the mov ebx,eax and cmp instructions should be good as is, they work fine even in 16 bit code. The compiler will insert codes to tell the cpu that "here comes a 32 bit instruction" so that they are executed correctly.

Since I ignore the upper 32 bits I ignore the EDX register completely and just compares the EAX(the lower 32 bits).

This gives you two possibilities. if 'now' is the value at present time and 'end' is the value at the time after the wait, you have two situations:

now < end - no wrap around.
now > end - we wrap around.

At wrap around we first have to wait until 'now' wraps around so that now < end is established, the first loop loop1 does that wait. If we have the situation with no wrap around already we skip that loop and go directly to loop2.

When now < end we enter loop2 and wait until now has reached end and when now >= end we're done looping.

This code will only run properly on a non-multi-tasking system. Trying code like this on Win32 will NOT give the desired result. Reboot old MS-DOS 6.22 and run your program there.

Alf
0
 
LVL 22

Expert Comment

by:nietod
ID: 8173180
>> In this way it is probably better if you just reboot the machine in
>> MS-DOS 6.22 and take over some interrupts and handle it from there
That would certainly work, if this is just some sort of timing test, not some sort of "real" program to be run under windows.  However, the problem with this is that you can't (realistically) run a VC program under DOS.  You will have to find an older compiler, probably a C compiler to do this.  If you can find a copy of VC 1.5x, that will still create a program that can run under DOS.
0
 
LVL 12

Expert Comment

by:Salte
ID: 8173517
I would think that MSVC 4.0 can compile 16 bit programs that can run under MS-DOS 6.22 - as can Borland C++ 3.1 do or perhaps even Borland C++ builder 2.0 or some such.

But you can forget about VC 6.0 or Borland C++ builder 5.0 etc. I don't think they can handle 16 bit code.

Alf
0
 
LVL 22

Expert Comment

by:nietod
ID: 8173678
>> I would think that MSVC 4.0 can compile 16 bit programs that can run under MS-DOS 6.22
I am 99.9% sure it can't.  AFAIK VC 1.52 is the last one to produce 16 bit code, which is why it is still used by driver developers.  
0
 
LVL 12

Expert Comment

by:Salte
ID: 8173773
Ok, probably just my memory slipping...when you mention it, I believe it was 1.52 I used at that time for the MS-DOS version of the program. we kept a program at both windows and MS-DOS version and I used MSVC 4.0 at the time but when you mention it, I guess we used 1.52 to compile the Win3.1 version of the program.

Back in those days we also had the Win32s system which was a Win32 like system for MS-DOS and Win3.1 and I believe 1.52 also had support for that.

Alf
0
 

Author Comment

by:saido
ID: 8175377
As my application must be windows95/98/NT/2000/XP compatible, do you think using interrupts will be a solution ( just a note i use i2c Bus, SPI bus ...)

i'm working on Windows 2000.

Said
0
 
LVL 12

Expert Comment

by:Salte
ID: 8175600
Saido,

Why must your application be WinNT/Win2000/XP compatible? Are you aware that you are asking for the impossible?

WinNT/2000/XP are multi tasking systems. To some extent Win95/98/ME are as well.

You simply CANNOT wait for very short delays on those systems, it just isn't possible. Yes, you can use select and specify a very short delay such as 2 Microseconds. The only thing you know for certain si that you will sleep AT LEAST 2 microseconds. Most likely you will sleep at least 50 milliseconds which is 25000 times more than what you asked for and that is an error factor which simply aren't acceptible to the things you want to do. If your boss tells you to make this kind of application tell him you need a dedicated machine that can run MS-DOS or some similar non-multi tasking system and the program must run on that machine. That machine can be hooked on a network and communicate with another application running on a Win2K/XP system which can display the graph or whatever in a regular windows Win32 fashion, just the way a moronic boss wants it. However, the statistics must be collected on a machine that does NOT run any multi tasking system, is dedicated to the task and where you have complete control over everything.

It's that simple.

Of course, there IS another way - there always is. Here is how:

Design and make a specific hardware card that have some smart cpu that can do the statistics collection. Then put this card on the PCI bus of the computer and install a WDM driver that communicates with the card. This WDM driver must of course be written by you :-)

Now, your application can run under Win32 in WinNT/2000/XP and can use DeviceIoControl to talk with the driver which collects the statistics from your hardware card.

The card must of course also have connection to the bus you want to collect statistics about, if that happen to be the PCI bus then you're already there, if not you have to really do something smart on that card to hook it up to the bus you want to collect statistics about - for example the bus to the AGP port will probably best be done by making a card that connects on the AGP port and itself provide an AGP port which you can hook the graphics card to. Similar settings for other busses.

I think the dedicated CPU running MS-DOS is WAY simpler, cheaper and easier to both program maintain and expand.

Alf
0
 
LVL 22

Expert Comment

by:nietod
ID: 8176106
>> As my application must be windows95/98/NT/2000/XP compatible,
>> do you think using interrupts will be a solution
Probably not.

>> You simply CANNOT wait for very short delays
>> on those systems, it just isn't possible
To be more specific, you canot wait for short delays with an accuracy.  Your program is probalby executing less than 10% of the time.  Most of the time other programs are executing   That means that every few milliseconds  your program stops excuting and then does not resume executing for a while.  This is going on all the time.  This has nothing to do with sleeping, it happens to all programs no matter what they do.   So there is no way you can accurately wait for say 10 milliseconds, if your program is typcally suspended for 90 milliseconds out of every 100.  Your 10 millisecond wait might right out, then your program might be suspended for another 80 millisconds before it continues.

This sort of work must be done by device drivers and VXDs that can be invoked at interrupt time.  

>> Design and make a specific hardware card that have some smart
>> cpu that can do the statistics collection.
That shouldn't be necessary, I assume that you can write a device drinver to do this with the existing hardware.  I'm assuming that the necessary interrupts etc are available to allow this to be done.

It might help if you coudl tell us _exactly_ what you are trying to do and why.  But almost certainly, your approach to doing it will have to change.
0
 

Author Comment

by:saido
ID: 8179660
ok,
I have a board supporting multiple buses including I2c and SPI that i have to controle from PC via parallel port. for the I2c the function frequency must be about 200Khz and SPI about 1Mhz.

so when develloping the protocol,  i have to insert delays when sending/receiving bits ( either for the clock or data) to let them be stable on the line.

Said
0
 
LVL 12

Accepted Solution

by:
Salte earned 200 total points
ID: 8180070
Sounds like you very much need to write a device driver to me.

Since it is connected to the PC via the paralell port you don't need to make any hardware card (you appearantly have that already) but you do need to write a driver that can work on the paralell port and handle the timing accurately.

In any event, a regular application cannot possibly handle such timing. In a multi tasking environment your application may be stopped at any time and put to sleep by the OS in order to allow other processes (servers, system tasks, etc etc, do a CTRL+ALT+DEL in Win2K or WinXP and see the task manager and click on the 'processes' tab to see all the processes that require at one time or another the ability to run and whenever they run your application can not run, so it is forced to sleep).

It doesn't matter if you wake up after sleeping for exactly 3 milliseconds and then immediately is put to sleep for 300 milliseconds before you can do anything you were planning to do after that sleep.

Code like this:

void do_something()
{
A:
   sleep_for_very_short_interval();
B:
   do_something_else();
}

Now, if the sleep_for_very_short_interval() correctly wakes up after that interval but while you're at label B and before you get to do_something_else you are forced into sleep by the OS because some other high priority task require the CPU then you won't get chance to do_something_else until after the OS let you continue your task again.

Alf
0
 
LVL 9

Expert Comment

by:tinchos
ID: 9510633
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Please Review

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Tinchos
EE Cleanup Volunteer
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question