So, hier die versprochenen Code-Schnippsel.
Das ganze ist eher als Anregung gedacht und eigentlich nur Pseudo-Code, weil nicht alle Haeder dabei sind. Es sind nur die relevanten stellen, die für ne C-Messung gebraucht wurden. Der Code ist recht antik, undokumentiert und war auch nicht für's breite Publikum gedacht...

Das ganze drumrum hab ich weggelassen wie Taster abfragen, VFD-Routinen, etc

Laufen tut das auf einem AT90S2313 mit 8MHz Keramik.

Hier wird nur der C geladen und die Zeit in Ticks gemessen.

Code:
#include "capacity.h"
//#include "morse.h"

extern void ioinit(); 
extern void wait_10ms (const byte);

// Multiplikator:
// k = (ny * R * ln 2)^{-1}
// mit ny = 8MHz und R = 10k:

// k = 18pF / Inkrement

word measure_time (byte loadTime)
{
	// Load capacity via AIN+ push-pull
	SET (PORT_AIN_POS); MAKE_OUT (PORT_AIN_POS);
	wait_10ms (loadTime);

	// disable all interrupts
	cli();
	
	// stop timer1
	TCCR1B = 0;
	
	// enable AC (ACD = 0)
	// AC Input Capture on -> connect to Input Capture of Timer/Counter1
	// AC Interrupt on Falling Output Edge
	ACSR = _BV(ACIC) | _BV (ACIS1);
	
	// disconnect timer1 from output pin OC, no PWM
	TCCR1A = 0;
	
	// reset timer1 to 0
	TCNT1 = 0;
	
	// clear Timer1 Overflow and InputCapture Flags
	TIFR = _BV (TOV1) | _BV (ICF1);
	
	// start timer 1 at full speed
	// no clear on compare match
	// no noise cancel
	// input capture edge = falling
	TCCR1B = _BV (CS10);

	// here we go! 
	// start discharging via external resistor
	// AIN+ to high Z
	MAKE_IN (PORT_AIN_POS); CLR (PORT_AIN_POS); 
	
	byte flag;
	
	do
	{
		flag = TIFR & (_BV (TOV1) | _BV (ICF1));
	} while (flag == 0);
	
	if (flag & _BV (TOV1))
		return 0xffff;
		
	return ICR1;
	
	// restore status of machine
//	ioinit();
	
//		morse (_O_);
//	if (flag & _BV (ICF1))
		
//		morse_dec (capture-4);
//		morse (_FRAGE_);
}
Und hier etwas von dem Geklimper drumrum: Umrechnen in Kapazität, Messbereich auswählen, Kalibrierung, etc
Code:
#include "ports.h"
#include "main.h"
#include "util.h"
#include "taster.h"
#include "timer.h"

#include "vfd.h"
#include "capacity.h"

extern void ioinit(); 

static unsigned long mul_ww (word, word);
static void measureC (byte doCallibrate);
static void put_decimal (byte pos, word val, byte dot);
static word callibra[3] = {3, 3, 3};

enum
{
	OHM_1M = 0,
	OHM_47K = 1,
	OHM_1K5 = 2
};


#define	CONST_1M   687995.        /* 0M993    */
#define	CONST_47K   32140.        /*    46K8  */ 
#define	CONST_1K5     759.5       /*     1K49 */

// doCallibrate == 0: C bestimmen und anzeigen
// doCallibrate != 0: C bestimmen und callibrate[] damit besetzen
void measureC (byte doCallibrate)
{
	word capval;

	char dim;
	char toobig;
	byte ohm;
	word const_R;
	byte loadTime;
	byte dot;

	ioinit();
#if VFD	
	vfd_reset (1);
#endif	
	vfd_clear();
	vfd.bright = 0;
	vfd.cursor_on = 0;
	vfd.cursor_blink = 0;
	vfd_init ();

	for (ohm = OHM_1M; ohm <= OHM_1K5; ohm++)
	{
		switch (ohm)
		{
			default:
			case OHM_1M:
				MAKE_IN (PORT_RELAIS1); CLR (PORT_RELAIS1);
				MAKE_IN (PORT_RELAIS2); CLR (PORT_RELAIS2);
				const_R = (word) (1.01*1e12*65536./(XTAL_PHI * CONST_1M)); // 1pF
				loadTime = 20;
				dot = 0;
				dim = 'p';
				break;
			case OHM_47K:
				MAKE_OUT (PORT_RELAIS1); SET (PORT_RELAIS1);
				MAKE_IN  (PORT_RELAIS2); CLR (PORT_RELAIS2);
				const_R = (word) (1.01*1e10*65536./(XTAL_PHI * CONST_47K)); // 100pF
				loadTime = 40;
				dot = 1;
				dim = 'n';
				break;
			case OHM_1K5:
				MAKE_OUT (PORT_RELAIS1); SET (PORT_RELAIS1);
				MAKE_OUT (PORT_RELAIS2); SET (PORT_RELAIS2);
				const_R = (word) (1.17*1e9*65536./(XTAL_PHI * CONST_1K5)); // 1nF
				loadTime = 150;
				dot = 0;
				dim = 'n';
				break;
		}
	
		wait_10ms (10);
		
		capval = measure_time (loadTime);
		
		toobig = (0xffff == capval);
		
		if (doCallibrate)
		{
			if (toobig)
				break;
			callibra[ohm] = capval-3;
		}
		else
		{
			if (!toobig)
			{
				capval -= callibra[ohm];
				capval = (word) (mul_ww (const_R, capval) >> 16);
				break;
			}
		}
			
		ioinit();
	}
	ioinit();		
	
	vfd.bright = 4;
	vfd_init ();
		
	if (toobig)
	{
		static const prog_char STR_C_ZU_GROSS[] = "C zu groß";
		if (doCallibrate)
		{
			vfd_pos_string_P (0x03, STR_C_ZU_GROSS);
			vfd_pos_string_P (0x40, PSTR("zum kalibrieren"));
		}
		else
			vfd_pos_string_P (0x43, STR_C_ZU_GROSS);
			
		return;
	}

	if (doCallibrate)
	{
		vfd_pos_string_P (0x03, PSTR("Kalibriert"));
		return;
	}
	
	if (ohm == OHM_1K5)
	{
		if (capval > 1000)
		{
			capval = (word) (mul_ww (capval, (word) (65536./10.)) >> 16);
			dim = 0xe4; // my
			dot = 2;
		}
	}
	if (ohm == OHM_1M)
	{
		if (capval > 1000)
		{
			dim = 'n';
			dot = 3;
		}
	}
	vfd_pos_char (0x40, '0'+ohm);
	put_decimal (0x48, capval, dot);
	vfd_pos_char (0x4a, dim);
	vfd_pos_char (0x4b, 'F');
}

void put_decimal (byte pos, word val, byte dot)
{
	byte i = 0;
	do
	{
		word r,d;
		divmod10 (d, r, val);
		vfd_pos_char (pos--, '0' + (byte) r);
		val = d;
		i++;
		if (i == dot)
			vfd_pos_char (pos--, '.');
	} while (val);
}

#if 1
//	return (a*b) >> 16
unsigned long mul_ww (word _a, word b)
{
	unsigned long ab = 0;
	unsigned long a = _a;
	
	while (1)
	{
		if (b & 1)
			ab += a;
			
		b >>= 1;
		if (b==0)
			return ab;
		a <<= 1;
	}
}
#endif