| ??? 05/27/07 08:29 Modified: 05/27/07 09:01 Read: times |
#139889 - No Extra Hardware Needed Responding to: ???'s previous message |
You could implement this as a straightforward polled pins microcontroller application. To demonstrate the performance possibilities lets say that you implemented an MCU that had 16 inputs on two byte wide ports. If you polled the two ports repeatedly you could keep track of the pulse counts for all 16 of the inputs using code like that shown below. The sample code implements 16-bit counters for each of the inputs so that you can count many pulses on each input.
If this was implemented on an MCU such as a SiLabs C8051F226 part running at 25MHz you can detect properly for 16 inputs with high pulse widths up to 14usec wide and a period of 28usec. To leave a little margin estimate that this corresponds to detecting pulses for frequencies up to about 32 KHz @ 50% duty cycle. The 16-bit counters implemented would be able to count pulses for up to 2 seconds without overflow at this upper rate. Included in the code is a short subroutine to fetch out any one of the 16 counters from the array of bytes that hold the counter values. Michael Karas
$XREF
$PL(78) PW(119)
$DEBUG
$SYMBOLS
$NOMOD51
#define CYGNAL_DEBUG 1 // set non-zero for enable of code mode for
// cygnal debug platform.
#if CYGNAL_DEBUG
$include(c8051f200.inc) ; register definitions compatible
; with Cygnal C8051F200
#else
$include(REG51FX.INC) ; register definitions compatible
; with standard Intel architecture FX cpu
#endif
;***************************************************
; SETUP THE NAMES OF THE SEGMENTS
;---------------------------------------------------
BITS_SEG SEGMENT BIT
DATA_SEG SEGMENT DATA
BUFF_SEG SEGMENT IDATA
CODE_SEG SEGMENT CODE
;***************************************************
; DATA ALLOCATIONS AND BUFFER SPACES
;---------------------------------------------------
;
;
; Variables and buffers
;
RSEG BITS_SEG
TEST_BIT:
DBIT 1 ; sample bit declaration
;
RSEG DATA_SEG
PREV_LO:
DS 1 ; previously sampled port 2
PREV_HI:
DS 1 ; previously sampled port 3
COUNTERS:
DS 32 ; array of counter values - a total
; of 16 counters of 16-bits each stored
; in low / high byte order
;
;
; stack support
;
RSEG BUFF_SEG
STACK:
DS 10 ; reserve 10 bytes of space
;***************************************************
; INTERRUPT VECTOR DEFINITIONS
;---------------------------------------------------
CSEG AT 0000H ; reset vector
JMP POWER_UP ; power-on entry point
CSEG AT 0003H ; intr 0 vector
CLR EX0 ; external int 0
RETI ; not used
CSEG AT 000BH ; timer 0 vector
RETI ; not used
CSEG AT 0013H ; intr 1 vector
CLR EX1 ; external int 1
RETI ; not used
CSEG AT 001BH ; timer 1 vector
RETI ; not used
CSEG AT 0023H ; UART vector
RETI ; not used
;***************************************************
; BASE OF CODE AREA
;---------------------------------------------------
RSEG CODE_SEG
USING 0 ; use register block 0
;***************************************************
; MAIN PROGRAM INITIALIZATION
;---------------------------------------------------
POWER_UP:
MOV SP, #STACK ; set stack pointer
#if CYGNAL_DEBUG
; disable watch dog timer
MOV WDTCN, #0DEh ; Disable the WDT.
MOV WDTCN, #0ADh ; 2nd move to WDTCN must be within
; 4 clocks of first so watch IRQs
; Configure the PRTnMX Registers
MOV PRT0MX, #005h ; PRT0MX: Initial Reset Value
; bit 2="1" enables /INT0 pin
; bit 0="1" enables TxD and RxD pins
MOV PRT1MX, #000h ; PRT1MX: Initial Reset Value
MOV PRT2MX, #000h ; PRT2MX: Initial Reset Value
; Select Pin I/0
; Port configuration (1 = Push Pull Output)
MOV PRT0CF, #001h ; Output configuration for P0
; bit 0="1" enables TxD pin as push pull output
MOV PRT1CF, #000h ; Output configuration for P1
MOV PRT2CF, #000h ; Output configuration for P2
MOV PRT3CF, #000h ; Output configuration for P3
MOV P0MODE, #0FFh ; Input Configuration for P0
MOV P1MODE, #0FFh ; Input Configuration for P1
MOV P2MODE, #0FFh ; Input Configuration for P2
MOV P3MODE, #0FFh ; Input Configuration for P3
; enable the external oscillator
MOV OSCXCN, #067h ; External Oscillator Control Register
CLR A
DJNZ ACC, $ ; wait for
DJNZ ACC, $ ; at least 1ms
OX_WAIT:
MOV A, OSCXCN
JNB ACC.7, OX_WAIT ; poll XTLVLD
;
MOV A, OSCICN ; Internal Oscillator Control Register
SETB ACC.3 ; set for external clock to be used
MOV OSCICN, A
CLR A
MOV CKCON, A ; ensure timers T0, T1 & T2 run with /12 clocks
#endif
;
;
; main loop to poll 16 inputs from a port (P3::P2) and increment counters for
; inputs that have a change in the input state. The counters are stored as an
; array of 16-bit low/high counters at the COUNTERS local RAM buffer.
;
; The main loop uses the B register to hold the edge detect and carry bits
; during the computational algorithm.
;
MOV A, P2 ; initialize the initial NOT prev_lo
CPL A
MOV PREV_LO, A
MOV A, P3 ; initialize the initial NOT prev_hi
CPL A
MOV PREV_HI, A
MAIN_LOOP: ; main processing task
; setup pointer to the counters
MOV R0, #COUNTERS
; edge detect logic for port 2 bits
MOV B, P2 ; get the port value
MOV A, PREV_LO
ANL A, B ; edge bits
XCH A, B ; save edge bits to B and get port_val to A
CPL A ; save NOT port bits to prev_lo
MOV PREV_LO, A
;
; increment low counters with pulse detects
MOV R1, #8 ; counter for low counters loop
BUMP_0_7:
MOV A, B
RRC A ; get increment bit for a counter
MOV B, A
CLR A
ADDC A, @R0 ; bump low byte of counter
MOV @R0, A
INC R0
CLR A
ADDC A, @R0 ; bump high byte of counter
MOV @R0, A
INC R0
DJNZ R1, BUMP_0_7
;
; edge detect logic for port 3 bits
MOV B, P3 ; get the port value
MOV A, PREV_LO
ANL A, B ; edge bits
XCH A, B ; save edge bits to B and get port_val to A
CPL A ; save NOT port bits to prev_lo
MOV PREV_LO, A
;
; increment high counters with pulse detects
MOV R1, #8 ; counter for high counters loop
BUMP_8_15:
MOV A, B
RRC A ; get increment bit for a counter
MOV B, A
CLR A
ADDC A, @R0 ; bump low byte of counter
MOV @R0, A
INC R0
CLR A
ADDC A, @R0 ; bump high byte of counter
MOV @R0, A
INC R0
DJNZ R1, BUMP_8_15
;
SJMP MAIN_LOOP
;***************************************************
;NAME: GET_CNT
; Used to extract a count value from the counter
; byte array.
; Entry A is the 0-15 counter number
; Exit B::A is the counter 16-bit value
;---------------------------------------------------
GET_CNT:
ANL A, #0FH ; make nibble index to array of counter data
RL A ; *2 because the counters are 2 bytes each
ADD A, #COUNTERS+1
MOV R0, A ; R0 is index to requested counters high byte
MOV A, @R0 ; get the low byte of the counter
MOV B, A
DEC R0 ; bump pointer to high byte
MOV A, @R0
RET
;
END
|
| Topic | Author | Date |
| 12 parallel pulses counting | 01/01/70 00:00 | |
| How fast are these pulses? | 01/01/70 00:00 | |
| pulses speed | 01/01/70 00:00 | |
| More info | 01/01/70 00:00 | |
| Pulse rate | 01/01/70 00:00 | |
| Isn't it slightly more complicated? | 01/01/70 00:00 | |
| Stretching pulses | 01/01/70 00:00 | |
| Another Quick Way | 01/01/70 00:00 | |
| Sampling timer with a buffer | 01/01/70 00:00 | |
| Showing Vertical Couners | 01/01/70 00:00 | |
| Yes other interrupt are also there | 01/01/70 00:00 | |
| Avoid using interrupts where possible | 01/01/70 00:00 | |
| Run signals frequency... | 01/01/70 00:00 | |
| PLC can be dirt cheap | 01/01/70 00:00 | |
| PLCs | 01/01/70 00:00 | |
an xcellent idea | 01/01/70 00:00 | |
| Sample with 2 74LS165 parallel loadShiftRegisiters | 01/01/70 00:00 | |
| would not the output pins drop... | 01/01/70 00:00 | |
| No Extra Hardware Needed | 01/01/70 00:00 | |
| No Extra Hardware Needed - I do not agree | 01/01/70 00:00 |



