Electronic – How to estimate the speed of this code section for this microcontroller

cclockmicrocontrollerprogramming

I'm using an ATmega328P to read the state of a digital input by using the following code section written in C (there can be alternative ways, but this is an example). val is a uint8_t variable type, and it stores the state of the digital input pin:

Here is the part of the code:

if ((PIND & (1 << PIND6)) == (1 << PIND6)) {
    val = 1;
} else {
    val = 0;
}

I set the clock as:

#define F_CPU   16000000UL

Imagine the digital input is an ON/OFF pulse train with 50% duty cycle and we gradually increase the frequency of it. At some point at a certain frequency the code above should not be able to capture the digital input state correctly.

  1. How can we estimate roughly the maximum pulse frequency the above code can handle to read the state correct?
  2. Should we find how many clock cycles it uses and multiply it by the clock frequency?
  3. And if so, how can I do it in practice?

    int main(void) {
    
        DDRD = B0100000;
        DDRD |= 1<<5;
    
        while (1) {
    
            unsigned long data = 0;
            uint8_t val;
    
            for (int i=0; i<25; i++) {
                data <<= 1;
                PORTD &= ~(1 << 5);
                _delay_us(2);
                PORTD |= (1 << 5);
                _delay_us(2);
    
                if ( (PIND & (1 << PIND6)) == (1 << PIND6) ) {
                    val = 1;
                } 
                else {
                    val = 0;
                }
    
                data |= val;
            }            
    
            // The rest of the code
    
        }
    }
    

Best Answer

  1. Since the code snippet you're interested in isn't big, you could disassemble your compiled code, look at all the assembly instructions and count how many cycles they need. You can find the number of cycles for each instruction in the datasheet.

  2. If you have an oscilloscope, you can turn on a pin before the if statement and turn it off after your code snippet. (Using direct port manipulation PORTB, not the Arduino library function) With a scope you can see how long it takes to run the code.

  3. Use the micros() function in the Arduino library. Place one before and after the code snippet. However here you will have a couple of microseconds overhead since the 'micros()' has to run as well.

  4. Use a debugger or hardware simulator that can count cycles. Put a breakpoint on the first statement of the code snippet and one on the statement after the snippet. delta_t = cycles / clock_freq (in line with Oldfart's answer)