#include #include #define F_CPU 8000000 // Prototypen der Funktionen void ioinit(); // Fuer One Wire Interface volatile unsigned char status_global, bitcount, transbyte, bytecount ; volatile unsigned char shift_reg, fb_bit ; volatile unsigned char transdata[9]; // Hier werden die Daten aufbewahrt, die gesendet/empfangen werden, // dabei gilt die Zuordnung wie beim 18B20 Tempsensor. Auch fuer die EEPROM Bytes // Definitionen für den Zustandsanzeiger #define IDLE 0x00 #define RESET 0x01 #define PRESENCEPULSE 0x02 #define WAITOPCODE 0x04 #define READMEM 0x08 #define WRITEEEPROM 0x09 #define RECEIVE_OPCODE 0x10 #define MATCHROM 0x20 #define SEARCHROM 0x40 #define WRITEMEM 0x80 // definitionen für die OneWire erkennung #define FAMILYCODE 0x28 // Identifies as 18B20 Thermometer #define DEVICEID 0x55 // Um Speicher zu sparen wird die deviceid 5 mal gesendet, es können also 256 IDs eingestellt werden #define CRCVAL 0x54 // aus http://www.zorc.breitbandkatze.de/crc.html // Mit order = 8, Polynom 0x31, Initial 00, final 0 data: %aa%aa%aa%aa%aa%aa%10 // Übertragen wird CRC 6mal DEVICEID FAMILYCODE #define ADIN0 0x02 #define ADIN1 0x03 #ifdef __AVR_ATtiny13__ #define PAD_RELAIS 0 #define ONEWIREPIN 1 // Pin, an dem der 1-Wire angeschlossen ist, MUSS INT0 sein #define PRESENCEZEIT 15 // Timingdeclarationen für 9,6 MHz #define PRESENCEWAITZEIT 2 #define ABTASTZEIT 3 // Abtastzeitpunkt beim empfangen #define SENDEZEIT 5 // Dauer des 0-Sendeimpulses #elif defined (__AVR_ATmega8__) #define TIMSK0 TIMSK // TIMSK0 istTIMSK beim Attiny13 #define TIFR0 TIFR #define EEPE EEWE #define EEMPE EEMWE #define PAD_RELAIS 3 // #define ONEWIREPIN 2 // Pin, an dem der 1-Wire angeschlossen ist, MUSS INT0 sein #define PRESENCEZEIT 15 #define PRESENCEWAITZEIT 2 #define ABTASTZEIT 3 // War 5 jetzt 3 #define SENDEZEIT 5 // War 15 jetzt auf 10 #define BAUDRATE 38400 #endif // Port als Ausgang // Initialisierung der Hardware void ioinit() { unsigned char i; #ifdef __AVR_ATtiny13__ CLKPR = 0x80; // Per software auf 9,6 MHz stellen Aenderung des Vorteilers freigeben CLKPR = 0x00; // Vorteiler auf 1 (000) setzen PORTB &= ~(1 << ONEWIREPIN); // Pin auf Null, aber Input PORTB |= (1 << PAD_RELAIS); // Pullup setzen DDRB |= (1 << PAD_RELAIS); // Ausgang enable TCCR0A = 0; TCCR0B = 0x03; // Prescaler 1/64 MCUCR |= (1 << ISC00); // Interrupt auf beide Flanken GIMSK |= (1 << INT0) ; // Externen Interrupt freigeben // Den ADC aktivieren und Teilungsfaktor auf 64 stellen ADCSRA = (1<>8); UBRRL = (uint8_t) (ubrr); // UART Receiver und Transmitter anschalten // Data mode 8N1, asynchron UCSRB = (1 << RXEN) | (1 << TXEN); UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); // Flush Receive-Buffer do { uint8_t dummy; (void) (dummy = UDR); } while (UCSRA & (1 << RXC)); #else #error Das ist noch nicht implementiert fuer diesen Controller! #endif // Port als Ausgang } #if defined (__AVR_ATmega8__) unsigned char uart_putc (unsigned char c) { // Warten, bis UDR bereit ist für einen neuen Wert while (!(UCSRA & (1 << UDRE))) ; // UDR schreiben startet die Übertragung UDR = c; return 1; } unsigned char uart_getc_wait() { // Warten, bis etwas empfangen wird while (!(UCSRA & (1 << RXC))) ; // Das empfangene Zeichen zurückliefern return UDR; } unsigned char uart_getc_nowait() { // Liefer das empfangene Zeichen, falls etwas empfangen wurde; -1 sonst return (UCSRA & (1 << RXC)) ? (int) UDR : -1; } #endif // Das Hauptprogramm (Einsprungpunkt) int main() { unsigned char i, dummy; unsigned char hyst; // Peripherie initialisieren ioinit(); status_global = IDLE; unsigned char blind; // Interrupts aktivieren sei(); // PORTD |= (1 << PAD_RELAIS); // Debug Relais an // Eine Endlosschleife. while (1) { #if defined (__AVR_ATmega8__) switch (status_global){ // Nur zum Debuggen case RESET: uart_putc('R'); case PRESENCEPULSE: uart_putc('P'); case WAITOPCODE: uart_putc('W'); case READMEM: uart_putc('M'); case WRITEEEPROM: uart_putc('W'); case RECEIVE_OPCODE: uart_putc('O'); case MATCHROM: uart_putc('M'); // case SEARCHROM: uart_putc('S'); case WRITEMEM: uart_putc('I'); case IDLE: ; // default: { // uart_putc(status_global); // status_global = IDLE; // } } #endif // Kanal des Multiplexers waehlen ADMUX = ADIN0; // ADMUX |= (1< transdata[1] + transdata[2] - hyst){ // PORTD |= (1 << PAD_RELAIS); // Relais an hyst = transdata[3]; } else { // PORTD &= ~(1 << PAD_RELAIS); // Relais aus hyst = 0; } transdata[4] = hyst; } } // Timer interrupt routine #ifdef __AVR_ATtiny13__ ISR (TIM0_OVF_vect) #elif defined (__AVR_ATmega8__) ISR (TIMER0_OVF_vect) #endif // Port als Ausgang { unsigned char tim0_i, status; signed int temperaturwert, temperaturwert_bruch; TIMSK0 &= ~(1 << TOIE0); // Timer Interrupt aus status = status_global; #ifdef __AVR_ATtiny13__ DDRB &= ~(1 << ONEWIREPIN); // Pin auf Eingang #elif defined (__AVR_ATmega8__) DDRD &= ~(1 << ONEWIREPIN); // Pin auf Eingang #endif if (status == RESET){ #ifdef __AVR_ATtiny13__ DDRB |= (1 << ONEWIREPIN); // Pin auf Ausgang #elif defined (__AVR_ATmega8__) DDRD |= (1 << ONEWIREPIN); // Pin auf Ausgang #endif status = PRESENCEPULSE; bitcount = 0; TCNT0 = ~PRESENCEZEIT; // Neu Starten zum bestimmen der Presencepulselaenge TIFR0 |= (1 << TOV0); TIMSK0 |= (1 << TOIE0); // Timer Interrupt an } else if (status == PRESENCEPULSE){ // Presence Puls zu ende, Timer INT aus, Pin auf Eingang, warten auf Opcode status = RECEIVE_OPCODE; bitcount = 0; // TINT wird oben ausgeschaltet } else if (status & (RECEIVE_OPCODE | MATCHROM | WRITEMEM)){ bitcount++; if (bitcount == 1) { transbyte = 0; } transbyte = transbyte >> 1; #ifdef __AVR_ATtiny13__ if (PINB & (1 << ONEWIREPIN)){ #elif defined (__AVR_ATmega8__) if (PIND & (1 << ONEWIREPIN)){ #endif transbyte |= 0x080; } if (bitcount == 8){ if (status == RECEIVE_OPCODE) { if (transbyte == 0x55){ // 0x55 -> Matchrom status = MATCHROM; transbyte = 0; // New } else if (transbyte == 0x4E){ status = WRITEMEM; transbyte = 0; } else if (transbyte == 0x48){ // Write data to EEPROM status = WRITEMEM; transbyte = 0; } else if (transbyte == 0x48){ // Write data to EEPROM for (tim0_i = 2; tim0_i < 4; tim0_i++){ while(EECR & (1<>EEPM0); /* Set up address and data registers */ EEARL = tim0_i; // EEPROM Address EEDR = transdata[tim0_i]; /* Write logical one to EEMPE */ EECR |= (1< 35)) { // Reset pulse wenn Puls >30 und < F0 geaendert auf 35 TIFR0 |= (1 << TOV0); // Timer Overflow loeschen TCNT0 = ~PRESENCEWAITZEIT; // Timer Neu Starten Fuer Presencepulse TIMSK0 |= (1 << TOIE0); // Timer Interrupt an status = RESET; } } else { // Fallende Flanke am One Wire if (status == READMEM){ if ((transbyte & 0x01) == 0){ #ifdef __AVR_ATtiny13__ DDRB |= (1 << ONEWIREPIN); // Pin auf Ausgang #elif defined (__AVR_ATmega8__) DDRD |= (1 << ONEWIREPIN); // Pin auf Ausgang #endif } TIFR0 |= (1 << TOV0); // TimerOverflow loeschen TCNT0 = ~SENDEZEIT; TIMSK0 |= (1 << TOIE0); // Timer Interrupt an fb_bit = (transbyte ^ shift_reg) & 0x01; // CRC berechnen shift_reg = shift_reg >> 1; if (fb_bit) shift_reg = shift_reg ^ 0x8c; bitcount++; transbyte = transbyte >> 1; if (bitcount == 8){ bitcount = 0; bytecount++; if (bytecount == 8){ transbyte = shift_reg; // CRC senden } else if (bytecount == 9) status = IDLE; // CRC senden else transbyte = transdata[bytecount]; } } else if (status == IDLE) { // Erste fallende Flanke TIFR0 |= (1 << TOV0); // TimerOverflow loeschen TIMSK0 &= ~(1 << TOIE0); // Timer Interrupt aus TCNT0 = 0; // status = RESET; // Erste fallende Flanke nach Idle, Timer nutzen um Länge des Pulses zu messen } else if (status & (RECEIVE_OPCODE | MATCHROM | WRITEMEM)){ TCNT0 = ~ABTASTZEIT; // Zeichen abtasten in ABTASTZEIT TIFR0 |= (1 << TOV0); // TimerOverflow loeschen TIMSK0 |= (1 << TOIE0); // Timer Interrupt an } else if (status == RESET) { // Da hat ein anderer einen Presence Pulse gesendet, da haengen wir uns dran // DDRD |= (1 << ONEWIREPIN); // Pin auf Ausgang status = PRESENCEPULSE; bitcount = 0; TCNT0 = ~PRESENCEZEIT; // Neu Starten zum bestimmen der Presencepulselaenge TIFR0 |= (1 << TOV0); // Timer OVF loeschen TIMSK0 |= (1 << TOIE0); // Timer Interrupt an } else if (status == PRESENCEPULSE); // Gar nichts tun, Pegeländerung kommt vom eigenen Timer beim Senden oder anderen else { status = IDLE; TCNT0 = 0; TIFR0 |= (1 << TOV0); // TimerOverflow loeschen TIMSK0 &= ~(1 << TOIE0); // Timer Interrupt aus } } status_global = status; }