|
发表于 2013-6-28 16:19:16
|
显示全部楼层
To complete the education of the good Professor, here is a simple demo.
First, the hardware:
U2A/B form a simple (digital) multiplexer: it controls which signal to be fed into the external prescaler (U1 here). If PS_SEL is set, the external pulse train is fed into the prescaler (PS_CLK idles high here); If PS_SEL is cleared, PS_CLK (pulsed by the mcu) is fed into the prescaler.
The basic principal of reading the prescaler U1, which gzhuli laid out very early in this thread, is to switch the prescaler to count PS_CLK pulse train until its output (PS_INPUT) changes. By counting how many PS_CLK pulses are sent to the mcu to trigger a change on PS_INPUT, you know the remaining count in the prescaler (because you know the width of the prescaler used).
Here is the relevant code, in its entirety:
- #include <htc.h> //we use picc
- #include "config.h"
- #include "gpio.h" //gpio header file
- #include "delay.h" //we use software delay
- //hardware configuration
- #define OUT_PORT PORTA
- #define OUT_DDR TRISA
- #define OUTs 0xff
- #define OUT(val) OUT_PORT = (val)
- #define PS_PORT PORTB
- #define PS_DDR TRISB
- #define PS_SEL (1<<2) //switch input selection, active high (for external prescaler). low to read prescaler
- #define PS_RESET (1<<1) //start counting, active high
- #define PS_CLK (1<<3) //clock
- #define PS_INPUT (1<<0) //prescaler input
- #define PS_WIDTH (1<<(12-1)) //12-bit prescaler
- //end hardware configuration
- //initialize prescaler pins
- void ps_init(void) {
- IO_CLR(OUT_PORT, OUTs); //clear output pins
- IO_OUT(OUT_DDR, OUTs);
-
- IO_CLR(PS_PORT, PS_SEL | PS_RESET | PS_CLK); //ps_sel low -> no external pulse input is getting tot he external prescaler
- IO_OUT(PS_DDR, PS_SEL | PS_RESET | PS_CLK); //pins as output
-
- IO_IN(PS_DDR, PS_INPUT); //ps_input set as input
- }
- //read the prescaler
- unsigned short ps_read(void) {
- unsigned short tmp=0; //temporary variable
- unsigned char ps_in=ps_in=IO_GET(PS_PORT, PS_INPUT); //read the input
-
- //ps_sel should have been turned low before this routine. it is cleared here again to be safe.
- IO_CLR(PS_PORT, PS_SEL); //ps_sel low -> not counting external pulses yet.
- do {
- IO_SET(PS_PORT, PS_CLK);
- tmp+=1;
- IO_CLR(PS_PORT, PS_CLK);
- } while (IO_GET(PS_PORT, PS_INPUT)==ps_in); //wait for the prescaler's output to change -> the squeeze out the remaining numbers in the prescaler
- return PS_WIDTH - tmp;
- }
- void mcu_init(void) {
- ANSEL=0x00; //all pins gpio
- ANSELH=0x00;
- CM1CON0 = 0x00; //turn off analog comparators
- CM2CON0 = 0x00;
- //IRCF2=1, IRCF1=1, IRCF0=0; //running at 4Mhz
- }
- void main(void) {
- unsigned short tmp;
-
- mcu_init(); //initialize mcu
- ps_init(); //reset the prescaler module
-
- while(1) {
- IO_SET(PS_PORT, PS_RESET); //reset the external counter
- IO_SET(PS_PORT, PS_SEL | PS_CLK); //select the external counter -> read to read the chip -> now external signal goes to the prescaler
-
- IO_CLR(PS_PORT, PS_RESET); //counting starts
- delay_ms(100); //waste some time
- IO_CLR(PS_PORT, PS_SEL); //stop the pulse train / counting
-
- tmp = ps_read(); //read the prescaler
- OUT(tmp>>8); //output the value, msb first
- delay_ms(10);
- OUT(tmp);
- }
- }
复制代码 Two routines: ps_init() resets the relevent pins; ps_read() read the prescaler pins.
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|