ATtiny202 und CCL             

 
                      Elektronik-Labor  Bastelecke  Projekte  Mikrocontoller                        




CCL heißt Configurable Custom Logic und ist eine interessante Peripherie der Tiny0-Serie, die ich gerne ausprobieren möchte. Vorher aber soll der Brenner noch etwas komfortabler werden. Jetzt brauche ich nur noch auf pyupdi klicken, um den Chip zu brennen. Damit entfällt das lästige Kopieren des Hexfiles. Fabi hatte herausgefunden, wie man einen Arduino mit jtag2updi einsetzt und in das Atmel-Studio einbindet. Und Rainer hat die Einbindung für pyupdi hinbekommen. Man muss im Fenster External Tools den Namen des Brenners (pyupdí) und das zu startende Programm (py.exe) eingeben und die Arguments festlegen:

C:\Users\User\pyupdi.py -d tiny202 -c COM4 -b 115200 -f  $(TargetDir)$(TargetName).hex

Was von PC zu PC verschieden sein kann, ist der Dateipfad (C:\Users\User\) und die COM-Nummer (COM4). Außerdem habe ich hier eine höhere Baudrate eingegeben. Damit funktioniert es ebenfalls.




Dreifach-AND

Zurück zum eigentlichen Thema, CCL. Informationen findet man im Datenblatt und in einer Application Note von Microchip: http://ww1.microchip.com/downloads/en/AppNotes/TB3218-Getting-Started-with-CCL-90003218A.pdf  Die Quelltexte dazu findet man bei Github: https://github.com/MicrochipTech/TB3218_Getting_Started_with_CCL  Die Beispiele sind für einen ATmega4809 geschrieben. Als erstes habe ich das AND-Beispiel genommen und für den Tiny202 angepasst. Änderungen betreffen die verwendeten Ports und die Wahrheitstabelle für die gewünschte logische Funktion. Beim Tiny202 liegen die drei Eingänge an A0, A1 und A2. Der Ausgang liegt an A6. Und hier muss die Tabelle LUT0 verwendet werden, nicht aber wie im Beispiel LUT1. Mit allen erforderlichen Änderungen sieht das Programm nun so aus:

//ATtiny202 CCL 3 Input AND
#include <avr/io.h>

void PORT0_init (void);
void CCL0_init(void);

/**
 * \brief Initialize ports
 */
void PORT0_init (void)
{
    PORTA.DIR &= ~PIN0_bm;         //PA0 - LUT0 IN[0]
    PORTA.DIR &= ~PIN1_bm;         //PA1 - LUT0 IN[1]
    PORTA.DIR &= ~PIN2_bm;         //PA2 - LUT0 IN[2]
    PORTA.DIR |= PIN6_bm;           //PA6 - LUT0 output
}

void CCL0_init(void)
{

//configure inputs for used LUTs
    CCL.LUT0CTRLB = CCL_INSEL0_IO_gc    /* IO pin LUTn-IN0 input source */
                    | CCL_INSEL1_IO_gc; /* IO pin LUTn-IN1 input source */
    CCL.LUT0CTRLC = CCL_INSEL2_IO_gc;   /* IO pin LUTn-IN2 input source */   
//Configure Truth Table
    CCL.TRUTH0 = 0x80; /* Truth 1: 128 */
//Enable LUT0 output on IO pin
    CCL.LUT0CTRLA = CCL_OUTEN_bm;     /* Output Enable: enabled */
//Enable LUTs
    CCL.LUT0CTRLA |= CCL_ENABLE_bm;    /* LUT Enable: enabled */   
//Enable CCL module
    CCL.CTRLA = CCL_ENABLE_bm;         /* Enable: enabled */
}

int main(void)
{
    PORT0_init();
    CCL0_init();
    while (1)
    {
        ;       
    }
}


Und das Dreifach-AND-Gatter funktioniert wie gewünscht! Nur wenn ich A0, A1 und A2 an VCC lege, geht auch der Ausgang A7 hoch. A0 hing übrigens noch am Programmiergerät (RXD und TCD über Widerstand) und blieb im Ruhezustand high. Den Eingang A2 habe ich dann testweise an einen externen Generator gelegt. Bis über 100 kHz habe ich getestet, und konnte kein Jitter erkennen. Das bedeutet, dass tatsächlich ein völlig unabhängiges AND-Gatter gebildet wurde, das in keiner Weise vom internen Takt des Controllers abhängt. Man kann zwar auch die Eingangssignale mit dem Takt synchronisieren, aber das wird in diesem Beispiel bewusst nicht gemacht. In einem zweiten Test habe ich dann meinen Kurzwellensender ganz vorsichtig über einen Schutzwiderstand an den Eingang gelegt. Bis 24 MHz konnte das Gatter mithalten! Das öffnet ungeahnte Möglichkeiten sogar für HF-Anwendungen.



Entscheidend für die AND-Funktion war die Einstellung CCL.TRUTH0 = 0x80;. Damit ist Bit 7 in
TRUTH0 gesetzt, mit dem Ergebnis, dass alle drei Eingange 1 sein müssen, damit der Ausgang 1 wird. Man kann auch mehrere Bits gleichzeitig setzten, um eine bestimmte Funktion zu bekommen.


Inverter

Um alles etwas genauer zu verstehen, wollte ich einen einzelnen Inverter mit dem Eingang PA1 und dem Ausgang PA6 programmieren. Der Gedanke dabei war, dass man damit auch einen Oszillator bauen könnte. In diesem Fall muss ich Bit 0 setzen, damit der Ausgang hochgeht, wenn alle Eingänge low sind, CCL.TRUTH0 = 0x01; Weil ich aber nur einen Eingang brauche, wird auch nur einer definiert. CCL.LUT0CTRLB = CCL_INSEL1_IO_gc; kann auch als CCL.LUT0CTRLB = 0x50; geschrieben werden. So wird PA1 als Eingang eingerichtet.


//ATtiny202 CCL,  PA1 Inverter/Oscillator PA6
#include <avr/io.h>

void PORT0_init (void);
void CCL0_init(void);

/**
* \brief Initialize ports
*/
void PORT0_init (void)
{
PORTA.DIR &= ~PIN1_bm; //PA1 - LUT0 IN[1]
PORTA.DIR |= PIN6_bm; //PA6 - LUT0 output
}

/**
* \brief Initialize CCL peripheral
*/
void CCL0_init(void)
{

//configure inputs for used LUTs
CCL.LUT0CTRLB = CCL_INSEL1_IO_gc; /* IO pin LUTn-IN1 input source */
//Configure Truth Table
CCL.TRUTH0 = 0x01; /* Truth 0: 1 */
//Enable LUT0 output on IO pin
CCL.LUT0CTRLA = CCL_OUTEN_bm; /* Output Enable: enabled */
//Enable LUTs
CCL.LUT0CTRLA |= CCL_ENABLE_bm; /* LUT Enable: enabled */
//Enable CCL module
CCL.CTRLA = CCL_ENABLE_bm; /* Enable: enabled */
}


int main(void)
{
PORT0_init();
CCL0_init();
while (1)
{
;
}
}


In der Form funktioniert das Programm. Wenn ich PA1 an GND lege geht PA6 hoch, wenn ich PA1 an VCC legen, geht PA6 runter. Und wenn ich mit einem Widerstnd eine Gegenkopplung baue? Dann entstehen Schwingungen. Mit 10 k bekomme ich ca. 7 MHz. Ein Kondensator zwischen Eingang und GND liefert eine kleinere Frequenz. Mit 10 k und 100 nF werden es ca. 2,5 kHz. Aus dem Verhältnis 7000 kHz / 2,5 kHz kann man die Kapazität des Eingangs und des Aufbaus mit 35 pF abschätzen. Wenn ich allerdings 1 k verwende, steigt die Frequenz nicht auf 70 MHz, sondern nur auf 17,8 MHz. Und eine direkte Drahtverbindung zwischen Eingang und Ausgang liefert 32 MHz. Daraus ergibt sich eine Gatterlaufzeit von ca. 30 ns.



Der Oszillator funktioniert bei kleineren Frequenzen so schön, als wäre er mit einem NE555 gebaut. Das bedeutet, dass der Eingang eine Hysterese haben muss. Ein Blick auf den Eingang zeigt tatsächlich eine Hysterese von etwa einem Volt. Jedenfalls hat die CCL-Einheit hier einen ersten praktischen Nutzen. Man kann sich einen zuverlässigen RC-Oszillator ohne ein zusätzliches IC bauen.









Elektronik-Labor  Bastelecke  Projekte  Mikrocontoller