/* frequency.c measure frequency on PB0/ICP1 */ /* also generates a testsignal on D06/PD6/OC0A to measure */ // Arduino UNO R3 // AVR_ATmega328P #define F_CPU 16000000UL #include #include void init_tmr1_capture( void ); void init_uart( void ); void generate_test_signal( void ); void putchar_uart( unsigned char ); void string_out_uart( char * ); void decimal_out_uart( signed int number, unsigned char fixed_decimals, char format ); #define DECIMAL_MARK ',' #define SIGN 1 #define NOSIGN 0 int main(void) { unsigned int T1, T2, T, f; generate_test_signal( ); init_uart( ); init_tmr1_capture( ); while(1) { // Bits in TIFR1 register: "- - ICF1 - - OCFB OCFA TOV" TIFR1 |= ( 1 << ICF1 ); // "--1-----" reset ICF1 flag while( (TIFR1 & (1 << ICF1))==0 ) {} // Wait for ICF1 flag T1 = ICR1; TIFR1 |= ( 1 << ICF1 ); // "--1-----" reset ICF1 flag while( (TIFR1 & (1 << ICF1))==0 ) {} // Wait for ICF1 flag T2 = ICR1; T = T2 - T1; // calculate period f = (unsigned int) (2000000UL /((unsigned long int)T)); string_out_uart( "\r\nFrequency f is [Hz]: " ); decimal_out_uart( f, 0, NOSIGN ); _delay_ms( 1000 ); } return 0; // never reached } /* *********************************** */ /* FUNCTIONS */ /* *********************************** */ void init_tmr1_capture( void ) { // DDRB &= ~( 1 << PB0 ); // PB0/ICP1 "0" is input - default nothing has to be done // PRR &= ~( 1 << PRTIM1 ); // enable TC1 module - default nothing has to be done // Setup TIMER1 Compare mode // Bits in TCCR1A register: "COM1 COM1 COM1 COM1 - - WGM11 WGM10" // Bits in TCCR1B register: "ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10" // normal mode "WGM13 WGM12" "WGM11 WGM10" "00" "00" - default nothing has to be done TCCR1B |= ( 1 << ICES1 ); // "-1------" Capture on rising edge // TIMER1 clock prescaler "CS12 CS11 CS10" // "001" clk/1, "010" clk/8, "011" clk/64, "100" clk/256, "101" clk/1024 TCCR1B |= ( 1 << CS11 ); // "-----010" clk/8 -> TIMER1_tick is 0.5 us (2 MHz) } void init_uart( void ) { // Bits in UCSR0B register: "RXCIE0 TXCIE0 UDRIE0 RXEN0 TXEN0 UCSZ02 RXB80 TXB80" UCSR0B |= (1<<(RXEN0)) | (1<<(TXEN0)); // "----1---" // Bits in UCSR0C register: "UMSEL01 UMSEL00 UPM01 UPM00 USBS0 UCSZ01/UCPHA0 UCSZ01/UCPHA0 UCPOL0" UCSR0C |= (1<<(UCSZ01)) | (1<<(UCSZ00)); // "-----11-" UBRR0 = 103; // Baud prescaler 103 -> 9600 Baud } unsigned char getchar_uart( void ) { unsigned char ch; // Bits in UCSR0A register: "RXC0 TXC0 UDRE0 FE0 DOR0 UPE0 U2X0 MPCM0" // wait until a byte is ready to read while( ( UCSR0A & ( 1<<(RXC0) ) ) == 0 ){} // grab the byte from the serial port ch = UDR0; return ch; } void putchar_uart( unsigned char ch ) { // Bits in UCSR0A register: "RXC0 TXC0 UDRE0 FE0 DOR0 UPE0 U2X0 MPCM0" // wait until the port is ready to be written to while( ( UCSR0A & ( 1<<(UDRE0) ) ) == 0 ){} // write the byte to the serial port UDR0 = ch; } void string_out_uart( char * string ) // use for strings in RAM { while (* string != '\0') putchar_uart(*string ++); } void decimal_out_uart( signed int number, unsigned char fixed_decimals, char format ) { unsigned char i; unsigned int divisor = 10000; if (format == SIGN) { if (number < 0 ) { putchar_uart( '-' ); number = -number; } else putchar_uart( '+' ); } for(i=0; ;i++) { putchar_uart( (unsigned char)(number/divisor) + '0' ); if( i==4 ) break; if( i== ( 4 - fixed_decimals) ) putchar_uart( DECIMAL_MARK ); number %= divisor; divisor /= 10; } } void generate_test_signal( void ) { // generates 7812 Hz test signal on D06/PD6/OC0A // so there is a something to measure DDRD |= (1 << DDD6); // PD6 (PWM pin OC0A) is now an output OCR0A = 128; // set PWM for 50% duty cycle at pin OC0A // Bits in TCCR0A register: "COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00" TCCR0A |= (1 << COM0A1); // set none-inverting mode "10------" TCCR0A |= (1 << WGM01) | (1 << WGM00); // set fast PWM Mode "------11" // Bits in TCCR0B register: "FOC0A FOC0B - - WGM02 CS02 CS01 CS00" TCCR0B |= (1 << CS01); // set prescaler to 8 and starts PWM "-----010" } /* *********************************** */ /* HARDWARE */ /* *********************************** */ /* Chip ATMega328 Arduino Uno R3 stackable header _______ Digital: _____/ \__ Analog: ______________ ______________ txd ->-|D00 >RXD A5|- | \/ | rxd -<-|D01 -(D01)-|03 PD1/TXD PC3 26|-(A3)- -|D04 A1|- -(D02)-|04 PD2/INT0 PC2 25|-(A2)- -|D05~ A0|- -(D03)-|05 PD3/INT1/PWM PC1 24|-(A1)- Tst-<-|D06~ | Power: -(D04)-|06 PD4 PC0 23|-(A0)- -|D07 Vin|- +5V ---|07 VCC GND 22|--- Gnd | GND|- Gnd ---|08 GND AREF 21|--- Vin f ->-|D08 GND|- Xtal |X|--|09 PB6/OSC1 AVCC 20|--- +5V -|D09~ +5V|- 16MHz |X|--|10 PB7/OSC2 SCK/PB5 19|-(D13)- -|D10~ +3.3V|- -(D05)-|11 PD5/PWM MISO/PB4 18|-(D12)- -|D11~ Res|- Tst-<-(D06)-|12 PD6/PWM PWM/MOSI/PB3 17|-(D11)- -|D12 IOREF|- -(D07)-|13 PD7 PWM/SS'/PB2 16|-(D10)- -|D13 LED --- | f ->-(D08)-|14 PB0 PWM/PB1 15|-(D09)- -|GND | |______________________________| -|AREF | -|SCL | Connect Tst to f to measure 7812 Hz -|SDA | |________________| */