Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problems with PWM measuring using ICP in ATMega328

Status
Not open for further replies.

feluma

Newbie level 1
Joined
Oct 15, 2009
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,287
Hello,

I'm new to PWM techniques and I can't find a simple code to compare mine to get a PW mesure using my ATMega328.

The problem is that right now I get measures, but they are not consistent, they present a very wide range of values for the same input signal; I don't know if this is because some asyncronous problem wrong set of registers or other thing.

If somebady could help me would be nice.

Code:
#include <avr\io.h>
#include <avr\interrupt.h>
#include <stdio.h>
#include <string.h>
#define F_CPU 8000000
#include <util/delay.h>



//Asynchronous serial communication

#define BAUD 9600
#define MYUBRR ((F_CPU/BAUD/16)-1)



//ICP measuring

#define ICP PINB0

//define ovrflow counter
uint16_t ov_counter;

//define times for start and end of signal
uint16_t rising, falling;

//define overall counts
uint32_t counts;


//overflow counter interrupts service routine
ISR(TIMER1_OVF_vect){
  ov_counter++;
}

//Timer1 capture interrupt service subroutine
ISR(TIMER1_CAPT_vect){

	// This subroutine checks was it start of pulse (rising edge) 
    // or was it end (fallingedge) and performs required operations

	if (ICP){ //if high level

            //save start time

            rising=ICR1;

            //set to trigger on falling edge

            TCCR1B=TCCR1B&0xBF;

            //reset overflow counter

            ov_counter=0;

	}
	else{

            //save falling time

            falling=ICR1;

            //rising edge triggers next

            TCCR1B=TCCR1B|0x40;

            counts=(uint32_t)falling-(uint32_t)rising+(uint32_t)ov_counter;

			//you can convert coutns to seconds and send to LCD
			printf("%lu\n", (unsigned long)counts); //Values variates from 800 to 62000 for the same input signal.
            }
	_delay_ms(100);
}



//Define functions
//======================

void ioinit(void); // Initializes IO
static int uart_putchar(char c, FILE *stream);
uint8_t uart_getchar(void);

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);


int main(void) {

	ioinit(); //Setup IO pins and defaults

	//PWM
	TIMSK1=0x24; //Enable overflow and input capture interrupts
	TCCR1B=0xC1; //Noise canceller, without prescaler, rising edge
	sei(); //Enable interrupts

    while(1) {  // Loop forever timer does the job
	}


return(0);
}




void ioinit (void)
{
    //1 = output, 0 = input
    DDRB = 0b11111110; //PORTB (yP on PB0 / Accelerometer)
    DDRC = 0b11111111; //
    DDRD = 0b11111110; //PORTD (RX on PD0)

    UBRR0H = 0b00000000;
    UBRR0L = 0b00110011;

	UCSR0A = 0b00100000;
	UCSR0B = 0b00011000;
	UCSR0C = 0b00110110;

    
    stdout = &mystdout; //Required for printf init



	
}


static int uart_putchar(char c, FILE *stream)
{
    if (c == '\n') uart_putchar('\r', stream);
  
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;
    
    return 0;
}

uint8_t uart_getchar(void)
{
    while( !(UCSR0A & (1<<RXC0)) );
    return(UDR0);
}
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top