Ok, Ich bin dann mal so frech und hau nen Code raus.
Im Simulator hab ich das mal getestet - Da scheints zu funktionieren.
Mit nem Controller kann ich leider nicht testen ( Kein ATMEGA 88 hier ).
Ich hab das Prinzip mit dem Pinchange umgesetzt.
Die Simulation war mit 8MHz, dabei kann ein Versatz ( Jitter ) von 30µS bei den Signalen entstehen.
Auch wenn mehrere Ports ihre Level zu gleichen Zeit ändern, sollte der Code funzen.Code:/***************************************************** Project : Einzelimpulse zu Summensignal Version : 0.1 Date : 19.12.2014 Author : Company : Comments: Chip type : ATmega88 Program type : Application Clock frequency : 8,000000 MHz Memory model : Small External SRAM size : 0 Data Stack size : 256 Zeitversatz beim Einlesen der Impulse 30µs! *****************************************************/ /******** PC0 = Kanal 1 PC1 = Kanal 3 PC2 = Kanal 5 PC3 = Kanal 7 PD0 = Kanal 2 PD1 = Kanal 4 PD2 = Kanal 6 PD3 = Kanal 8 PB1 = Summensignalausgang ********/ #include <mega88.h> volatile unsigned int ui_timerold[8]; //Speicherwerte für die Steigende Flanke der entsprecheden Kanäle volatile unsigned int ui_pulslengh[8]={1500,1500,1500,1500,1500,1500,1500,1500}; //Ermittelte Pulslängen volatile unsigned char uc_oldgerade=0; //Zwischenspeicher für den alten Zustand der geraden Kanäle 2,4,6,8 volatile unsigned char uc_oldungerade=0; //Zwischenspeicher für den alten Zustand der geraden Kanäle 1,3,5,7 volatile unsigned char uc_cyclecount; //Zyklenzähler für die Impulsausgabe #define maxcycle 15 #define interpulspause 50 //50 = 50µs #define interframepause 4000 //4000 = 4ms Interframepause //#define normal //Bestimmt ob die Impulsausgabe normal oder invers geschehen soll //#define revers #define portsungerade PINC #define portsgerade PIND #define outport PORTB.1 // Pin change 8-14 interrupt service routine interrupt [PCINT1] void pin_change_isr1(void) { unsigned char uc_portungerade,uc_result; unsigned int ui_timer; ui_timer=TCNT1H; ui_timer=(ui_timer<<8)+TCNT1L; uc_portungerade=portsungerade&0x0F; uc_result=uc_portungerade^uc_oldungerade; if(uc_result&0x01) { if(uc_portungerade&0x01) //Es war ne steigende Flanke { ui_timerold[0]=ui_timer; } else //Es war ne fallende Flanke { ui_pulslengh[0]=ui_timer-ui_timerold[0]; }; } if(uc_result&0x02) { if(uc_portungerade&0x02) //Es war ne steigende Flanke { ui_timerold[2]=ui_timer; } else //Es war ne fallende Flanke { ui_pulslengh[2]=ui_timer-ui_timerold[2]; }; } if(uc_result&0x04) { if(uc_portungerade&0x04) //Es war ne steigende Flanke { ui_timerold[4]=ui_timer; } else //Es war ne fallende Flanke { ui_pulslengh[4]=ui_timer-ui_timerold[4]; }; } if(uc_result&0x08) { if(uc_portungerade&0x08) //Es war ne steigende Flanke { ui_timerold[6]=ui_timer; } else //Es war ne fallende Flanke { ui_pulslengh[6]=ui_timer-ui_timerold[6]; }; } uc_oldungerade=uc_portungerade; } // Pin change 16-23 interrupt service routine interrupt [PCINT2] void pin_change_isr2(void) { unsigned char uc_portgerade,uc_result; unsigned int ui_timer; ui_timer=TCNT1H; ui_timer=(ui_timer<<8)+TCNT1L; uc_portgerade=portsgerade&0x0F; uc_result=uc_portgerade^uc_oldgerade; if(uc_result&0x01) { if(uc_portgerade&0x01) //Es war ne steigende Flanke { ui_timerold[1]=ui_timer; } else //Es war ne fallende Flanke { ui_pulslengh[1]=ui_timer-ui_timerold[1]; }; } if(uc_result&0x02) { if(uc_portgerade&0x02) //Es war ne steigende Flanke { ui_timerold[3]=ui_timer; } else //Es war ne fallende Flanke { ui_pulslengh[3]=ui_timer-ui_timerold[3]; }; } if(uc_result&0x04) { if(uc_portgerade&0x04) //Es war ne steigende Flanke { ui_timerold[5]=ui_timer; } else //Es war ne fallende Flanke { ui_pulslengh[5]=ui_timer-ui_timerold[5]; }; } if(uc_result&0x08) { if(uc_portgerade&0x08) //Es war ne steigende Flanke { ui_timerold[7]=ui_timer; } else //Es war ne fallende Flanke { ui_pulslengh[7]=ui_timer-ui_timerold[7]; }; } uc_oldgerade=uc_portgerade; } // Timer 1 output compare A interrupt service routine interrupt [TIM1_COMPA] void timer1_compa_isr(void) { unsigned char uc_low,uc_high; unsigned int ui_buffer; switch(uc_cyclecount) { case 0: outport=1; //Der erste Impuls ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=ui_pulslengh[0]; //Pulslänge dazuzählen uc_low=ui_buffer&0x00FF; //OCR Register für nächsten Interrupt vorbelegen uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 1: //Die Pausen case 3: case 5: case 7: case 9: case 11: case 13: outport=0; ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=interpulspause; uc_low=ui_buffer&0x00FF; uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 2: outport=1; //Der zweite Impuls ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=ui_pulslengh[1]; //Pulslänge dazuzählen uc_low=ui_buffer&0x00FF; //OCR Register für nächsten Interrupt vorbelegen uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 4: outport=1; //Der dritte Impuls ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=ui_pulslengh[2]; //Pulslänge dazuzählen uc_low=ui_buffer&0x00FF; //OCR Register für nächsten Interrupt vorbelegen uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 6: outport=1; //Der vierte Impuls ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=ui_pulslengh[3]; //Pulslänge dazuzählen uc_low=ui_buffer&0x00FF; //OCR Register für nächsten Interrupt vorbelegen uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 8: outport=1; //Der fünfte Impuls ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=ui_pulslengh[4]; //Pulslänge dazuzählen uc_low=ui_buffer&0x00FF; //OCR Register für nächsten Interrupt vorbelegen uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 10: outport=1; //Der sechste Impuls ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=ui_pulslengh[5]; //Pulslänge dazuzählen uc_low=ui_buffer&0x00FF; //OCR Register für nächsten Interrupt vorbelegen uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 12: outport=1; //Der siebte Impuls ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=ui_pulslengh[6]; //Pulslänge dazuzählen uc_low=ui_buffer&0x00FF; //OCR Register für nächsten Interrupt vorbelegen uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 14: outport=1; //Der achte Impuls ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=ui_pulslengh[7]; //Pulslänge dazuzählen uc_low=ui_buffer&0x00FF; //OCR Register für nächsten Interrupt vorbelegen uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; case 15: outport=0; ui_buffer=OCR1AH; //Aktuelle Werte holen ui_buffer=(ui_buffer<<8)+OCR1AL; ui_buffer+=interframepause; uc_low=ui_buffer&0x00FF; uc_high=(ui_buffer>>8)&0x00FF; OCR1AH=uc_high; OCR1AL=uc_low; break; default: uc_cyclecount=0; } uc_cyclecount++; if(uc_cyclecount>maxcycle){uc_cyclecount=0;} } // Declare your global variables here void main(void) { // Declare your local variables here // Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=0x80; CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif // Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=0 State0=T PORTB=0x00; DDRB=0x02; // Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=T State5=T State4=T State3=P State2=P State1=P State0=P PORTC=0x0F; DDRC=0x00; // Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=P State2=P State1=P State0=P PORTD=0x0F; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped // Mode: Normal top=FFh // OC0A output: Disconnected // OC0B output: Disconnected TCCR0A=0x00; TCCR0B=0x00; TCNT0=0x00; OCR0A=0x00; OCR0B=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 1000,000 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: On // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x02; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2A output: Disconnected // OC2B output: Disconnected ASSR=0x00; TCCR2A=0x00; TCCR2B=0x00; TCNT2=0x00; OCR2A=0x00; OCR2B=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off // Interrupt on any change on pins PCINT0-7: Off // Interrupt on any change on pins PCINT8-14: On // Interrupt on any change on pins PCINT16-23: On EICRA=0x00; EIMSK=0x00; PCICR=0x06; PCMSK1=0x0F; PCMSK2=0x0F; PCIFR=0x06; // Timer/Counter 0 Interrupt(s) initialization TIMSK0=0x00; // Timer/Counter 1 Interrupt(s) initialization TIMSK1=0x02; // Timer/Counter 2 Interrupt(s) initialization TIMSK2=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; ADCSRB=0x00; // Watchdog Timer initialization // Watchdog Timer Prescaler: OSC/128k // Watchdog Timer interrupt: Off /*#pragma optsize- #asm("wdr") WDTCSR=0x1E; WDTCSR=0x0E; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif */ // Global enable interrupts #asm("sei") while (1) { #asm("wdr") // Place your code here }; }







Zitieren

Lesezeichen