Searching \ for 'analog frequency generator using 16c71' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page:
Search entire site for: 'analog frequency generator using 16c71'.

Truncated match.
PICList Thread
'analog frequency generator using 16c71'
1998\05\22@163719 by andre

Hi to all engineers.

I am trying to make analog control A/D generator. I connected
20 Mhz crystal with 16c71. on output I am getting only 20 Khz.
I know 20/4 = 5 Mhz do you think A/D conversion slowing it down.
Is there any thing I am doing wrong?

here is my code.

TMR0        EQU     0x01              ; COUNTER
PC          EQU     0x02              ; PROGRAM COUNTER
STATUS      EQU     0x03              ; STATUS REGISTER
FSR         EQU     0x04              ; FILE SELECT REGISTER
PORTA       EQU     0x05              ; OUTPUTS
PORTB       EQU     0x06
RP0         EQU     0x05
TRISA       EQU     0x05             ;
TRISB       EQU     0x06             ;
OPTION_REG  EQU     0x81             ;
ADCON0      EQU     0x08
ADCON1      EQU     0x08             ;
ADRES       EQU     0x09
PCLATH      EQU     0x0A
INTCON      EQU     0x0B
CARRY       EQU     0x00              ; CARRY BIT
DCARRY      EQU     0x01              ; DIGIT CARRY BIT
PDOWN       EQU     0x03              ; POWER DOWN BIT
WATDOG      EQU     0x04              ; WATCHDOG TIMEOUT BIT
F           EQU     0x01
Z           EQU     0x02
PORTA       EQU     0x05               ; PIN
PORTB       EQU     0x06               ; INPUTS FROM DIP SWITCH
CH_1_RESOLT EQU     0x0C               ; TEMP REGISTER
CH_2_RESOLT EQU     0x0D
CH_3_RESOLT EQU     0x0E
CH_4_RESOLT EQU     0x0F
COUNT       EQU     0x1D
COUNT1      EQU     0x1C
TEMP        EQU     0x1E

LIST P=16C71


   ORG     00H

; ****************** SUBROUTINES **********************
       MOVWF COUNT            ; SAVE IT THERE

       GOTO   $ - 1           ; IF NOT JUMP

; ****************** INITALISATION ********************

       BANK1                   ; SET UP PAGE 1
       MOVLW   B'00000000'
       MOVLW   B'00011111'
       MOVWF   TRISA           ; SET AS INPUTS A4 OUTPUT
       MOVLW   B'00000000'
       BANK0                   ; RETURN TO PAGE 0
       MOVLW   B'11000001'     ; SET A/D INTERNAL RC CLOCK AND 11 FOR
CH 4
       MOVWF   ADCON0          ; DO IT

; ****************** THE START ************************

               BSF PORTB,2
               BSF     ADCON0,2        ; START CONVERSION
               MOVLW   10              ; THIS LINE IS 10
               MOVWF   TEMP
               DECFSZ  TEMP,F          ; WAIT A WHILE
               GOTO    $-1
               BTFSC   ADCON0,2        ; TEST FOR END OF CONVERSION
               GOTO    $-1
               MOVF    ADRES,W         ; LOAD A/D RESULT INTO W
               MOVWF   CH_1_RESOLT     ; STORE IT

               BSF PORTB,0
               CALL DELAY
               BCF PORTB,0
               CALL DELAY
               GOTO MAIN


1998\05\22@220859 by Bill Cornutt


Great looking code as all ways.

One thing that may be slowing down the program is that
you are starting the conversion and waiting for it
to complete before reading the A/D and doing the delay.

If you first read the A/D and then start the next conversion
before doing the delay, there would be much less, if any,
time spent waitting for the conversion to complete.

I have rearanged your code in the MAIN routine to do this.

I would arange the routines in a different order.

wait for A/D to complete
read A/D
select next A/D input (if necessary)
  Delay for next input to settle (if changed A/D inputs)
start conversion

This can all be done under interupt if you desire.  It gets
a little complicated if you switch inputs.  But there are no
wasteful delays necessary.

with no A/D input switching

INTERUPT   wait for A/D to complete
          read A/D
          start next conversion  * this gives one more cycle
          store A/D reading      * for conversion
          set 'NEW' bit flag     * to show main that new A/D reading
          return from interupt
          END INTERUPT

with A/D input switching

INTERUPT   wait for A/D to complete
          read A/D
          select next A/D input  * if posible before
          store A/D reading      * storing A/D reading
          set 'NEW' and 'CONVERSION DELAY' bit flags
          do something to show which A/D input had 'NEW' reading
          and it would be nice to calculate the next-next A/D input
          return from interupt
          END INTERUPT

SUBRTN     if 'CONVERSION DELAY' bit flag set
              clear 'CONVERSION DELAY' bit flag
              set 'START CONVERSION' bit flag
              return from subroutine
              clear 'START CONVERSION' bit flag
              start conversion
              return from subroutine

and in the main body of the program test for the bits
bit test in one instruction.  if either is set, then call
SUBRTN.  Just make sure that there is enuff cycles
between 'TEST's to let the A/D input settle, and that
the numbers of cycles between three 'TEST's calls are not
greater than the interupt timer.

It is necessary to have the two part routine to insure
that if an interupt occures just before a 'TEST' instruction,
there will be a delay before the conversion is started.

After writting this, I see another way to switch A/D inputs.
Just run the interupt timmer twice as fast and...

INTERUPT  if 'START CONVERSION' bit flag clear
             read A/D
             select 'NEXT A/D INPUT'
             store A/D reading
             set 'NEW' and 'START CONVERSION' bit flags
             indicate which A/D input is 'NEW' ('LAST A/D INPUT')
             set 'START CONVERSION' bit flag
             return from interupt
         else   (the bit is set)
             start conversion      * do this as soon as possible
             clear 'START CONVERSION' bit flag
             good place to move the 'NEXT A/D INPUT' pointer
                into the 'LAST A/D INPUT' pointer, and calculate
                'NEXT A/D INPUT' pointer
             return from interupt

It may be best to have a 'NEW' bit flag for each A/D input
and a seperate register for each A/D input reading.

With this method there is an equal amount of time for
the input to settle and for the conversion to complete.
But still best to test for conversion compete before
reading it.

Have fun

Bill C.

The good smelling guy!

{Quote hidden}

1998\05\23@145743 by David Sorlien

picon face

Bill Cornut's advice is excellent.

Have you considered putting the code to generate the output waveform in
the interrupt handler, but leave the A to D code in the main loop?

A while back, I designed some PIC code for a circuit that went into a
ruggedized portable PC that had internal heating elements. This PC was for
data collection in test aircraft, the PC had to function at -30 deg C. The
PIC had to sample four temp sensors, calculate the required PWM duty
cycles for the five heating elements, and generate the five PWM outputs
that controlled FETs to switch power to the heaters.

I put the A to D code and the calculation code in the main program loop -
real easy stuff there.

The difficult part was the PWM outputs. The heaters consume a huge amount
of power, so all five could not be on at the same time. I had to
synchronize and interleave the PWM outputs to not exceed the power budget
(and burn up the power supply section!) In the interrupt code, I had a
counter that would increment each interrupt. The main loop calculated the
start and end count number for each of the five PWM outputs. The interrupt
turned on/off the appropriate PWM outputs when the count equalled the
start/stop values. Worked great, so I submitted the design.

In testing, the client wanted the PWM frequency increased. But I already
had the TMR0 prescaler at 0, and the PIC was running at 20Mhz. The
interrupt code could not be made smaller, so I decided to modify the TMR0
value from inside the interrupt routine. Since TMR0 caused an interrupt
when it rolls from 0xFF to 0x00, TMR0 has a value of 0 when the interrupt
routine begins. The first instructions in my interrupt routine (except
saving STATUS and W) were to load TMR0 with a new value. This forced the
interrupt frequency to increase.

To get the maximum PWM frequency, the interrupts happened so often that
the main loop code would execute about five instuctions between
interrupts. Any faster and the main loop would never get a chance to run!

So, try putting your output code in the interrupt handler, and if the top
frequency is still inadequate, modify TMR0 in the interrupt handler to
force interrupt frequency to increase. Carefully calculate worse-case
timing and make sure the main loop gets a chance to execute.


Andre Abelian wrote:

{Quote hidden}

'analog frequency generator using 16c71'
1998\06\14@220521 by Marc Heuler
Hi David (David Sorlien), in <> on May 23 you wro

> synchronize and interleave the PWM outputs to not exceed the power budget
> (and burn up the power supply section!)

That would have generated enough heat for the computer, wouldn't it :-)

More... (looser matching)
- Last day of these posts
- In 1998 , 1999 only
- Today
- New search...