1. /*
  2. Titel: S7-1200_1215C_AO-Simulation
  3. Autor: Niklas Menke - www.niklas-menke.de
  4. Erstelldatum: 10.04.2019
  5.  
  6. Version: 1.1.0
  7. Aktualisierungsdatum: 13.10.2020
  8. */
  9.  
  10.  
  11.  
  12. #define F_CPU 8000000 // Takt: 8Mhz
  13.  
  14.  
  15.  
  16. // --- Bibliotheken START ---
  17.  
  18. #include <avr/io.h> // Definition der IO-Pins des Mikrocontrollers
  19. #include <util/delay.h> // Zeitverzoegerungen
  20.  
  21. // --- Bibliotheken ENDE ---
  22.  
  23.  
  24.  
  25. // --- Definitionen START ---
  26.  
  27. // Segmente der 7-Segment-Anzeige
  28. static uint8_t segments_A[10] = {0x7A, 0x40, 0x2A, 0x4A, 0x50, 0x5A, 0x7A, 0x48, 0x7A, 0x5A}; // Speichert die Pins von PORTA, welche für die Zahlen 0-9 auf High gesetzt werden müssen
  29. static uint8_t segments_C[10] = {0x10, 0x10, 0x30, 0x30, 0x30, 0x20, 0x20, 0x10, 0x30, 0x30}; // Wie oben für PORTC
  30. static uint8_t digits_B[6] = {0x04, 0, 0x08, 0, 0, 0x02}; // Speichert den Pin von PORTB, welcher für die entsprechende Stelle einer Ziffer auf High gesetzt werden muss
  31. static uint8_t digits_C[6] = {0, 0x04, 0, 0x02, 0x01, 0}; // Wie oben für PORTC
  32.  
  33. #define DP_A 2 // Pin von PORTA des Dezimalpunkts
  34.  
  35. // --- Definitionen ENDE ---
  36.  
  37.  
  38.  
  39. // --- analog_input START ---
  40.  
  41. // Lese die analogen Werte von der SPS ein
  42. int analog_input(const uint8_t pin) {
  43. ADMUX = pin ? 0x44 : 0x45; // Dem ADC den geforderten Analogeingang zuweisen (pin = 0 --> AI0 mit der Adresse 0x45; pin = 1 --> AI1 mit der Adresse 0x44)
  44. ADCSRA |= (1<<ADEN) | (1<<ADSC); // ADC einschalten und Wert einlesen
  45. while (ADCSRA & (1<<ADSC)); // Warten, bis der Wert eingelesen wurde
  46. ADCSRA = 0; // ADC abschalten
  47. return (ADC*0.02+0.05)*10; // Eingelesenen Wert in den Stromwert umrechnen, Runden, eine Nachkommastelle vor das Komma setzen und zurueckgeben
  48. }
  49.  
  50. // --- analog_input ENDE ---
  51.  
  52.  
  53.  
  54. // --- lcd_print START ---
  55.  
  56. // Wert auf einer der Anzeigen darstellen
  57. void lcd_print(uint16_t value, uint8_t display) {
  58.  
  59. if(display > 1) display = 1;
  60.  
  61. // Schleife für jede Ziffer ausfuehren
  62. for (uint8_t dg = 0; dg < 6; dg+=2)
  63. {
  64. PORTB = 0; // Port B zurücksetzen
  65.  
  66. // Setze notwendige Pins auf High, um die letzte Ziffer aus value anzuzeigen
  67. PORTA = segments_A[value%10];
  68. PORTC = segments_C[value%10];
  69. value /= 10; // Letzte Ziffer entfernen
  70.  
  71.  
  72. // Pin der entsprechenden Stelle der Ziffer einschalten
  73. PORTB = digits_B[dg+display];
  74. PORTC |= digits_C[dg+display];
  75.  
  76. // Wenn die zweite Ziffer angezeigt wird, dann Dezimalpunkt setzen
  77. if(dg == 2) PORTA |= (1<<DP_A);
  78.  
  79. _delay_us(25); // Den LEDs Zeit zum Leuchten geben
  80. } // for END
  81.  
  82. // Alles zuruecksetzen
  83. PORTA = 0;
  84. PORTB = 0;
  85. PORTC = 0;
  86.  
  87. _delay_us(600); // Warten, um "ueberschreiben" zu verhindern
  88. }
  89.  
  90. // --- lcd_print ENDE ---
  91.  
  92.  
  93.  
  94. // --- Hauptfunktion START ---
  95.  
  96. int main(void)
  97. {
  98. // Variablendefinition
  99. uint16_t laup = 0; // Zaehler
  100. uint16_t AI0 = analog_input(0); // Wert von AI0
  101. uint16_t AI1 = analog_input(1); // Wert von AI1
  102.  
  103. // Pins als Ein- bzw. Ausgaenge definieren
  104. DDRA = 0x7E;
  105. DDRB = 0xE;
  106. DDRC = 0x37;
  107.  
  108. // Hauptschleife
  109. while (1)
  110. {
  111. lcd_print(AI0, 0); // Wert auf Anzeige 1 schreiben
  112. lcd_print(AI1, 1); // Wert auf Anzeige 2 schreiben
  113.  
  114. laup++; // Zaehler um 1 hochsetzen
  115.  
  116. // Wenn der Zaehler groesser als 50 ist, dann den Zaehler zuruecksetzen und die Analogwerte aktualisieren
  117. if (laup > 50)
  118. {
  119. laup = 0;
  120. AI0 = analog_input(0);
  121. AI1 = analog_input(1);
  122. }
  123. }
  124. }
  125.  
  126. // --- Hauptfunktion ENDE ---