• C

Generating a Software Clock Pulse

Ok, i'm not sure if any of you guys have had experience with Hardware and Software I/O interfacing. But none the less, I'll give this a shot. I'm working on a fairly simple project involving a ADC0809 ( analog to digital convertor) It requires a 640 KHz clock pulse. Of course it can be supplied using a tripple 5 timer etc, but I want to use a software method.
I'm using Borland C 2.0 for DOS
It has a delay() function already predefined in it. the problem is, the period of this pulse if less than 1 ms.
Any solutions will be appreciated, thank you. If maybe U need me to tell u how this specific adc functions, just ask.
LVL 13
Kelvin_KingAsked:
Who is Participating?
 
kinrossCommented:
KISS keep it simple stupid :)

What you are proposing to do will cause you nothing but frustration.
My suggestion would be is get a hardware clock. Since you want to do it in software, tweak away.  Here's how to do it.

First you need to disable all optimizations on your compiler or it will delete the following code because it thinks it's useless.

asm
{
nop
nop
nop
nop
nop
}

outportb(PORTA,address);
outportb(PORTC, 0x00); //disable all bits
outportb(PORTC, 0x80); //activate WR outportb(PORTC, 0x10)    
//this is the bit for the clock
//maybe I can toggle it in a loop for 8 times...bacause the ADC requires 8 clock pulese to to a conversion then just go on to the next step//
                                 
outportb(PORTC, 0x00)

Now all of your outportx() functions are precompiled binaries that are linked in so there is no way for you to now the timing of these function other than by trial and error.   Keep adding nops until you get the timing just right, have fun in the build, run, test, tweek cycle.  Do not put the nops in a loop.  This will generate branches and could mess up your timing even more.  Do not make a function out of the nops,  you must have the nops followed immeadiatly after the outport stuff otherwise you will have to worry about stack timing.

Now my guess is that you are over killing a project with a processor on hand  that you are familiar with therby trying to fit a square peg in a round hole.  I wold suggest going to an architecture that is more suited for embedded applications, that sounds like what you ar doing.  You can find processors with real time clocks that generate interrupts down to the clock pulse.  They also have a2d built right into the cpu.

0
 
Kelvin_KingAuthor Commented:
ok ok .. I forgot to add something important. The address of my adc is 0x303 ( i'm working in hexa )so when I'm reading from a port i use
inportb(portc);
and write to a port I use
outportb(portc, 0xXX);
just an example.
0
 
ufolk123Commented:
Hi ,

In dos there is no other way to get a pause of less than that resoultion.For getting high resolution you do something like this.

while(count)
{
some dummy assignment or instruction //
}
note the time taken by this loop and use it for providing an abstraction for pause of high resolution.

Like if you are using assembly
loop of NOP instruction will do.


This way you can get a fine resolution delay but you may have to do some experimenting with the time taken by loop and instructions inside the loop.


0
Managing Security Policy in a Changing Environment

The enterprise network environment is evolving rapidly as companies extend their physical data centers to embrace cloud computing and software-defined networking. This new reality means that the challenge of managing the security policy is much more dynamic and complex.

 
vissteveCommented:
hi,
   can u give the details of the adc.how fns?what r u using?............
               thank u.
0
 
Kelvin_KingAuthor Commented:
Hmmm, I'm firmiliar with Assembly Language instructions like NOP, but in C, what instruction has the same function ? ( does'nt nothing but waste time )
Also, is there some kind of book which tells u the duration if each operation, like in assembly language ?

vissteve>>
I'm using a motorola ADC 0809
which is an 8 input step convertor.
We start conversion by sending selecting the input and a '1' to the active high "start conversion " pin.
When the conversion is done, it will send a '1' at the "inturrupt " pin. but what I'm interested in is the clock cycle.
0
 
Ernest022699Commented:
You're far better off using a hardware timer.  Tight loops incrementing values stored in memory locations or doing some complex math may seem like a good solution, but you'll spend forever tweaking things.  And if you need to do other stuff later, ....
0
 
Kelvin_KingAuthor Commented:
Thank U for that advise ernest. But I'm looking for software solutions.
0
 
Kelvin_KingAuthor Commented:
I was thinking about something likevoid adc_conversion();
{
      outportb(PORTA,address);
      outportb(PORTC, 0x00);            //disable all bits
      outportb(PORTC, 0x80);            //activate WR
        outportb(PORTC, 0x10)  
        //this is the bit for the clock
        //maybe I can toggle it in a loop for 8 times...bacause the ADC requires 8 clock pulese to to a conversion then just go on to the next step//
   
      outportb(PORTC, 0x00);            // also possible to use xor
      do
      {
            ready = inport(PORTC);      //read portc
            ready = ready & 0x01;
      }
      while(ready!=0x01);             //LOOP IF CONVERSION NOT ENDED

}


0
 
Kelvin_KingAuthor Commented:
I was thinking about something like
void adc_conversion();
{
      outportb(PORTA,address);
      outportb(PORTC, 0x00);            //disable all bits
      outportb(PORTC, 0x80);            //activate WR
        outportb(PORTC, 0x10)  
        //this is the bit for the clock
        //maybe I can toggle it in a loop for 8 times...bacause the ADC requires 8 clock pulese to to a conversion then just go on to the next step//
   
      outportb(PORTC, 0x00);            // also possible to use xor
      do
      {
            ready = inport(PORTC);      //read portc
            ready = ready & 0x01;
      }
      while(ready!=0x01);             //LOOP IF CONVERSION NOT ENDED

}


0
 
Kelvin_KingAuthor Commented:
Open for Discussion
0
 
SunBowCommented:
I agree w/ Ernest, you'd need to know the cpu, its implementation of cycles, its speed, the compiler's method of impementing machine code (why not Borland v3?), and more.  
But then, I do no not understand the purpose. I want to read as:

Wait (small time less than 1 ms)
  {
  Do stuff
  }

So you would ask about what is 'do stuff'.  But I cannot, I am likely confused on the issue. I want to suggest that the 'do stuff' part uses hardware options to fixate on specific time(s), with software parts determining elapsed time. If so the question would involve: how much time to wait.

I don't know, but believed that 1 ms & ~ 1/18th (tic) were readily available units, as well as a smaller measure.

But if you are only playing on a single unit, approaches I have taken before use nested loops.  Find a bigger time increment that you can realy on, like 1 second.  Then massage the looping to accomodate. Nested loops of 1 to 1000 work well.  For improved accuracy, tune to outer loop of minute, hour day, and adjust the loops accordingly (60,60,24). This time is used to refine the inner loops.  A single increment command could be the only statement used for this purpose. Innermost loop of 1000 may be nice. Tune the length of subsequent loops until the whole thing runs, say 10 seconds. That'll give you good approx. for how many inc's your machine needs for your standard small amount of time. Accuracy improves by lengthening the total program runtime.

Problem is in porting this method elsewhere. So I'd go for software access to h/w timer functions for portability.  But I suspect I am missing your point. I am not very expert on any of these issues, including ADC -clock...

Are you trying to assess the time elapsed between the active high "start conversion " pin and when it will send a '1' at the "inturrupt " pin? Or use that period to time something else?
0
 
NorbertCommented:
>>>It requires a 640 KHz clock
640 kHz = 640000 kHZ = 0.0000015625 s

that means 1.563 micro seconds
how exact the clock must be ?
remember: No PC is deterministic!
There are interrupts for ram refresh, PC clock, keyboard input and so on.
These will disturb your Clock tick.
So the Ticker will not always have the same distance.
My be a hardware clock would be the better solution
0
 
SunBowCommented:
..speed of cache, ram, i/o, all them thar bus paths...
0
 
kinrossCommented:
KISS keep it simple stupid :)

What you are proposing to do will cause you nothing but frustration.
My suggestion would be is get a hardware clock. Since you want to do it in software, tweak away.  Here's how to do it.

First you need to disable all optimizations on your compiler or it will delete the following code because it thinks it's useless.

asm
{
nop
nop
nop
nop
nop
}

outportb(PORTA,address);
outportb(PORTC, 0x00); //disable all bits
outportb(PORTC, 0x80); //activate WR outportb(PORTC, 0x10)  
//this is the bit for the clock
//maybe I can toggle it in a loop for 8 times...bacause the ADC requires 8 clock pulese to to a conversion then just go on to the next step//
                                 
outportb(PORTC, 0x00)

Now all of your outportx() functions are precompiled binaries that are linked in so there is no way for you to now the timing of these function other than by trial and error.   Keep adding nops until you get the timing just right, have fun in the build, run, test, tweek cycle.  Do not put the nops in a loop.  This will generate branches and could mess up your timing even more.  Do not make a function out of the nops,  you must have the nops followed immeadiatly after the outport stuff otherwise you will have to worry about stack timing.

Now my guess is that you are over killing a project with a processor on hand  that you are familiar with therby trying to fit a square peg in a round hole.  I wold suggest going to an architecture that is more suited for embedded applications, that sounds like what you ar doing.  You can find processors with real time clocks that generate interrupts down to the clock pulse.  They also have a2d built right into the cpu.
0
 
tdubroffCommented:
Kelvin,

If you can use a 555, use it.  They are easy to set up and if you put an op-amp comparator on the output you should get a nice square wave clock. If you still want some control of the 555 through software, you could conceivably add an enable pin that is I/O-mapped to your computer.  Or likewise you could add a voltage-controlled resistor, or a voltage-controlled capacitor that is controlled by software but affects the 555's pulses.

In general though, anytime you need a real-time clock, there is no other solution than a hardware solution.

-Ted
0
 
LucHoltkampCommented:
I agree with tdubroff, although you can make a clock in software, it will never be very reliable, the PC OS's are not intended as a real-time OS...
My advice is to use the 555
Luc
0
 
Kelvin_KingAuthor Commented:
Interesting Conversation !!
Yes.. I agree, Using the 555 is more efficient.
I did'nt have much time to do that project anyway, so I decided on a hardware clock. But If given more time, I would have tried for a software clock. Thanks anyway for all your help.
I'll just give this on to kinross ;)
0
 
obgCommented:
The standard PC architecture does not provide any counter better than the timer, which runs at 1.19 MHz (as far as I know). If you want 640 kHz you'd want triggers at 1.28 MHz, but if you could settle with 1.19, you could read the CRTL source of delay() from your Borland C installation to see how this is done. By the way, I'm not sure that the source is included in 2.0. Drop in a msg and I'll post it.
0
 
obgCommented:
Ok, to keep it simple (though I don't like the attitude), why not just make a loop for a million laps (or so), meassure how long time it took, and from there calculate the necessary amount of laps to generate the pulse. (Of course, to be accurate, you'd need to meassure a lot of outportbs as well.)

- Simple AND PORTABLE!
0
 
LucHoltkampCommented:
// next code works reasonable
// GetTickCount returns the tick count from the real time clock (increased
// every 50 ms or so)
// it's a win32 function, but there are similar functions in other OS's

double one_micro_sec;

void calibrate()
{
   volatile DWORD start = GetTickCount(), end;
   unsigned teller = 0;
   // wait until clocktick flips over
   do end = GetTickCount();
   while (start == end);
   // actual calibration loop
   start = end;
   do
   {
      ++teller;
      end = GetTickCount();
   }
   while (start == end);
   one_microsec = teller/(1000.0*(end - start));
}

void wait(unsigned micro_sec)
{
   if (!micro_sec) return;
   unsigned count = micro_sec*one_microsec + 0.5; // number of iterations
   volatile DWORD dummy;
   while (count--) dummy = GetTickCount();
}
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.