
tinyAVR0-Controller mit UPDI

Der ATTiny202/402
Fabian hat mich auf eine neue, besonders sparsame
Mikrocontroller-Familie von Atmel/Microchip aufmerksam gemacht. Der
kleineste Vertreter ist der ATtin202 mit 2 kB und acht Beinchen, einer
der größten ist der ATtiny1616 mit 16 kB und 20 Beinchen. Alle diese
Controller haben die UPDI-Schnittstelle (Unified Program and Debug
Interface). Man braucht hier nur einen Pin, und das ist der
Reset-Anschluss, der sonst ohnehin meist frei bleibt.
Als ich mir die Details im Datenblatt des ATtiny202 angesehen habe, war
ich gleich Feuer und Flamme. Es handelt sich um eine bidirektionale
serielle Schnittstelle mit automatischer Baudraten-Erkennung. Damit
kann man den Flash-Speicher beschreiben, aber auch jedes andere
Register und RAM-Inhalte auslesen oder beschreiben. Alles ist bis ins
letzte Detail im Datenblatt beschrieben. Ich hatte schon überlegt, wie
man die TXD- und die RXD-Leitung einer seriellen Schnittstelle
zusammenführen kann, um die Programmierung per UPDI anzusteuern. Aber
dann habe ich eine genial einfache und fertig programmierte Lösung im
Netz gefunden:
https://npk-stn.ru/2019/07/19/simple_programming_attiny414_via_updi/?lang=en
Der UPDI-Pin kommt an RXD, und von da geht ein Widerstand mit 4,7 k an
TXD. Fertig, das ist alles an Hardware. Dazu gibt es dann ein
Python-Skript, das ein Hexfile in den Chip brennt. Fabi hatte schon
einige Tiny202 und Tiny402 bestellt. Zwei sind bei mir gelandet, sodass
ich es gleich einmal probieren konnte.
Für
den ersten Test habe ich meine Ft232-Platine eingesetzt. Sie liefert
die Betriebsspannung von 5 V und das Programmiersignal. Der
erforderliche Widerstand von 4,7 k ist mit auf die USB-Platine
gesteckt. Zur Programmierung habe ich das AVR Studio 7.0 verwendet. Bisher war
ich damit nicht warm geworden, weil die Software sehr groß ist, einen
schnellen PC erfordert und mir sehr kompliziert vorkam. Aber nun habe
ich das Studio 7 auf meinem Win10-Rechenr installiert. Ich konnte bei
der Installation einstellen, dass nur die 8-Bit-AVR-Controller
unterstützt werden, so blieb die Installation überschaubar.
Ein erstes Projekt für den ATtiny202 war schnell gestartet. Im
Hintergrund arbeitet dann GCC. Einige Bezeichnung sind ganz anders als
ich es gewohnt war. Aber die Software bietet umfangreiche Hilfen. Wenn
ich PortA tippe, erscheint ein Fenster mit den möglichen Registern.

Am Ende stand das einfachste mögliche Programm, wobei ich ohne Wartezeit mit einem Port klappere.
Mit Build/ Build Solution ließ sich das Projekt fehlerfrei übersetzen.
Das fertige Hex-File findet sich dann im Debug-Ordner des Projekts.
Nach den Anweisungen auf der oben angegebenen Seite habe ich dann
pyupdi.py von Github geladen und in C:\Users\User\ kopiert. Dann wurde
es noch etwas kompliziert, weil ich einige Bibliotheken wie z.B.
pyserial nachinstallieren musste, was mir mangels Python
-Erfahrungen auf dem PC schwer fiel. Fabi hat mir dann geholfen, und am
Ende hat alles funktioniert. Das Hexfile muss ebenfalls in
C:\Users\User\ kopiert werden. Dann öffne ich die Eingabeaufforderung
und starte das Skript mit:
C:\Users\User>py pyupdi.py -d tiny202 -c COM4 -b 9600 -f GccApplication1.hex
(Python wurde abgekürzt mit py aufgerufen, weil an meinem PC unter
Windows10 ansonsten der Microsoft App-Store erscheint. Denn Microsoft
weiß ja jederzeit besser was der Nutzer will, als der Nutzer selbst.)
Man bekommt nun Informationen über den Chip und erhält eine
Erfolgsmeldung. Und das Oszi zeigt ein Rechtecksignal mit ca. 830 kHz.
Der Frequenzzähler sagt 837 kHz. Das Programm braucht vier Takte, je
einen für die Portausgaben und zwei für den Rücksprung der Schleife. 4
* 837 kHz ist 3,348 MHz, verdächtig nahe an 3,33 MHz, die im Datenblatt
erwähnt werden. Und die kommen zustande, weil der interne
20-MHz-Oszillator durch 6 geteilt wird. Nebenbei zeigt die Messung,
dass mein Controller eine Frequenzabweichung von nur 0,4% hat.
Software- Erweiterungen und serielle Ausgaben
Das kleine Startprogramm wurde noch einmal leicht verändert, um auch
die Wartezeiten auszuprobieren. Außerdem habe ich entdeckt, dass man
statt PORTA_DIR auch PORTA.DIR schreiben kann. Mit dieser Änderung
blinken die Ausgänge nun langsamer, sodass man eine LED anschließen
kann.
/*
* GccApplication1.c
*
* Created: 15.07.2020 13:39:52
* Author : User
*/
#define F_CPU 3333333
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
int main(void)
{
PORTA.DIR = 255;
while (1)
{
PORTA.OUT = 255;
_delay_ms(100);
PORTA.OUT = 0;
_delay_ms(100);
}
}
Auf der Suche nach weiteren Funktionen und Programmbeispielen bin ich auf folgende Seiten gestoßen:
https://www.elektormagazine.com/news/new-microchip-pic-and-avr-mcus-increase-system-performance-in-closed-loop-control-applications
Interessant ist, dass PIC und ARV mehr zusammenwachsen, wenn es um die
Peripherie geht. Der ATtiny1607 ist der größte Controller aus der
tinyAVR0-Serie. Bei Microchip selbst gibt es eine Getting-started
Application Note:
http://ww1.microchip.com/downloads/en/AppNotes/Getting-Started-with-tinyAVR0-series-DS00002712.pdf
Allerdings wird da auch nur etwas mit den Leitungen geklappert. Mehr in die Tiefe geht Simon Merrett auf Hackaday:
https://hackaday.io/project/165439/logs
Weitere Hilfe habe ich einer anderen Application Note bei Microchip
gefunden. Hier geht es um die Nutzung des USART bei tinyAVR0- und
tinyAVR1-Controllern:
http://ww1.microchip.com/downloads/en/AppNotes/TB3216-Getting-Started-with-USART-90003216B.pdf
Die Beispielprogramme passen zwar nicht genau zur 0-Serie, können aber
leicht angepasst werden, weil die grundlegenden Strukturen gleich sind
wie bei der 1-Serie.
Die App-Note verweist z.B. auf dieses Beispiel, das man in Githup laden kann:
https://github.com/MicrochipTech/TB3216_Getting_Started_with_USART/tree/master/Send_Hello_World
In diesem Fall muss man nur beachten, dass die Anschlüsse TXD und RXD
beim Tiny202 an A7 und A6 liegen. Das Beispiel läuft nun auf dem
Tiny202 und meldet über das Terminal, dass der TXD-Ausgangs an PA6
liegt. Nur ein Problem konnte ich nicht lösen: Der Anwender wird dies
niemals lesen können, wenn er nicht vorher den Pin PA6 schon selbst
richtig angeschlossen hat.
/*
* GccApplication2.c
*
* Created: 14.07.2020 18:27:57
* Author : User
*/
#include <avr/io.h>
#define F_CPU 3333333
#define USART0_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
void USART0_init(void);
void USART0_sendChar(char c);
void USART0_sendString(char *str);
void USART0_init(void)
{
PORTA.DIRSET = 0x40; //TXD an PA6
PORTA.DIRCLR = 0x80; //RXD an PA7
USART0.BAUD = (uint16_t)USART0_BAUD_RATE(9600);
USART0.CTRLB |= USART_TXEN_bm;
}
void USART0_sendChar(char c)
{
while (!(USART0.STATUS & USART_DREIF_bm))
{
;
}
USART0.TXDATAL = c;
}
void USART0_sendString(char *str)
{
for(size_t i = 0; i < strlen(str); i++)
{
USART0_sendChar(str[i]);
}
}
int main(void)
{
USART0_init();
while (1)
{
USART0_sendString("TXD an PA6 \r\n");
_delay_ms(500);
}
}