You are here

Das Programm auf dem ATmega8

Error message

Deprecated function: Array and string offset access syntax with curly braces is deprecated in include_once() (line 20 of /mnt/web216/e3/48/5667948/htdocs/includes/file.phar.inc).

Die Aufgabe des Microcontroller ATmega8 ist im wesentlichen die Anzeige der gemessenen Frequenz auf einem LC-Display. Der nachfolgende Code zeigt das kleine Programm, das in C geschrieben wurde.

  1. #include <inttypes.h>
  2. #include <avr/io.h>
  3. #include <avr/interrupt.h>
  4. #include <stdio.h>
  5.  
  6. // approx. internal RC-Clock
  7. #define CLOCK 8000000
  8.  
  9. #include "../user_includes/LCDServices1.c"
  10.  
  11. void Counter_Idle() {
  12. }
  13.  
  14. void Counter_Init(void) {
  15. PORTB = (PORTB | 0x38) & 0xfb;
  16. DDRB = (DDRB | 0x2c) & 0xef;
  17. SPCR = 0x5d;
  18. }
  19.  
  20. uint32_t Counter_Read(void) {
  21. uint32_t adc;
  22.  
  23. cbi(PORTB,6);
  24.  
  25. SPDR = 0x55;
  26. while ((SPSR & 0x80)==0) { Counter_Idle(); }
  27. adc = SPDR;
  28.  
  29. SPDR = 0x55;
  30. while ((SPSR & 0x80)==0) { Counter_Idle(); }
  31. adc = (adc << 8) | SPDR;
  32.  
  33. SPDR = 0x55;
  34. while ((SPSR & 0x80)==0) { Counter_Idle(); }
  35. adc = (adc << 8) | SPDR;
  36.  
  37. SPDR = 0x55;
  38. while ((SPSR & 0x80)==0) { Counter_Idle(); }
  39. adc = (adc << 8) | SPDR;
  40.  
  41. sbi(PORTB,6);
  42.  
  43. return (adc);
  44. }
  45.  
  46.  
  47.  
  48. int main (void) {
  49. uint32_t cnt,v,n;
  50. uint8_t i;
  51.  
  52. cli();
  53. LCD_Init();
  54. printf("\001Frequenzzähler 3 GHz\002 (c) 2004 by DL8NCI ");
  55. for(i=0; i<=50; i++) LCD_Delay();
  56. printf("\001 ");
  57. printf("\002 ");
  58.  
  59. // Port B6 (Sel\) als Output
  60. sbi(PORTB,6);
  61. sbi(DDRB,6);
  62.  
  63. // Port B1 (DATA_ACK\) als Output
  64. sbi(PORTB,1);
  65. sbi(DDRB,1);
  66.  
  67. // Port B7 (DATA_READY\) als Input
  68. cbi(PORTB,7);
  69. cbi(DDRB,7);
  70.  
  71. Counter_Init();
  72.  
  73. while(1) {
  74.  
  75. while ((PINB & 0x80) !=0) { Counter_Idle(); }
  76.  
  77. // Read Shift Register
  78. cnt = Counter_Read();
  79.  
  80. // Acknowledga data received
  81. cbi(PORTB,1);
  82. asm("nop" "\n\t" "nop" "\n\t"
  83. "nop" "\n\t" "nop" "\n\t"
  84. "nop" "\n\t" "nop" "\n\t"
  85. "nop" "\n\t" "nop" "\n\t"
  86. "nop" "\n\t" "nop" "\n\t"
  87. "nop" "\n\t" "nop" "\n\t"
  88. ::);
  89. sbi(PORTB,1);
  90.  
  91. // Display Shift Register
  92. v = cnt/1000000;
  93. n = cnt%1000000;
  94. printf("\001%4lu.%06lu MHz ",v,n);
  95.  
  96. cnt = cnt<<6;
  97. v = cnt/1000000;
  98. n = cnt%1000000;
  99. printf("\002%4lu.%06lu MHz ",v,n);
  100. }
  101. }

Das Programm selbst ist verhältnismäßig unspektakulär. Wenn man mal von den Initialisierungen absieht, dann ist der Hauptteil in der Endlosschleife ab Zeile 73 zu finden. Zuerst wird gewartet, bis neue Daten vorliegen und der Zähler dann sein Signal data_read auf Low legt. Während des wartens könnte der ATmega8 andere sinnvolle Aufgaben erledigen, was durch die Prozedur Counter_Idle, Zeile 11, angedeutet ist. Liegen die Daten vor, dann wird Counter_Read aufgerufen (Zeile 78 und 20), das unter VVerwendung der SPI-Schnittstelle in vier Schritten den Zählerstand aus dem Latch/Schieberegister des Zählers ausliest. Ab Zeile 81 beginnt die Bestätigung der Datenübernahme indem das Signal data_ack des Zählers längs einiger NOPs auf Null gelegt wird bevor es wieder in den passiven Zustand High wechselt.

Die Ausgabe erfolgt unter Ausnutzung der Formatiermöglichketen für Integerzahlen über das printf-statement. Dabei wird der Zählerstand ganz einfach in einen Vorkommaanteil (MHz) und einen Nachkommaanteil unter Verwendung der Integer-Division bzw. Modulo-Division aufgespalten. Das setzt voraus, daß die Torzeit auf eine Sekunde eingestellt ist. Daß die Ausgabe in der ersten zeile des LC-Displays erfolgen soll, wird durch das \001 signalisiert. Analog wird in der zweiten Zeile (\002) ein anderes Ergebnis ausgegeben, das dem 64-fachen Zählergebnis entspricht. Dieser Wert ist abzulesen, wenn ein Vorteiler verwendet wird, der selber einen Teilerfaktor von 64 hat.