CH32V003 GPIO Initialisierung         


Elektronik-Labor  Projekte  CH32V


Die sehr umfangreichen Initialisierungs-Funktionen des CH32V003 haben mich gestört, weil sie schwer durchschaubar sind und ich kaum nachvollziehen kann, das da wirklich passiert. Mein Ziel war deshalb, die Sache zu vereinfachen und auf das absolute Minimum zu reduzieren. Auch die Datenblätter sind für mich nicht gerade einfach zu verstehen. Aber jetzt habe ich mir die GPIO-Initialisierung genauer angesehen und mit den fertigen Funktionen verglichen. Eigentlich muss man nur die richtigen 32 Bits in das Register GPIO_CFGLR des gemeinten Ports schreiben. Jedes der acht möglichen Portbits kann seine eigenen Einstellungen bekommen, die in vier Bits ausgedrückt werden.



Hier habe ich versucht, das absolute Minimum auszuloten. Alle acht Pinne am Port C sollen als Ausgänge mit Push-Pull und mit geringer Flankensteilheit (2 MHz) initialisiert werden. Dazu reicht die Zeile GPIOC->CFGLR =0x22222222;. Jeder Pinn erhält die Bits 0010. Sie unteren zwei Bits (10) stehen für den Ausgang mit 2 MHz, die oberen (00) stehen für Push-Pull. Was aber zusätzlich nötig ist, ist die Taktzuweisung mit RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);. In der Endlosschleife werden dann mit GPIOC->OUTDR = n; die Ausgaben geschickt, um einen Port-Zähler zu bilden. 

//GPIO Gonfig
#include "debug.h"

int main(void){
    u8 n = 0;
    Delay_Init();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIOC->CFGLR =0x22222222;   //00 PP, 10 2MHz;
    while(1){
        Delay_Ms(250);
        GPIOC->OUTDR = n;
        n++;
    }
}

Das funktioniert wie gewünscht. Und ich bin zufrieden, weil ein so kurzes Programm zur einfachen Aufgabe passt, und weil die Initialisierung kaum Zeit verbraucht.

Als nächstes wollte ich acht Eingänge am Port C erzeugen und dazu Pullups einschalten. 00 steht für Input und 10 für Pull, wobei für die Entscheidung Pullup oder Pulldown in das Register OUTDR geschrieben werden muss.

int main(void){
    Delay_Init();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIOC->CFGLR =0x88888888;   //10 Pull, 00 Input;
    while(1){
        GPIOC->OUTDR = 255;  //Pullup
        Delay_Ms(250);
        GPIOC->OUTDR = 0;    //Pulldown
        Delay_Ms(250);
        n++;
    }
}

Durch das Umschalten zwischen Pullup und Pulldown entsteht hier ein Blinker, der durch die hochohmigen Pullup-Widerstände sehr stromsparend arbeitet. Das habe ich vielfach in PicoBasic so gemacht und bin nun froh, dass es auch mit dem RISCV-Chip geht. So kann ich auch LEDs ohne Vorwiderstände an die Ports legen. Dann kann ich ja auch beliebige Bytes an GPIOC->OUTDR ausgeben und damit z.B. einen sparsamen Port-Zähler bauen.

int main(void){
    u8 n = 0;
    Delay_Init();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIOC->CFGLR =0x88888888;   //10 Pull, 00 Input;
    while(1){
        GPIOC->OUTDR = n;  //Pullup Count
        Delay_Ms(250);
        n++
    }
}

Oder ich gebe bestimmte Bitmuster über die Pullups aus. Hier tanzen acht LEDs einen Booggie Wooggie bei gedämpftem Licht.

int main4(void){
    u8 n = 0;
    Delay_Init();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIOC->CFGLR =0x88888888;   //10 Pull, 00 Input;
    while(1){
        GPIOC->OUTDR = 170;  //Blink
        Delay_Ms(250);
        GPIOC->OUTDR = 85;   //Blonk
        Delay_Ms(250);
        n++;
    }
}



Elektronik-Labor  Projekte  CH32V