#include #include #include #include // Copyright 2004-2005 by JDF of GhostGadgets.com // Written by JDF - info@GhostGadgets.com // Rev. B, Released 06-30-2005 // 06-30-2005: Fixed timing issues with need delays for TLC1542 // Driver for the 10 bit TLC1542 11 channel A/D Converter // Compiling the c driver code in Linux (output file will be adc_driver): cc 10BitDriver.c -o adc_driver // The function that takes samples is called "getSample(int Channel)", in which you would pass the integer // of the channel you want to read (1 - 11), and then the voltage reading on that channel is then returned // as a double after sampling. Included is a main() function that prints a test reading of each channel. // Define addresses int writePort = 0x378; int readPort = 0x379; // Define port write hex codes int ioclk = 0x2; int cs = 0x4; int address = 0x8; // Define port read hex codes int EOC = 0x20; int data = 0x40; static int Value; static int i; double getSample(int Channel); // Declare this function float getmS(void); void mS_Delay(float Time); struct timeval tv; // Used for timestamps unsigned long offsetTime; // Use this to subtract from seconds // Pause for x mS void mS_Delay (float Time) { float DelayTime = getmS(); while ((getmS() - DelayTime) < Time) { } } // Return the time elapsed in mS (with resolution to microseconds!) float getmS () { gettimeofday(&tv,NULL); return ( ((tv.tv_sec - offsetTime) *1000) + ((float)tv.tv_usec / 1000) ); } // Send in channel address // Then read in results after conversion is done // These two passes could be shorted to run faster if needed double getSample(int Channel) { // Decrease Channel by 1 (convert to computer counting mode) --Channel; // CS High & 60 uS settle time mS_Delay(.06); outb(cs,writePort); // Make sure EOC is high and safe to sample, if low wait for it while (((inb(readPort) & EOC) >> 5) == 0) {} // 10 uS CS settle, CS Low & 2 uS delay settle time mS_Delay(.01); outb(0,writePort); mS_Delay(.002); // Read in channel address to chip for (i=0;i<12;i++) { // output the address MSB, also makes I/O Clock low // address is 1000 outb((Channel & address),writePort); // Tap I/O Clock high so it is ready for the next bits outb(ioclk,writePort); // Move to next bit of Channel address, if past the end zeros outputed. Channel <<= 1; } // CS High & 60 uS settle time mS_Delay(.06); outb(cs,writePort); // Initialize value Value = 0; // Make sure EOC is high and safe to sample, if low wait for it while (((inb(readPort) & EOC) >> 5) == 0) {} // 10 uS CS settle, CS Low & 2 uS delay settle time mS_Delay(.01); outb(0,writePort); mS_Delay(.002); // Get conversion results from previous read in for (i=0;i<12;i++) { // output the address MSB, also makes I/O Clock low // address is 1000 outb((Channel & address),writePort); // read in data bits MSB first (shift right so data bit is 1 or 0 // then shift Value left 1 and add in next bit) Value = (((inb(readPort) & data) >> 6) | (Value << 1)); // Tap I/O Clock high so it is ready for the next bits outb(ioclk,writePort); } // CS High & 60 uS settle time mS_Delay(.06); outb(cs,writePort); // Convert Value to volts & return results return (((Value / 1.024)/1000) * 5); } // End function getSample // Test function to sample once from each channel int main() { // Request access to Read/Write Port // Only needed in Linux Systems ioperm(writePort, 1, 1); ioperm(readPort, 1, 1); // Done requesting access // Initialize the time functions and set offset gettimeofday(&tv,NULL); offsetTime = (unsigned long)tv.tv_sec; // Declare the inital offset time (so getmS isn't REAL big!) printf("\n\n"); // Print channel readings from 1 - 11 int ch; for (ch=1; ch<=11; ch++) { printf("\tTest Input From Channel %d: %f\n",ch,getSample(ch)); } printf("\n"); // Return access to Read/Write Port // Only needed in Linux Systems ioperm(writePort, 1, 0); ioperm(readPort, 1, 0); // Done returning access return 1; } // End method main