N76E003 Multiplex LED-Feld   


Elektronik-Labor  Projekte  Nuvoton 



Für diesen Versuch verwende ich die Franzis Pingpong-Platine. Der ATmega8 befindet sich zwar noch auf der Platine, aber ich habe seinen Reset-Eingang an GND gelegt. Damit ist er völlig abgeschaltet und überlässt die LED-Ansteuerung dem externen Controller. Die ursprüngliche Schaltung zeigt, wie das Display angesteuert werden muss.




Der N76E003 hat weniger Anschlüsse als der ATmega8:



Folgende Belegung bietet sich an:
P1.0…P1.7 + P1.0 + P1.1 als parallele LED-Reihen
P0.2 + P0.3 + P0.4 zur Ansteuerung der Schieberegister

Die Multiplexansteuerung läuft in einer Interrupt-Funktion mit 4 kHz. Bei jedem Durchgang wird ein Null-Zustand für die Kathoden einer Reihe um eine Stelle weiter getaktet. Dazu reicht in einzelner Taktimpuls für die Schieberegister. Dann werden die Anoden-Zustände als parallele Daten ausgegeben. Das Word-Array ui_leds[14] ist eine Art Video-RAM, in dem man programmiert, welche LEDs an oder aus sein sollen.


unsigned char uc_col;       
unsigned int random;
unsigned int ui_leds[14];   

void Timer0_ISR (void) __interrupt 1          //interrupt address is 0x000B
{
    TH0 = 0xF6;
    P05=1;                                  //Laufzeit-Test
    uc_col++;                      
    if (uc_col==12) uc_col = 0;                                      
    P0 = P0 & 0x70;                         //LEDs off
    P1 = 0;                                                         
    if (uc_col == 0) P02 = 0; else P02 = 1; //Dat = 0 bei Spalte 0
    P03 = 1;                                                                       
    P03 = 0;                                //CLK
    P04 = 1;                                
    P04 = 0;                                //STR
    P02 = 1;                              
    P1 = ui_leds[uc_col];                   //LED 0...7                       
    P0 = (P0 & 0xFC) |(ui_leds[uc_col] & 0x0300) >> 8;
    P05=0;                                  //Laufzeit-Test
    random= random + 57;                                 
}


Das Testmuster im Bild oben wurde mit diesen Daten erzeugt:

 ui_leds[0]=1;ui_leds[1]=3;ui_leds[2]=7;ui_leds[3]=15;
 ui_leds[4]=31;ui_leds[5]=63;ui_leds[6]=127;ui_leds[7]=255;
 ui_leds[8]=511;ui_leds[9]=1023;ui_leds[10]=511;ui_leds[11]=255;

Im Interrupt wird eine nicht ganz zufällige Zufallszahl erzeugt, die bei jedem Durchlauf um 57 erhöht wird. Damit sollen nun einzelne LEDs nach einem Zufallsmuster eingeschaltet werden. Der effektive Wertebereich wird durch die Modulo-Division % festgelegt. Wenn dieselbe Zufallszahl für die Spalte und für die Reihe verwendet wird, entsteht tatsächlich ein regelmäßiges Muster.


n=random;
ui_leds[n % 12] = ui_leds[n % 12] | (0x0001 << (unsigned int) n % 10);  // regelmäßig



Wenn man sich nach kurzer Zeit eine zweite Zufallszahl holt, ist das Ergebnis zufälliger. Nach ungefähr zehn Minuten ist auch die letzte LED im Display eingeschaltet.

     delay(25);
     d=random;
     ui_leds[n % 12] = ui_leds[n % 12] | (0x0001 << (unsigned int) d % 10);   //zufällig


Und man kann auch zufällig ein-und ausschalten.

   ui_leds[n % 12] = ui_leds[n % 12] ^ (0x0001 << (unsigned int) d % 10);   //Exclusiv Oder, auch AUS...

Das unregelmäßige Flackern sieht dann so aus wie die Computer in ganz alten James-Bond-Filmen. Man kann stundenlang zusehen. Und das Display wird gleichzeitig zu einem wirksamen Orakel. Irgendwann wird ein Bild erscheinen, das mir die gesuchte Antwort gibt.


// Multiplexanzeige 10 x 12 LEDs
#include "N76E003.h"
#include <stdio.h>


void InitUART0_Timer1(long Baudrate);
char getchar(void);
void putchar(char);
void delay(unsigned int ms);

//P1.0…P1.7 + P1.0 + P1.1 als parallele LED-Spalten
//P0.2 + P0.3 + P0.4 zur Ansteuerung der Schieberegister

unsigned char uc_col;       
unsigned int random;
unsigned int ui_leds[14];   
unsigned char p;

void Timer0_ISR (void) __interrupt 1          //interrupt address is 0x000B
{
    TH0 = 0xF6;
    P05=1;                                  //Laufzeit-Test
    uc_col++;                      
    if (uc_col==12) uc_col = 0;                                      
    P0 = P0 & 0x70;                         //LEDs off
    P1 = 0;                                                         
    if (uc_col == 0) P02 = 0; else P02 = 1; //Dat = 0 bei Spalte 0
    P03 = 1;                                                                       
    P03 = 0;                                //CLK
    P04 = 1;                                
    P04 = 0;                                //STR
    P02 = 1;                              
    P1 = ui_leds[uc_col];                   //LED 0...7                       
    P0 = (P0 & 0xFC) |(ui_leds[uc_col] & 0x0300) >> 8;
    P05=0;                                  //Laufzeit-Test
    random= random + 57;                                 
}

void main(void)
{
unsigned int n, d;
    P0M1=0;P0M2=255;P1M1=0;P1M2=255;P3M1=0;P3M2=0;      //P17 Eingang
    P30=1;

    InitUART0_Timer1(9600);
    printf ("UART0, 9600 Baud\r\n");
    ADCCON1=1;                          //ADC on
    ET0 = 1;                             //enable Timer1 interrupt
    EA = 1;                              //enable interrupts
    TR0 = 1;                             //Timer0 run
    //  for(n=0;n<12;n++) ui_leds[n] =0:

   // ui_leds[0]=1;ui_leds[1]=3;ui_leds[2]=7;ui_leds[3]=15;
   // ui_leds[4]=31;ui_leds[5]=63;ui_leds[6]=127;ui_leds[7]=255;
   // ui_leds[8]=511;ui_leds[9]=1023;ui_leds[10]=511;ui_leds[11]=255;

    while (1)
    {
       ADCCON0 = 0;  //ADC0 = P17
       ADCS = 1;                                 
       while(ADCF == 0);
       n=ADCRH;
       n=16  * n+ ADCRL;
     //  printf ("\r\n ADC =  %d",n);
       delay(25);
       n=random;
     // ui_leds[n % 12] = ui_leds[n % 12] | (0x0001 << (unsigned int) n % 10);  // regelmäßig
       delay(25);
       d=random;
     //ui_leds[n % 12] = ui_leds[n % 12] | (0x0001 << (unsigned int) d % 10);   //zufällig
       ui_leds[n % 12] = ui_leds[n % 12] ^ (0x0001 << (unsigned int) d % 10);   //Exclusiv Oder, auch AUS...
       printf ("\r\n %d",(0x0001 << ((unsigned int)d % 10)));
    }
}

void InitUART0_Timer1(long Baudrate)    //T1M = 1, SMOD = 1
{
    SCON = 0x50;        //UART0 Mode1,REN=1,TI=1
    TMOD |= 0x20;       //Timer1 Mode1 
    PCON |= 128;        //SMOD = 1 UART0 Double Rate Enable
    CKCON |=16;         //set_T1M
    T3CON &= ~64;       //BRCK = 0  Serial port 0 baud rate clock source = Timer1
    TH1 = 256 - (1000000/Baudrate+1);               /*16 MHz */
    TR1 = 1;
    TI = 1;             //For printf
}

char getchar(void)
{
    char c;
    while (!RI);
    c = SBUF;
    RI = 0;
    return (c);
}

void putchar(char c)
{
    while (!TI); 
    TI = 0;
    SBUF = c;     
}

void delay(unsigned int ms)
{
     unsigned int i,j;
    for(i=0;i<ms;i++)
      for(j=0;j<0x320;j++);
}





Elektronik-Labor  Projekte   Nuvoton