PIC Mikrocontroller

Dieses Projekt beschäftigt sich eingehend mit dem programmieren eines Mikrocontrollers. Mikrocontroller werden heutzutage praktisch überall verwendet, ob in ihrem Multimeter oder auch in der Mikrowelle und Waschmaschine. Mit einem Mikrokontroller können fast alle Schaltungen auf einfache und elegante Weise realisiert werden, ausserdem gibt es diese Mikrocontroller vielen Grössen und Bauformen. Der hier verwendete Mikrocontroller ist ein PIC16F877-20/P.


  PIC16F877 40-Pin, 8-Bit CMOS Microcontroller

  • RISC CPU
  • Operating voltage range: 2.0V to 5.5V
  • Maximum current, all I/O-Pins: 25mA
  • DC - 20MHz clock input
  • DC - 200 ns instruction cycle
  • 256 Byte EEPROM Data Memory
  • 14 Interupts
  • A/D-Wandler (10Bit), 8 Inputs
  • 8k FLASH Program Memory (14Bit Words)
  • 33 I/O-Pins; Ports (A,B,C,D,E)
  • Serial Com.: MSSP (I2C), USART (RS232) Rx oder Tx
  • Parallel Com.: PSP
  • Instruction set: 35 Instructions
  • 3 Timer
  • 2 PWM Module



Das Board

Die serielle Schnittstelle dient zur Kommunikation mit dem PC und dank der RJ11 Schnittstelle kann das Board ganz einfach programmiert werden. Mit den beiden Jumpern können Rx und Tx vertauscht werden. Die Standardbelegung ist (RC7 = Rx, RC6 = Tx). Der Widerstand R4 bestimmt die Versorgungsspannung: 720Ω für 5V, 400Ω für 3.3V. Ich habe hier die 5V-Speisung gewählt.









Um den PIC zu programmieren verwende ich ein ICD-Interface, das über eine USB Schnittstelle verfügt. Zum Kompilieren der gerschriebenen Programme benutze ich den passenden CCS C-Compiler. Das schreiben der Programme in einer höheren Programmiersprache, wie C, ist wesentlich konfortabler als wenn man die Programme in Assembler schreiben muss.




Zur Spannungsversorgung des Pics verwende ich ein modifiziertes altes PC-Netzteil. Dies Hat den Vorteil, dass die Versorgungsspannung schon für logische Schaltungen stabilisiert ist




Mein Arbeitsplatz:




Um den PIC zu testen ist es vorteilhaft ein kleines LED-Array aufzubauen. Zu jedem LED braucht es ein Vorwiderstand von 560Ω.






Head-Lines die in jedem Programm benötigt werden

# include <16F877.h>
Dieses H-file enthält die wichtisten Funktionen für den PIC16F877. Es sagt dem Compiler, welchen Chip erprogrammiert.

# fuses HS,NOWDT,NOPROTECT,NOBROWNOUT
Weitere Optionen:
HS: Highspeed
NOPROTECT (PROTECT): Nicht sichern / sichern.
Mit dem Attribut 'PROTECT' sollte man sehr vorsichtig sein. Denn wurde es gesetzt und das Programm auf den Mikrocontroller geladen, so lässt sich das Programm nie mehr vom Controller lesen, entfernen oder überschreiben.
NOLVP: No low voltage programming
NOWDT: No watch dog timer
NOBROWNOUT: No brownout reset
NOPUT: No Power Up Timer
NOCPD: No EE protection
NOWRT: Program memory not write protected
NODEBUG: No Debug mode for ICD

# use delay (clock = 16000000)
Gibt an, wie hoch der Chip getaktes ist, damit der Compiler Wartezeiten etc. einrichten kann.

# use rs232 (baud = 9200, xmit = PIN_C6, rcv = PIN_C7)
Wird benötigt um die serielle Schnittstelle zu erkennen und das Programm die Schnittstelle anspricht. Diese Zeile reicht noch nicht aus, die serielle Schnittstelle muss zuerst initialisiert werden. C6 und C7 hat den Vorteil, dass der Compiler die Schnittstelle ständig automatisch initalisiert.


Die wichtigsten Funktionen

output_high (PIN_A0);
Setzt den als Parameter mitgegebenen Pin auf High, legt also eine Spannung von 5V am Pin an.

output_low (Pin_A0);
Setzt den als Parameter mitgegebenen Pin auf Low (d.h. 0V).

delay_ms (2000);
Unterbricht den Programmablauf um die angegebene Anzahl Millisekunden.

delay_us (2000);
Unterbricht den Programmablauf um die angegebene Anzahl Mikrosekunden.


Hilfreiche Funktionen, Variablen und Operatoren

set_tris_X(value);
Diese Funktion bestimmt, welche Pins des angegebenen Ports als Eingänge bzw. Ausgänge definiert sind.
z.B.: set_tris_a(0b00010010);
So werden die Pins 1 und 4 des Ports A als Eingänge definiert. Alle anderen Pin sind Ausgänge.

# BYTE x
Erzeugt eine Varable mit 8 Bit-Stellen und dem Namen x.

portX
X bezeichnet den Port: A,B,C,D oder E. Das sind vordefinierte Variablen aus dem Header 'atros.h' vom Typ BYTE. Wenn ihnen ein 8-stelliger Bit-Wert zugewiesen wird werden die entsprechenden Pins auf High/Low gesetzt.


Ein einfaches Programm - LED Lauflicht

  #include <16F877.h>
  #fuses HS,NOWDT,NOPROTECT,NOBROWNOUT
  #use delay(clock=16000000)

  void main (void)
  {
       int n = 100;
       
       while (1)
       {
             output_high (PIN_A0);     //LED ein
             delay_ms (n);             //Delay 0,1 Sek
             output_low (PIN_A0);      //LED aus
             
             output_high (PIN_A1);     //LED ein
             delay_ms (n);             //Delay 0,1 Sek
             output_low (PIN_A1)       //LED aus
             
             output_high (PIN_A2);     //LED ein
             delay_ms (n);             //Delay 0,1 Sek
             output_low (PIN_A2)       //LED aus
             
             output_high (PIN_A3);     //LED ein
             delay_ms (n);             //Delay 0,1 Sek
             output_low (PIN_A3)       //LED aus
             
             output_high (PIN_A4);     //LED ein
             delay_ms (n);             //Delay 0,1 Sek
             output_low (PIN_A4)       //LED aus
             
             output_high (PIN_A3);     //LED ein
             delay_ms (n);             //Delay 0,1 Sek
             output_low (PIN_A3)       //LED aus
             
             output_high (PIN_A2);     //LED ein
             delay_ms (n);             //Delay 0,1 Sek
             output_low (PIN_A2)       //LED aus
             
             output_high (PIN_A1);     //LED ein
             delay_ms (n);             //Delay 0,1 Sek
             output_low (PIN_A1)       //LED aus
       }
  }




Folgendes kleine Video zeigt das Ergebnis des Programms:




Ein zweites Programm - PWM

Dieses kleine Programm benutzt eines der PWM-Module des Mikrokontrollers und generiert ein pulsweitenmoduliertes Signal. Der Duty-Cycle, welcher die On-Zeit des Signals bestimmt wird durch die erste for-Schleife bis auf etwa 95% erhöht und durch eine zweite for-Schleife wieder bis auf 5% dekrementiert.

// PWM.c
// Oliver Knecht
// 03.03.2008

#include <16F877.h>
#use delay(clock=16000000)
#fuses HS,NOPROTECT,NOWDT,BROWNOUT,PUT,NOLVP


void main(void)
{
    byte duty, duty2, period;
    byte prescale;
    int i=0;
    int j=0;

    setup_ccp1(CCP_PWM);   // Configure CCP1 as a PWM

    period = 0x80;
    prescale =  4;

    setup_timer_2(T2_DIV_BY_16, period, 1);

    // The cycle time will be (1 / clock) * 4 * t2div * (period + 1)
    // (1/20000000) * 4 * 16 * 128 = 409.6 us or 2.4 khz

    while (1)
    {
      duty = 0x12;

      for(i=0;i<46;i++)          //increase duty-cycle
      {
        set_pwm1_duty(duty);
        delay_ms(100);
        duty=duty+0x02;
        duty2=duty;
      }

      for(i=0;i<46;i++)          //decrease duty-cycle
      {
        set_pwm1_duty(duty2);
        delay_ms(100);
        duty2=duty2-0x02;
      }
    }
}


Folgendes kleine Video zeigt das Ergebnis des Programms auf einem Oszilloskop:



Impressum PHP Counter Sie sind Besucher: 522405