Hallo!
Ich habe aus einem alten Tektronix-Laserdrucker einen RTC-Baustein
ausgebaut. (Datenblatt im Anhang). Ich versuche seit Tagen, ihn zum
Leben zu erwecken am ATMega16.
Dieser Baustein hat ja auch frei benutzbares RAM ab Adresse 0x0E. Also
habe ich versucht, ein Programm zu schreiben, welches ein paar Werte in
den Ram schreibt, und später wieder ausliest und auf einem LCD
darstellt. Im Prinzip funktioniert es auch, aber es werden mir immer 234
zuviel angezeigt. Ich schreibe z.B. eine '0' rein, es kommt '234'
zurück. Bei einer '1' ist es dann '235'. Versuche ich, das Register
"0x00" (Sekunden) auszulesen, kommt '255' zurück. Bei nachfolgenden
Registern genauso. Pull-Ups ein / aus ist egal. Immer das gleiche.
Ich habe keinen Eagle-Plan dazu gezeichnet, versuche aber jetzt, die
Verdrahtung euch so zu zeigen:
ATMega: DS17287:
PB0...PB7 AD0...AD7
PC0 ALE
PC1 WR
PC2 RD
PC3 CS
VBAUX auf GND
die restlichen PINs unbelegt
Hier ist mein C-Code dazu:
1 | #include <avr/io.h>
|
2 | #include <stdlib.h>
|
3 | #include "lcd-routines.c"
|
4 | #include <util/delay.h>
|
5 |
|
6 | #define ALE 0
|
7 | #define WR 1
|
8 | #define RD 2
|
9 | #define CS 3
|
10 | #define ADDR_PORT PORTB
|
11 | #define DATA_PIN PINB
|
12 | #define RTC_DDR DDRB
|
13 | #define KOM_PORT PORTC
|
14 | #define KOM_PORT_DDR DDRC
|
15 |
|
16 |
|
17 | uint8_t rtc_lesen (uint8_t adresse)
|
18 | {
|
19 | uint8_t daten;
|
20 | RTC_DDR = 0xFF; //Adress-/ Datenport auf Ausgang
|
21 | KOM_PORT = (1<<CS); //Alle Kommandos löschen und CS auf "1"
|
22 | _delay_us(1);
|
23 | KOM_PORT |= (1<<RD | 1<<WR); //RD und WR auf "1"
|
24 | _delay_us(1);
|
25 | KOM_PORT |= (1<<ALE); //ALE auf "1"
|
26 | _delay_us(1);
|
27 | ADDR_PORT = adresse; //Adresse auf Ausgänge legen
|
28 | KOM_PORT &= ~(1<<CS); //CS auf "0"
|
29 | _delay_us(1);
|
30 | KOM_PORT &= ~(1<<ALE); //ALE auf "0"
|
31 | _delay_us(1);
|
32 | ADDR_PORT = 0; //Adresse löschen
|
33 | RTC_DDR = 0; //PortB auf Eingang umschalten
|
34 | ADDR_PORT = 0xFF; // Pull-Ups
|
35 | KOM_PORT &= ~(1<<RD); //RD auf "0"
|
36 | _delay_us(1);
|
37 | daten = DATA_PIN; //Eingangsdaten in Variable 'daten' speichern
|
38 | _delay_us(1);
|
39 | KOM_PORT |= (1<<RD); //RD wieder auf "1"
|
40 | //_delay_us(1);
|
41 | KOM_PORT |= (1<<CS); //CS auf "1"
|
42 | _delay_us(1),
|
43 | KOM_PORT |= (1<<ALE); //ALE auf "1"
|
44 | return daten;//Funktion beenden und Daten vom Datenport zurückgeben
|
45 | }
|
46 |
|
47 | void rtc_schreiben (uint8_t adresse, uint8_t daten)
|
48 | {
|
49 | KOM_PORT = (1<<CS | 1<<RD | 1<<WR); //CS, RD und WR auf "1"
|
50 | _delay_us(20);
|
51 | KOM_PORT |= (1<<ALE); //ALE auf "1"
|
52 | KOM_PORT &= ~(1<<CS);
|
53 | RTC_DDR = 0xFF; //Adress-/ Datenport auf Ausgang
|
54 | ADDR_PORT = adresse; //Adresse auf Ausgang legen
|
55 | _delay_us(20);
|
56 | KOM_PORT &= ~(1<<ALE); //ALE auf "0"
|
57 | _delay_us(20);
|
58 | ADDR_PORT = 0;
|
59 | _delay_us(20);
|
60 | KOM_PORT &= ~(1<<WR); //WR auf "0" (Active Low)
|
61 | _delay_us(20);
|
62 | ADDR_PORT = daten;
|
63 | KOM_PORT |= (1<<WR);
|
64 | _delay_us(20);
|
65 | KOM_PORT |= (1<<CS);
|
66 | return; //Funktion beenden
|
67 | }
|
68 |
|
69 |
|
70 | int main() //Hauptprogramm
|
71 | {
|
72 | uint8_t rtc_daten;
|
73 | char buffer[20];
|
74 | KOM_PORT_DDR = 0xff;
|
75 | DDRD = 0xFF;
|
76 | lcd_init ();
|
77 | rtc_schreiben (0x0A, (1<<5));
|
78 | for (uint8_t i=0; i<20; i++)
|
79 | {
|
80 | rtc_schreiben ((0x0E + i), i+10);
|
81 | }
|
82 | while (1)
|
83 | {
|
84 | for (uint8_t i=0; i<20; i++)
|
85 | {
|
86 | set_cursor (3,1);
|
87 | rtc_daten = rtc_lesen (0x0e + i);
|
88 | itoa (rtc_daten, buffer, 10);
|
89 | lcd_string (buffer);
|
90 | lcd_data (' ');
|
91 | itoa (i, buffer, 16);
|
92 | lcd_string (buffer);
|
93 | for (uint16_t j=0; j<1000; j++) _delay_ms(1);
|
94 | }
|
95 | }
|
96 |
|
97 | return 0;
|
98 | }
|
Ich habe schon nach dem Baustein gegooglet, aber leider nur das
Datenblatt gefunden, keine Programmbeispiele. Hier auf
mikrocontroller.net gibt´s leider auch nicht. RTC-Beispiele ansich gibt
es wohl, aber es sind meistens I²C Bausteine. Evtl. hat ja von Euch
einer eine Idee.