Electronics > Projects, Designs, and Technical Stuff
Small package decade counter?
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
Go to full version