??? 05/27/07 09:03 Read: times |
#139890 - Showing Vertical Couners Responding to: ???'s previous message |
To show an implementation of the vertical counters idea I decided to code this up. To demonstrate the performance possibilities lets say that you implemented an MCU that had 8 inputs on one byte wide port. If you polled the port repeatedly you could keep track of the pulse counts for all 8 of the inputs using code like that shown below. The sample code implements 8-bit counters for each of the inputs so that you can count up to 255 pulses before having to deal with overflow.
If this was implemented on an MCU such as a SiLabs C8051F226 part running at 25MHz you can detect properly for 8 inputs with high pulse widths up to 3.6usec wide and a period of 7.2usec. To leave a little margin estimate that this corresponds to detecting pulses for frequencies up to about 125 KHz @ 50% duty cycle. The 8-bit vertical counters implemented would be able to count pulses for up to 2 msec without overflow at this upper rate. Included in the code is a short subroutine to fetch out any one of the 8 counters from the array of bytes that hold the vertical counter values. The extraction code has not been optimized and there are probably more time efficient ways to write that part. 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_VAL: DS 1 ; previously sampled port value ; BIT0_VAL: DS 1 ; bit 0 of the counters (LSB) BIT1_VAL: DS 1 ; bit 1 of the counters BIT2_VAL: DS 1 ; bit 2 of the counters BIT3_VAL: DS 1 ; bit 3 of the counters BIT4_VAL: DS 1 ; bit 4 of the counters BIT5_VAL: DS 1 ; bit 5 of the counters BIT6_VAL: DS 1 ; bit 6 of the counters BIT7_VAL: DS 1 ; bit 7 of the counters ; ; ; 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 8 inouts from a port (P3) and increment counters for ; inputs that have a change in the input state. The counters are implemented ; as vertical bit slices in a series of 8 bytes. ; ; The main loop uses the B register to hold the edge detect and carry bits ; during the computational algorithm. ; MOV A, P3 ; initialize the initial NOT prev_val CPL A MOV PREV_VAL, A MAIN_LOOP: ; main processing task ; edge detect logic MOV B, P3 ; get the port value MOV A, PREV_VAL 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_val MOV PREV_VAL, A ; ; perform bit serial increments into the vertical counters ; MOV A, BIT0_VAL ; compute the next stage carry bits ANL A, B ; ...CYout = BIT * CYin XCH A, B ; save the new carry and get previous XRL BIT0_VAL, A ; compute XOR add for bits 0 ; MOV A, BIT1_VAL ; compute the next stage carry bits ANL A, B ; ...CYout = BIT * CYin XCH A, B ; save the new carry and get previous XRL BIT1_VAL, A ; compute XOR add for bits 1 ; MOV A, BIT2_VAL ; compute the next stage carry bits ANL A, B ; ...CYout = BIT * CYin XCH A, B ; save the new carry and get previous XRL BIT2_VAL, A ; compute XOR add for bits 2 ; MOV A, BIT3_VAL ; compute the next stage carry bits ANL A, B ; ...CYout = BIT * CYin XCH A, B ; save the new carry and get previous XRL BIT3_VAL, A ; compute XOR add for bits 3 ; MOV A, BIT4_VAL ; compute the next stage carry bits ANL A, B ; ...CYout = BIT * CYin XCH A, B ; save the new carry and get previous XRL BIT4_VAL, A ; compute XOR add for bits 4 ; MOV A, BIT5_VAL ; compute the next stage carry bits ANL A, B ; ...CYout = BIT * CYin XCH A, B ; save the new carry and get previous XRL BIT5_VAL, A ; compute XOR add for bits 5 ; MOV A, BIT6_VAL ; compute the next stage carry bits ANL A, B ; ...CYout = BIT * CYin XCH A, B ; save the new carry and get previous XRL BIT6_VAL, A ; compute XOR add for bits 6 ; MOV A, BIT7_VAL ; compute the next stage carry bits ANL A, B ; ...CYout = BIT * CYin XCH A, B ; save the new carry and get previous XRL BIT7_VAL, A ; compute XOR add for bits 7 ; SJMP MAIN_LOOP ;*************************************************** ;NAME: BIT_MSK ; Used to convert a bit number to a byte mask ; Entry A is the 0-7 bit number ; Exit A is the bit mask ;--------------------------------------------------- BIT_MSK: INC A MOVC A, @A+PC RET ; DB 00000001B ; Bit 0 <- 0 DB 00000010B ; Bit 1 <- 1 DB 00000100B ; Bit 2 <- 2 DB 00001000B ; Bit 3 <- 3 DB 00010000B ; Bit 4 <- 4 DB 00100000B ; Bit 5 <- 5 DB 01000000B ; Bit 6 <- 6 DB 10000000B ; Bit 7 <- 7 ;*************************************************** ;NAME: GET_CNT ; Used to extract a count value from the vertical ; counter bytes. ; Entry A is the 0-7 counter number ; Exit A is the counter value ;--------------------------------------------------- GET_CNT: CALL BIT_MSK ; get bit mask from counter # MOV B, A ; save mask in B ; CLR A ; inital clear accumulate value PUSH ACC MOV A, BIT0_VAL ANL A, B ADD A, #0FFH ; shift bit to carry POP ACC RRC A ; PUSH ACC MOV A, BIT1_VAL ANL A, B ADD A, #0FFH ; shift bit to carry POP ACC RRC A ; PUSH ACC MOV A, BIT2_VAL ANL A, B ADD A, #0FFH ; shift bit to carry POP ACC RRC A ; PUSH ACC MOV A, BIT3_VAL ANL A, B ADD A, #0FFH ; shift bit to carry POP ACC RRC A ; PUSH ACC MOV A, BIT4_VAL ANL A, B ADD A, #0FFH ; shift bit to carry POP ACC RRC A ; PUSH ACC MOV A, BIT5_VAL ANL A, B ADD A, #0FFH ; shift bit to carry POP ACC RRC A ; PUSH ACC MOV A, BIT6_VAL ANL A, B ADD A, #0FFH ; shift bit to carry POP ACC RRC A ; PUSH ACC MOV A, BIT7_VAL ANL A, B ADD A, #0FFH ; shift bit to carry POP ACC RRC A ; 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 |