Krumeltee

-> Elektronik, Mikrocontroller und Retro-Computing <-

TLC540 8Bit, 11/12 Channel, AD-Wandler am AVR

Posted by krumeltee - 20. August 2011

Der TLC540 hat 12Analog- Kanäle, wovon 11 Kanäle auf Pins herausgeführt sind. Der Zwölfte Kanal ist für eine interne Referenzspannung benutzt worden um den Controller eine Art „Selbsttest“ machen lassen zu können.

Die 11 Kanäle werden mit einer Auflösung von  8 Bit gewandelt, die Geschwindigkeit pro Wandlung ist laut Datenblatt in etwa 17µS, dort ist allerdings noch nicht die Übertragung usw mit eingerechnet, nur die Wandlung im Chip an sich.

Mit meiner Software komme ich für eine AD-Wandlung auf etwa 45µS, was wohl so ziemlich an der Grenze des Machbaren liegt. Der TLC540 besitzt zwei unabhängige Clocks. Einen Systemtakt und einen IO-Takt. Der Systemtakt treibt die Wandlungen voran, der IO-Takt startet die Wandlungen und schiebt die Daten raus.

System-Clock ist laut Datenblatt mit 4,1Mhz angeben, IO-Clock mit 2Mhz. Meine Software liefert einen Systemtakt von 4,22Mhz und einen IO-Clock von 2Mhz. Der Systemtakt ist also mit etwa 0,12Mhz „übertaktet“. Der Grund dafür ist, dass die Software so etwas einfacher ist und stören tuts auch nicht. Ich habe mir das sehr genau angesehen und ausprobiert. Der ADC funktioniert so ohne irgendwelche Probleme.

Insgesamt habe ich so 12 verschiedene TLC540 probiert, keine Probleme aufgetreten.

Die Software von mir für den TLC540 ist ganz einfach für beliebig viele TLCs anpassbar. In meinem Beispiel hier verwende ich zwei, es funktioniert allerdings genauso mit einem, ohne eine Zeile Code ändern zu müssen. Man darf einfach nur die Channels 0-11 abfragen, 12-23 sind am zweiten AD-Wandler.

Mein Beispielprogramm ist für einen ATMega16 geschrieben, welcher mit 8Mhz läuft. Die 8Mhz können problemlos vom internen Taktgeber ezeugt werden, es ist also nicht unbedingt ein Quarz nötig.

/* tlc540.c 
* driver for the tlc540 ad converter
* tlc540:
* 8bits resolution
* 17µS/conversion
* 11 channels + 1 internal test channel, connected to a test reference
* serial interface
* independent SYSTEM and SERIAL clocks
* SYSTEM clock up to 4mhz
* SERIAL clock up to 2,1mhz
* 
* (c) 2011 krumeltee, email: <nils.stec@googlemail.com>
* 
* this code is free software. you can use it and do with it whatever you like.
* if you redistribute this code or parts of it, please let there be a note
* with a link to the source of the code and the author.
* 
* this driver was written for a AVR ATmega16 running with internal clock source
* at 8mhz.
* a ctc timer generates a ~4.22mhz system clock for the TLC540. This slightly
* overclocks the chip (~0.12mhz = 122khz). It works great with 12 chips i have
* tested so far.
* the i/o clock is generated by the spi master hardware interface of the avr,
* with a frequency of 2mhz. 
* 
* this driver supports as many converters connected to your microcontroller
* as you have pins for Chip Select on each AD-Converter.
* i've tested 12 chips on my mega16, it worked.
* 
* the code is well commented and you should easily find out how to add more chips.
* now the code is configured for 2 chips, connected this way:
* 
* AVR | Chip1 | Chip2
* ------------|----------------|--------------
* SCK (PB7) | IO Clock | IO Clock
* MISO (PB6) | DATA OUT | DATA OUT
* MOSI (PB5) | ADR IN | ADR IN
* OC1A (PD5) | SYS CLOCK | SYS CLOCK
* SS (PB4) | CHIP SELECT | 
* PB3 | | CHIP SELECT
* 
* The speed of my tlc540() function is about 45µS for 1 conversion with the speed 
* settings written above. This results in about 22222.2 conversions per second.
*/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "lcd.h"

#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include <util/delay.h>

unsigned char tlc540(unsigned char channel) {
    unsigned char config_byte, i;

    PORTB |= (1<<PB4);    // SET CS, disable chip 0
    PORTB |= (1<<PB3);    // SET CS, disable chip 1

    if(channel <= 11) {
        PORTB &= ~(1<<PB3);        // CLR_CS enable chip 0 
    } else if(channel <= 23) {
        PORTB &= ~(1<<PB4);        // CLR_CS enable chip 1
        channel -= 12;
    }

    config_byte  = channel<<4;        // AD channel Y (YYYYxxxx) MSB .... LSB

    _delay_us(6);          // after enabling a chip wait at least 2 rising + the second falling edges of system clock

    SPDR = config_byte;        // set + get data
    while(!(SPSR & (1<<SPIF)));    

    for(i = 0; i < 36; i++) {    // 36 clock cycles to do the next conversion
        PORTB |=(1<<PB7);
        PORTB &=~(1<<PB7);
    }

    // make sure all chips are disabled, so we simply disable ALL cs
    PORTB |= (1<<PB3);
    PORTB |= (1<<PB4);

    return SPDR;    // our AD-value 
}

int main (void) {
    DDRB |= (1<<PB4);    // CS ad chip 0
    DDRB |= (1<<PB3);    // CS ad chip 1
    DDRB |= (1<<PB2);    // CS sr 0

    DDRB &= ~(1<<PB6);    // DATA (data from adc to controller)
    PORTB |= (1<<PB6);    // pullup

    DDRB |=(1<<PB7);    // Serial Clock

    DDRB |= (1<<PB5);    // ADRIN (adress input of adc)

    DDRD |= (1<<PD5);    // SYSTEM Clock via OC1A (CTC timer1)
    TCCR1A |=(1<<COM1A0);   // OC1A toggle on compare match
    TCCR1B |=(1<<WGM12);    // CTC mode 4
    TCCR1B |=(1<<CS10);     // no prescaling
    OCR1A=0x0;        // ~4,22mhz system clock @8mhz avr
                // use OCR1A = 0x01 for 16mhz

    SPCR = (1<<SPE)|(1<<MSTR);    // spi enable, master
    SPSR = 0;            // spi freq f_cpu/4 ~2mhz @ 8mhz avr
                    // use f_cpu/8 prescaler for 16mhz

    lcd_init(LCD_DISP_ON);
    lcd_clrscr();    
    sei();

    char buffer[17];
    unsigned char ad_result;
    int i;

    for(;;) {
        for(i = 0; i < 24; i++) {
            ad_result = tlc540(i);
            sprintf(buffer, "channel %02d: $%02x", i, ad_result);
            lcd_gotoxy(0,0);
            lcd_puts(buffer);
            //_delay_ms(1000);
        }
    };
}

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

 
%d Bloggern gefällt das: