Hallo Forum Ich möchte mittels eines Atmega 168 eine Frequenzmessung eines Rechtecksignals realisieren. Meiner meinung nach eignet sich der capture modes des Timers1 am besten dazu. Das Programm funktioniert im debugger auch schon. Bei einer fallenden flanke wird der capture interrupt ausgelöst und der timerwert gespeichert. überläufe des Timers werden auch berücksichtigt. Soweit müsste alles unktionieren Wenn ich allerdings das programm auf den uc spiele und ein pwm signal am port B0 anlege kommt nur müll raus. Ich hoffe es kann mir jemand helfen Die Routine zur Displayausgabe habe ich seperat getested müsste auch funktionierne. Villeciht kann sich jémand die Mühe machen und das Programm mal anschauen, währe echt nett Danke mfg //*********** Includes*************************************************** #include <avr\io.h> #include <avr\interrupt.h> #include <util\delay.h> //********************************************************************** ** //*********** Systemkonstanten****************************************** #define F_CLOCK 2E7 // 20MHz CPU Takt #define Zahn 6 // 6 Grad Zahn Teilung //********************************************************************** //*********** Globale Variablen****************************** double test,b_f;// b_f=1 wenn negative flanke long int ueberlauf=0; double init=0; //initialisierung bei 1.neg Flanke unsigned int counter=0; double counterold=0; //Zählerstand N-1.fallende Flanke double counternew=0; //Zählerstand N fallende Flanke double diff=0; //Differnez Zählerstand N und Zählerstand N-1 double cmax=65535; // max Zähler des 16 Bit counters double help=0;//Hilfsgrösse double flanke=0;//Hilfsgrosse für dsp long Frequenz=0; long zahl=0; unsigned int ICR1Htemp; unsigned int ICR1Ltemp; //********************************************************************** //*********** Interrupt für fallende Flanke****************************** ISR(TIMER1_CAPT_vect) { cli(); //intterrupt spreeren //PORTB ^= 0xFF; counter=ICR1H*0x100+ICR1L; //counter=ICR1H*0x100+ICR1L;//16 Bit Verrechung H und L Reg Timer 1 capure Register if(b_f==0) //Erkennung 1. Flanke { counterold=counter;//Zählerstand merken ueberlauf=0; b_f=1; } //if(b_f==1) else { counternew=counter;//Zählerstand merken //diff=counternew-counterold; //help=(ueberlauf-1)*cmax; diff=cmax-counterold+(ueberlauf-1)*cmax+counternew;//Berechnungsformel //b_f=0; ueberlauf=0; counterold=counternew; flanke=1; // diff=counter-counterold; } sei();// interrups global zulassen } //********************************************************************** ** //***********Interrupt für Zähler Überlauf******************************** ISR( TIMER1_OVF_vect) { cli(); //intterrupt spreeren ueberlauf++; //if(PORTC==0x00) //{ //PORTC=0xFF; //} //else //{ //PORTC=0x00; //} sei();// interrups global zulassen } //********************************************************************** * //*********************Display*********************************** //*********************Display*********************************** #define F_CPU 20000000 #define sbi(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT))) #define cbi(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT))) #define outp(VAL,ADRESS) ((ADRESS) = (VAL)) #define inp(VAL) (VAL) //////////////////////////////////////////////////////////////////////// ///// // allgemeine-Funktionen //---------------------------------------------------------------------- ----- // wait_ms(..) - Wartet einige Millisekunden // Die Dauer ist nicht kalibriert. // PE: miliSec=Anzahl der zu wartenden Millisekunden //---------------------------------------------------------------------- ----- void wait_ms(int miliSec) { _delay_loop_2( 1*(F_CPU/(1000/4)) * miliSec); // 4 Zyklen arteschleife } void wait_us(int mikroSec) { _delay_loop_2( 1*(F_CPU/(1000000/4)) * mikroSec); // 4 Zyklen arteschleife } //////////////////////////////////////////////////////////////////////// ////// // LCD-Funktionen für myAVR-Board + myAVR-LCD // 4-BitModus an PortD Bit 4-7 // PortD Bit 2 = RS, high=Daten, low=Kommando // PortD Bit 3 = E, high-Impuls für gültige Daten //---------------------------------------------------------------------- ----- // lcd_send(..) - sendet ein Byte an LCD im 4-Bit-Modus // RS muss vorher richtig gesetzt sein // PE: data=zu sendendes Byte //---------------------------------------------------------------------- ----- void lcd_send(char data) { // aktuelles RS ermitteln char rs=PORTD; rs&=4; // High-Teil senden char tmp=data; tmp&=0xf0; tmp|=rs; PORTD=tmp; // Schreibsignal sbi(PORTD,3); cbi(PORTD,3); // Low-Teil senden tmp=data; tmp&=0x0f; tmp*=16; tmp|=rs; PORTD=tmp; // Schreibsignal sbi(PORTD,3); cbi(PORTD,3); // verarbeiten lassen wait_ms(1); } //---------------------------------------------------------------------- ----- // lcd_cmd(..) - sendet ein Kommando an LCD // PE: cmd=Kommando-Byte //---------------------------------------------------------------------- ----- void lcd_cmd(char cmd) { cbi(PORTD,2); // RS löschen = Kommando lcd_send(cmd); // senden } //---------------------------------------------------------------------- ----- // lcd_write(..) - sendet ein Zeichen (Daten) an LCD // PE: text=Zeichen //---------------------------------------------------------------------- ----- //---------------------------------------------------------------------- ----- // lcd_write(..) - sendet ein Zeichen (Daten) an LCD // PE: text=Zeichen //---------------------------------------------------------------------- ----- void lcd_write(char text) { sbi(PORTD,2); // RS setzen = Daten lcd_send(text); // senden } //---------------------------------------------------------------------- ----- // lcd_home(..) - Cursor auf Position 1,1 //---------------------------------------------------------------------- ----- void lcd_home() { lcd_cmd(0x02); wait_ms(2); // warten } //---------------------------------------------------------------------- ----- // lcd_clear(..) - löscht die Anzeige im LCD //---------------------------------------------------------------------- ----- void lcd_clear() { lcd_cmd(0x01); wait_ms(2); // warten } //---------------------------------------------------------------------- ----- // lcd_on(..) - schaltet das LCD an //---------------------------------------------------------------------- ----- void lcd_on() { lcd_cmd(0x0E); } //---------------------------------------------------------------------- ----- // lcd_off(..) - schaltet das LCD aus //---------------------------------------------------------------------- ----- void lcd_off() { lcd_cmd(0x08); } //---------------------------------------------------------------------- ----- // lcd_goto(..) - setzt die Cursorposition // PE: row = Zeile 1..2 // col = Spalte 1..16 //---------------------------------------------------------------------- ----- void lcd_goto(int row, int col) { row--; // Null-basierend row&=0x01; // sicherheitshalber row*=0x40; // Zeile nach Bit 6 bringen col--; // Null-basierend col&=0x0f; // sicherheitshalber char tmp=row|col; tmp|=0x80; // Cursor setzen lcd_cmd(tmp); // senden } //---------------------------------------------------------------------- ----- // lcd_init(..) - Schaltet die Ports und Initialisiert das LCD //---------------------------------------------------------------------- ----- void lcd_init() { // Port D = Ausgang DDRD=0xff; PORTD=0; // warten bist LCD-Controller gebootet wait_ms(50); // SOFT-RESET PORTD = 0x30; //0b00110000; sbi(PORTD,3); cbi(PORTD,3); wait_ms(5); PORTD = 0x30; //0b00110000; sbi(PORTD,3); cbi(PORTD,3); wait_us(100); PORTD = 0x30; //0b00110000; sbi(PORTD,3); cbi(PORTD,3); wait_ms(5); // 4-BitModus einschalten PORTD=0x20; // Schreibsignal sbi(PORTD,3); cbi(PORTD,3); wait_ms(5); // ab hier im 4-Bit-Modus lcd_cmd(0x28); // Funktions-Set: 2 Zeilen, 5x7 Matrix, 4 Bit //lcd_off(); lcd_cmd(0x06); // Entry Mode lcd_on(); lcd_clear(); } //********************************************************************** *** int main(void) { unsigned long i; //lokale Zähler Variable unsigned long rest=0; //unsigned long anz=0; i=0; //test=9999; DDRC=0xFF; //PORTC=0x00; b_f=0; //flanken erkennung init ueberlauf=0;// diff=0; counterold=0; //Zählerstand N-1.fallende Flanke counternew=0; //Zählerstand N fallende Flanke Frequenz=0; long anz; //---------------------Timer 1 Konfiguration---------------------------- TCCR1B = 0x07; // capture neg. Flanke und prescaler 1 TIMSK1 = 0x21; // interrupt Enable ovfer flow Enable &Capture Enable sei();// interrups global zulassen //--------------------------------------------------------------- wait_ms(200); lcd_init(); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write(' '); lcd_write('H'); lcd_write('r'); lcd_home(); lcd_write ('0'); PORTC=0xFF; while( 1==1 ) { wait_ms(1000); if(PORTC==0x00) { PORTC=0xFF; } else { PORTC=0x00; } if(flanke==1) { //Frequenz=F_CLOCK*cmax/diff; Frequenz=F_CLOCK*cmax/diff; rest=Frequenz; for(i=1000000;i>0;i/=10) { anz=rest/i; rest %=i; if(rest!=zahl) { lcd_write (anz +'0'); //wait_ms(200); } } lcd_home(); flanke=0; lcd_clear(); } } }
Es reicht auch in einem Forum zu posten. Hier sollten nur fertige Codes sein...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.