Electronics > Projects, Designs, and Technical Stuff

Small package decade counter?

<< < (5/5)

cv007:
If sticking to powers of 2, you can use fixed duty cycle of nco. Since we are talking relatively low speeds (100Hz,400Hz), there is plenty of time to load a few registers.

NCO INC = 1
use NCO CLK pin

div10 = 256 - 10/2
div200 = 256- 200/2

loop:
    ACCL = div10
    ACCU = 255
    ACCH = 255
    wait while NCO1IF == 0
    NCO1IF = 0


rcbuck:
Ian, I have programmed a PIC10F322 but am not getting any division of the input signal. The output on pin RA1 (CLC1) is the same as the input on RA2 (T0CLKI). I also tried to assign CLC1IN2 to RA2 which would mean T0CKI and the Flip-Flop had the same inputs. That also gives me 200 Hz out of RA1.

--- Code: ---#include "p10f322.inc"
   
; CONFIG
 __CONFIG _FOSC_INTOSC & _BOREN_OFF & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _LVP_OFF & _LPBOR_OFF & _BORV_LO & _WRT_OFF

RES_VECT  CODE    0x0000    ; processor reset vector
    GOTO    START   ; go to beginning of program

MAIN_PROG CODE ; let linker place main program
    radix dec ;default to decimal numbers
 
START
    CLRF    TRISA   ; all pins are outputs
    CLRF    LATA    ; clear all latches
    CLRF    ANSELA  ; all pins digital
    bsf     TRISA, 0 ; RA0 is an input
    bsf     TRISA, 2    ; RA2 is an input
    CLRW
   
    ; setup CLC module, input on RA2, Flip-Flop output on RA1
    movlw   0x01
    movwf   CLC1SEL1 ; CLCIN1 assigned to LC1D3S, RA0
    movlw   0xC4
    movwf   CLC1CON ; D Flip-Flop, port pin output enabled, module enabled
    movlw   0xAA
    movwf    CLC1GLS0 ; gating OR, no inversion
   
    ; setup TMR0
    movlw   0xE8  ; External clock on RA2, rising edge, no prescale
    movwf    OPTION_REG
    movlw -5 ; Prepare W with Timer 'bump' value
   
Loop:
    btfss INTCON, TMR0IF ;Wait for Timer 0 rollover
    goto Loop ;(2 Tcy)

    addwf TMR0,F ;'Bump' timer to 5 counts before rollover
    bcf   INTCON, TMR0IF ;Clear rollover flag

    movlw 1<<LC1G2POL ;toggle flipflop D input                               
    xorwf CLC1POL

    movlw -5 ; reload W with Timer 'bump' value
    goto Loop ;(2 Tcy)
   
    END
--- End code ---
Do you see any problem with the code setup? I don't completely understand the CLC module but I think I have is setup correctly.

Edit: Corrected a couple of errors in the CLC code setup area.

cv007:
Here is an nco version, can try if you want. I don't know if it will work. The nco io looks like its supposed to be async, so just have to worry about reloading acc values before the next rising edge which should not be a problem with the speeds you are talking about.

--- Code: ---#include <xc.h>
#define DIV 10 //div ncoclk in by (power of 2)
#define RELOADval 256-(DIV/2) //if DIV was not power of 2, it is now
void main(void) {
    ANSELAbits.ANSA1 = 0; //RA1, NCO1CLK <-
    TRISAbits.TRISA2 = 0; //RA2, NCO1 ->
    NCO1INCL = 1; //inc by 1
    NCO1CONbits.N1OE = 1; //NCO1 ->
    NCO1CONbits.N1EN = 1; //NCO1 on
    for(;;){
        NCO1ACCH = NCO1ACCU = 255;
        NCO1ACCL = RELOADval;
        while( PIR1bits.NCO1IF == 0 );
        PIR1bits.NCO1IF = 0;
    }
}
--- End code ---
NCO1CLKbits.N1CKS may need to be setup, the default reset value shows as using the NCO1CLK pin (0b00), but the nco diagram shows NCO1CLK as 0b11.

I don't know if this would also work if needing any div value (not just powers of 2)-

--- Code: ---#include <xc.h>
#define DIV 10
#define RELOADval 256-DIV

void main(void) {
    //RA0 = CLC1IN0 (clock in)
    ANSELAbits.ANSA0 = 0; //digital
    CLC1CONbits.LC1MODE = 2; //4input AND
    CLC1SEL0bits.LC1D1S = 1; //same source for all - CLC1IN[1]
    CLC1SEL0bits.LC1D2S = 1; //pinouts use CLC1IN0,CLC1IN1
    CLC1SEL1bits.LC1D3S = 1; //clc datasheet chapter uses CLC1IN1,CLCIN2
    CLC1SEL1bits.LC1D4S = 1; //so assume CLC1IN0 = CLC1IN1, CLC1IN1 = CLC1IN2
    CLC1GLS0 = 0x55; //AND all 4 to gate
    CLC1GLS1 = 0x55;
    CLC1GLS2 = 0x55;
    CLC1GLS3 = 0x55;
    CLC1POL = 15; //(invert for AND)

    //RA2 NCO1 output (divided clock out)
    TRISAbits.TRISA2 = 0;
    NCO1INCL = 1;
    NCO1CONbits.N1OE = 1;
    NCO1CLKbits.N1CKS = 0b11; //LC1OUT (diagram shows 0b10)

    NCO1CONbits.N1EN = 1; //enable nco
    CLC1CONbits.LC1EN = 1; //enable clc

    for(;;){
        PIR1bits.NCO1IF = 0;
        NCO1ACCH = NCO1ACCU = 255;
        NCO1ACCL = RELOADval;
        while( PIR1bits.NCO1IF == 0 ){       
            while( CLC1CONbits.LC1OUT == 0 ); //wait for clock edge
            CLC1POL ^= 0x80; //flip polarity
        }
    }
}
--- End code ---
The clc is just used to get a 'pulse' to the nco clock via lc1out, manually changing polarity on each edge of the input clock. The nco still does divide by 2 as it toggles its output on each rising edge, but now any value can be used since we provide a rising edge on each clock transition. The LC1OUT is clocked on Q1, so you are then somewhat tied to fosc a little and lose total async (if important). CLC1 output and NCO1CLK input are on the same pin, but I don't think you could get both to work (could try, though)- then you would be about as async as possible.

rcbuck:
cv007, I don't think the NCO can be used. I don't think it is accurate enough. I don't want to depend on the processor clock for any of the timing requirements.

From reading the Microchip documents I believe the PIC10F322 will work. The only thing that is confusing about the CLC module is the output. There is no selection for CLC1OUT. However, I think that CLC1 is actually the output.

I have a PIC12F1501 that has the CLC module in it. I will test that tomorrow to see if I can get it to work.

If I can't get the CLC module to work in the PICs I will just use a larger package discrete decade divider chip.

cv007:

--- Quote --- I don't want to depend on the processor clock for any of the timing requirements
--- End quote ---
From what I read, the nco clock input, adder, output are all on their own where the adder works on the rising edge. The only processor involvement is the instructions to watch the nco flag, and load the accumulator. It seems there is no way to avoid having some instructions involved so you will always have that no matter what, but they do not affect your divided clock until you get to a speed where the instructions get in the way. With a 16MHz clock, I think a 400 khz clock input can be done (16M/4/10 instruction cycles, or whatever needed can be done before the next rising edge).

The version where the clc clocks the nco will introduce jitter on the incoming edges as the lc1out is clocked at Q1 (this version is only if odd div values needed). If the ncoclk input (ra1) works when the clc1 out (ra1) is also working (don't know), then the lc1out can be eliminated and the clc1 output directly drives the nco, and the resulting divided clock is again async to fosc.


--- Quote ---I don't think the NCO can be used. I don't think it is accurate enough
--- End quote ---
I'm not sure what that means. The nco can count to 5 just fine(from -5 to 0 anyway)- the accumulator is pre-loaded, the increment value is 1, then the accumulator is incremented by 1 on every rising edge of ncoclk. When the accumulator overflows, the nco output toggles its output (all async from what I can tell). You now reload the accumulator, and do again.

Navigation

[0] Message Index

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod