Display delay

When you say timers, are you thinking of timing in the abstract sense, or are you talking about switching to using the actual hardware timers on the AVR? Actually, it looks like it would be pretty simple to modify the code you have now to do something like you describe. Keep in mind that incrementing variables takes almost no time compared to the millisecond delays, so you could have multiple “timebetweenbuttonpresses” type variables adding up at the same time. You can also have one variable that counts up in between millisecond delays, and make copies of it’s value in other variables when events occur, like a lap timer.

-Adam

I have been a real idiot and didnt realise that there was a second page - thats where my posts were going!

Yeah i tried removing the scanf lines etc, and replacing with the line that we have been using in the timer function when the jumpers are touched but arent quite getting satisfactory results…

with regard to the timer bit, when i say timer i mean our function that times between jumper touching, not the built in timers…

so runner 1 and 2 start a 20 meter relay where they kee going from end to end i am timing the length of each length for both runners.

touch jumpers starts both “timers”;
runner 1 reaches end - press his jumper
runner 2 reaches end - press his jumper
runner 1 reaches other end - press his jumper
runner 2 reaches other end - and press his jumper

now i have times for two laps for each runner, my worry is that c reads code in order and so if the next line is waiting for runner 1’s jumper and i press runner 2’s because he got there first, will it do the correct thing???

nailed the menu issue, just the two timers now!

        // F_CPU tells util/delay.h our clock frequency
        #define F_CPU 8000000UL   // Orangutan frequency (8MHz)

        #include <avr/io.h>
        #include <util/delay.h>

        uint32_t timebetweenbuttonpresses;
		
		uint32_t secondtimebetweenbuttonpresses;

        #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
        #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

        //ABOVE HERE = STANDARD
           
        //call delay function

        void delayms( uint16_t millis ) {
           while ( millis ) {
              _delay_ms( 1 );
              millis--;
           }
        }

        //--------------------------------
        //All to do with ADC
        //--------------------------------

        void analog_init(void)
        {

           ADMUX = (1 << REFS0);
           ADCSRA = (6 << ADPS0);
           ADCSRA |= (1 << ADEN);
        }


        // Read out the specified analog channel to 10 bits
        unsigned int analog10(unsigned char channel)
        {
           // Clear the channel selection (low 5 bits in ADMUX)
           ADMUX &= ~0x1F;
           // Select the specified channel
           ADMUX |= channel;

           ADCSRA |= (1 << ADSC);

           while (bit_is_set(ADCSRA, ADSC));
           return (ADCL | ADCH << 8);   // read ADC (full 10 bits);
        }

        unsigned int analog8(unsigned char channel)
        {
           return(analog10(channel) >> 2);
        }


        //--------------------------------
        //All to do with ADC
        //--------------------------------

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s'};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


        //STANDARD MAIN FUNCTION

        int main( void )
        {

          //--------------------------------------
          //LCD STUFF TO GO IN MAIN FUNCTION
          //--------------------------------------
          int i;

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------

       cbi(DDRC, DDC5);
       sbi(PORTC, PC5);


           while(1)
           {
		   switch(menu())
         {
            case 1: /*Adding the data to the program*/
                        {
                            
                            
                            lcd_line1();
            				lcd_string("strttmr");
                            timer();
                            break;
                        }
            
         }  /* End of switch */
    }       /* End of while  */

          

			   
				    //delay_sec(2);

           // A variable to store our converted analog value in:
              //int pot;

              // Initialize the ADC:
             // analog_init();

              //SETTING PORT OUTPUTS INPUTS: REMEMBER CANT USE SWITCHES AND LCD...
           
           //   DDRB |= (1 << PB0);      // set buzzer pin PB0 to output
           //   DDRC |= (1<< PC5);// led breadboard
           //   DDRB &= ~(1 << PB3);  // make PB3 (button SW3 pin) an input - cant use with LCD
              //DDRD |= (1<<PD1); //Led output

              //-----------------------------------------
              //COMMANDS FOR PRINTING WITH LCD
              //-----------------------------------------
           
              //for(;;)
           //   {
              //pot = analog10(6);
           //   if (pot > 100)
           //{   
           //PORTC |= (1<< PC5);// turn on breadboard (sonar transmitter)
                 //PORTB |= ( 1 << PB0 );   // buzzer on
                 //PORTD |= (1 << PD1);//LED ON
                 //delayms( 90 );         // delay 50 ms
                 //PORTB &=~ (1 << PB0); //BUZZER Off
                 //PORTC &= ~(1 << PC5);//turn off bread board (sonar transmitter)
             
                 //PORTD &= ~(1 << PD1);       // LED OFF
             
              //   }

              //else
           
              //PORTD &= ~(1 << PD1);
              //PORTC |= (1<< PC5);
              //delayms( 45 );
              //PORTC &= ~(1 << PC5);
           
                 // Startup Banner
             

              //}

              //   delay_sec(2);
              
           return 1;

        }

int timer(void)
{
while(1)
{
		
	
		lcd_line1();
            lcd_string("Psh2Strt");

	
//first lap time
          while(bit_is_set(PINC, PINC5));//do nothing

           if (bit_is_clear(PINC, PINC5))
           _delay_ms(50);
           while (bit_is_clear(PINC, PINC5))
           _delay_ms(50);

          lcd_clear();
		  lcd_line1();
            lcd_string("1");
          lcd_line2();
            lcd_string("Counting");
           timebetweenbuttonpresses=0;

           while bit_is_set(PINC, PINC5)
           {
              _delay_ms(1);
              timebetweenbuttonpresses++;
           }

			
			lcd_clear();
                

//attempt at second lap

			  
           while (bit_is_clear(PINC, PINC5))
           _delay_ms(50);

          lcd_clear();
		  lcd_line1();
            lcd_string("2");
          lcd_line2();
            lcd_string("Counting");
           secondtimebetweenbuttonpresses=0;

           while bit_is_set(PINC, PINC5)
           {
              _delay_ms(1);
              secondtimebetweenbuttonpresses++;
           }

		   lcd_clear();
                
			  
		//final results
		
			  lcd_clear();
                 lcd_line1();
                 lcd_time(timebetweenbuttonpresses);
                 lcd_line2();
                 lcd_time(secondtimebetweenbuttonpresses);
			delay_sec(6);
		lcd_clear();
		
		main();
		/*while end*/}

		/* funct end*/	}





/* Displays a menu and inputs user's selection back into the main function */
int menu(void)
{
    int reply;

//this is where i'm struggling... what do i do when the user presses jumpers on PC5 to choose the option

   //option 1 start lcd_line1();
     lcd_string("option 1");
while(bit_is_set(PINC, PINC5));//do nothing

           if (bit_is_clear(PINC, PINC5))
       
           _delay_ms(50);
    reply = 1;
    _delay_ms(10);

	//option 1 end
    return (reply); /*Sends the reply to the main function*/
}

check the bottom bit - the function called menu…

I have attempted the second timer on PC4, and two some sort of extent it works, you have to do odd touching of all wires, this one first that one next etc, i’m gonna keep trying to tidy it up but if you see my mistake please can you point it out.

thanks

        // F_CPU tells util/delay.h our clock frequency
        #define F_CPU 8000000UL   // Orangutan frequency (8MHz)

        #include <avr/io.h>
        #include <util/delay.h>

        uint32_t buttonpresstimer1;
		
		uint32_t secondbuttonpresstimer1;

		uint32_t buttonpresstimer2;

		uint32_t secondbuttonpresstimer2;

        #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
        #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

        
		//ABOVE HERE = STANDARD
        int const mass = 8;
		int const radius = 100;
		
		   
        //call delay function

        void delayms( uint16_t millis ) {
           while ( millis ) {
              _delay_ms( 1 );
              millis--;
           }
        }

        //--------------------------------
        //All to do with ADC
        //--------------------------------

        void analog_init(void)
        {

           ADMUX = (1 << REFS0);
           ADCSRA = (6 << ADPS0);
           ADCSRA |= (1 << ADEN);
        }


        // Read out the specified analog channel to 10 bits
        unsigned int analog10(unsigned char channel)
        {
           // Clear the channel selection (low 5 bits in ADMUX)
           ADMUX &= ~0x1F;
           // Select the specified channel
           ADMUX |= channel;

           ADCSRA |= (1 << ADSC);

           while (bit_is_set(ADCSRA, ADSC));
           return (ADCL | ADCH << 8);   // read ADC (full 10 bits);
        }

        unsigned int analog8(unsigned char channel)
        {
           return(analog10(channel) >> 2);
        }


        //--------------------------------
        //All to do with ADC
        //--------------------------------

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s'};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


        //STANDARD MAIN FUNCTION

        int main( void )
        {

          //--------------------------------------
          //LCD STUFF TO GO IN MAIN FUNCTION
          //--------------------------------------
          int i;

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------

       cbi(DDRC, DDC5);
       sbi(PORTC, PC5);
	   cbi(DDRC, DDC4);
       sbi(PORTC, PC4);


           while(1)
           {
		   switch(menu())
         {
            case 1: /*Adding the data to the program*/
                        {
                            
                            
                            lcd_line1();
            				lcd_string("strttmr");
                            timer1();
							
                            break;
                        }
            
         }  /* End of switch */
    }       /* End of while  */

          

			   
				    //delay_sec(2);

           // A variable to store our converted analog value in:
              //int pot;

              // Initialize the ADC:
             // analog_init();

              //SETTING PORT OUTPUTS INPUTS: REMEMBER CANT USE SWITCHES AND LCD...
           
           //   DDRB |= (1 << PB0);      // set buzzer pin PB0 to output
           //   DDRC |= (1<< PC5);// led breadboard
           //   DDRB &= ~(1 << PB3);  // make PB3 (button SW3 pin) an input - cant use with LCD
              //DDRD |= (1<<PD1); //Led output

              //-----------------------------------------
              //COMMANDS FOR PRINTING WITH LCD
              //-----------------------------------------
           
              //for(;;)
           //   {
              //pot = analog10(6);
           //   if (pot > 100)
           //{   
           //PORTC |= (1<< PC5);// turn on breadboard (sonar transmitter)
                 //PORTB |= ( 1 << PB0 );   // buzzer on
                 //PORTD |= (1 << PD1);//LED ON
                 //delayms( 90 );         // delay 50 ms
                 //PORTB &=~ (1 << PB0); //BUZZER Off
                 //PORTC &= ~(1 << PC5);//turn off bread board (sonar transmitter)
             
                 //PORTD &= ~(1 << PD1);       // LED OFF
             
              //   }

              //else
           
              //PORTD &= ~(1 << PD1);
              //PORTC |= (1<< PC5);
              //delayms( 45 );
              //PORTC &= ~(1 << PC5);
           
                 // Startup Banner
             

              //}

              //   delay_sec(2);
              
           return 1;

        }

int timer1(void)
{
while(1)
{
		
	
		lcd_line1();
            lcd_string("Psh2Strt");

	
//first lap time both timers
          while(bit_is_set(PINC, PINC5));//do nothing

//trying to make two simultaneous timers...

while(bit_is_set(PINC, PINC4));//do nothing (timer 2)

           if (bit_is_clear(PINC, PINC4))
           _delay_ms(50);
           while (bit_is_clear(PINC, PINC4))
           _delay_ms(50);

          lcd_clear();
		  lcd_line2();
            lcd_string("1b");
          
           buttonpresstimer2=0;

           while bit_is_set(PINC, PINC4)
           {
              _delay_ms(1);
              buttonpresstimer2++;
           }

			
			

//other timer...


           if (bit_is_clear(PINC, PINC5))
           _delay_ms(50);
           while (bit_is_clear(PINC, PINC5))
           _delay_ms(50);

          lcd_clear();
		  lcd_line1();
            lcd_string("1");
          
           buttonpresstimer1=0;

           while bit_is_set(PINC, PINC5)
           {
              _delay_ms(1);
              buttonpresstimer1++;
           }

			lcd_line1();
            lcd_time(buttonpresstimer1);
			lcd_line2();
            lcd_time(buttonpresstimer2);
			//lcd_clear();
                

//attempt at second lap
/*
			  
           while (bit_is_clear(PINC, PINC5))
           _delay_ms(50);

          lcd_clear();
		  lcd_line1();
            lcd_string("2");
          
           secondbuttonpresstimer1=0;

           while bit_is_set(PINC, PINC5)
           {
              _delay_ms(1);
              secondbuttonpresstimer1++;
           }

		   lcd_clear();
                
			  //final results
		
*/


			  lcd_clear();
                 lcd_line1();
                 lcd_time(buttonpresstimer1);
                 lcd_line2();
                 lcd_time(buttonpresstimer2);
			delay_sec(6);
		lcd_clear();
		
		main();
		
		/*while end*/}

		/* funct end*/	}





/* Displays a menu and inputs user's selection back into the main function */
int menu(void)
{
    int reply;

//this is where i'm struggling... what do i do when the user presses jumpers on PC5 to choose the option

   //option 1 start lcd_line1();
     lcd_string("option 1");
while(bit_is_set(PINC, PINC5));//do nothing

           if (bit_is_clear(PINC, PINC5))
       
           _delay_ms(50);
    reply = 1;
    _delay_ms(10);

	//option 1 end
    return (reply); /*Sends the reply to the main function*/
}

The way your timer1 function is written you have to ground PC5 and then PC4 to get to the actual timing part. You have to ground PC5 to get past this line:
while(bit_is_set(PINC, PINC5));//do nothing

And then you have to ground PC4 to get past this line:
while(bit_is_set(PINC, PINC4));//do nothing (timer 2)

If you wanted to start timing when either button is pressed, you could merge those two lines into something like:
while(bit_is_set(PINC, PINC5)&&bit_is_set(PINC, PINC4));

Or, if you wanted to start different timers for the different cases, you could do something like this:

while(1){ if(bit_is_clear(PINC, PINC5)){ timer1(); break; }else if(bit_is_clear(PINC, PINC5)){ timer2(); break; } }
Also, inside your timer1 function, you have the line:
while(bit_is_set(PINC, PINC5)&bit_is_set(PINC, PINC4));

A single & is a bitwise and operation. In this case it may work the way you want it to depending on the return value of the bit_is_set function, but the header description of that function only says that it returns non-zero numbers when true, but not necessarily numbers that evaluate as true after a bitwise and operation. If that didn’t make any sense, don’t worry about it. What you really want to use is the logical and operator &&, as in if A and B are both true, then do something.

There are also a couple of methodology mistakes that might come back to byte you later. It’s usually not a great idea to call your main function at all, or create recursive function loops unless you really want to (like function A calls function B calls function A). It will rerun initialization functions you probably only want to run once, and it will create new copies of variables and state information that can fill up the free memory and lead to weird errors like stack overflows and things that are really hard to diagnose on a microcontroller. In this case your call to main at the end of the timer1 function is completely unnecessary, since the while(1) loop in main will keep calling the menu after timer1 returns.

One other quick mistake I see is that you’re referencing functions before you’ve created them, specifically you call the functions “menu” and “timer1” in main, but you don’t actually define them until later in the code. That why you’re getting those “implicit declaration of of function” warnings.

WinAVR seems to handle this for you, but generally in C you either need to order the functions so that you call them after you’ve written them, or write what are called function prototypes up at the top of the code. It’s sort of like an index, only at the beginning of the book. For simplicity a lot of people just like to put their “main” function at the very end of the code, which works fine too.

I know it sounds like a lot of problems, but it’s really just the simple mistakes that everyone makes. Your timer project is actually coming along quite nicely!

-Adam

yeah thanks adam, for a first major project i’m not displeased… and i noticed that there were lots of warnings but tried to hide from those at the mo!!! prob not a good idea though,

ok i’ll try what you said about those timer things in the morning, and fix those warnings, i’d like it to be quite a neat project

i didnt really understand that && stuff, but i definately got the overall jist of what you were saying. i’ll see what happens. thanks

Hey adam, thats neater yeah, but it still goes back to my original worry that c reads code in order,

        // F_CPU tells util/delay.h our clock frequency
        #define F_CPU 8000000UL   // Orangutan frequency (8MHz)

        #include <avr/io.h>
        #include <util/delay.h>

        uint32_t buttonpresstimer1;
		
		uint32_t secondbuttonpresstimer1;

		uint32_t buttonpresstimer2;

		uint32_t secondbuttonpresstimer2;

        #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
        #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

        
		//ABOVE HERE = STANDARD
        int const mass = 8;
		int const radius = 100;
		
		   
        //call delay function

        void delayms( uint16_t millis ) {
           while ( millis ) {
              _delay_ms( 1 );
              millis--;
           }
        }

        //--------------------------------
        //All to do with ADC
        //--------------------------------

        void analog_init(void)
        {

           ADMUX = (1 << REFS0);
           ADCSRA = (6 << ADPS0);
           ADCSRA |= (1 << ADEN);
        }


        // Read out the specified analog channel to 10 bits
        unsigned int analog10(unsigned char channel)
        {
           // Clear the channel selection (low 5 bits in ADMUX)
           ADMUX &= ~0x1F;
           // Select the specified channel
           ADMUX |= channel;

           ADCSRA |= (1 << ADSC);

           while (bit_is_set(ADCSRA, ADSC));
           return (ADCL | ADCH << 8);   // read ADC (full 10 bits);
        }

        unsigned int analog8(unsigned char channel)
        {
           return(analog10(channel) >> 2);
        }


        //--------------------------------
        //All to do with ADC
        //--------------------------------

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s'};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


        //STANDARD MAIN FUNCTION

        int main( void )
        {

          //--------------------------------------
          //LCD STUFF TO GO IN MAIN FUNCTION
          //--------------------------------------
          int i;

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------

       cbi(DDRC, DDC5);
       sbi(PORTC, PC5);
	   cbi(DDRC, DDC4);
       sbi(PORTC, PC4);


           while(1)
           {
		   timer1();
		   /*switch(menu())
         {
            case 1: /*Adding the data to the program
                        {
                            
                            
                            lcd_line1();
            				lcd_string("strttmr");
                            timer1();
							
                            break;
                        } 
            
         }   End of switch */
    }       /* End of while  */

          

			   
				    //delay_sec(2);

           // A variable to store our converted analog value in:
              //int pot;

              // Initialize the ADC:
             // analog_init();

              //SETTING PORT OUTPUTS INPUTS: REMEMBER CANT USE SWITCHES AND LCD...
           
           //   DDRB |= (1 << PB0);      // set buzzer pin PB0 to output
           //   DDRC |= (1<< PC5);// led breadboard
           //   DDRB &= ~(1 << PB3);  // make PB3 (button SW3 pin) an input - cant use with LCD
              //DDRD |= (1<<PD1); //Led output

              //-----------------------------------------
              //COMMANDS FOR PRINTING WITH LCD
              //-----------------------------------------
           
              //for(;;)
           //   {
              //pot = analog10(6);
           //   if (pot > 100)
           //{   
           //PORTC |= (1<< PC5);// turn on breadboard (sonar transmitter)
                 //PORTB |= ( 1 << PB0 );   // buzzer on
                 //PORTD |= (1 << PD1);//LED ON
                 //delayms( 90 );         // delay 50 ms
                 //PORTB &=~ (1 << PB0); //BUZZER Off
                 //PORTC &= ~(1 << PC5);//turn off bread board (sonar transmitter)
             
                 //PORTD &= ~(1 << PD1);       // LED OFF
             
              //   }

              //else
           
              //PORTD &= ~(1 << PD1);
              //PORTC |= (1<< PC5);
              //delayms( 45 );
              //PORTC &= ~(1 << PC5);
           
                 // Startup Banner
             

              //}

              //   delay_sec(2);
              
           return 1;

        }

int timer1(void)
{
while(1)
{
		
	
		lcd_line1();
            lcd_string("Psh2Strt");

	
//start timers...
          while(1){
   if(bit_is_clear(PINC, PINC5)){
      if (bit_is_clear(PINC, PINC5))
           _delay_ms(50);
           while (bit_is_clear(PINC, PINC5))
           _delay_ms(50);

          lcd_clear();
		  lcd_line1();
            lcd_string("1");
          
           buttonpresstimer1=0;

           while bit_is_set(PINC, PINC5)
           {
              _delay_ms(1);
              buttonpresstimer1++;
           }
      break;
   }else if(bit_is_clear(PINC, PINC4)){
      if (bit_is_clear(PINC, PINC4))
           _delay_ms(50);
           while (bit_is_clear(PINC, PINC4))
           _delay_ms(50);

          lcd_clear();
		  lcd_line2();
            lcd_string("1b");
          
           buttonpresstimer2=0;

           while bit_is_set(PINC, PINC4)
           {
              _delay_ms(1);
              buttonpresstimer2++;
           }
      break;
   }
}


           

			
			

//other timer...


           

			lcd_line1();
            lcd_time(buttonpresstimer1);
			lcd_line2();
            lcd_time(buttonpresstimer2);
			//lcd_clear();
                

//attempt at second lap
/*
			  
           while (bit_is_clear(PINC, PINC5))
           _delay_ms(50);

          lcd_clear();
		  lcd_line1();
            lcd_string("2");
          
           secondbuttonpresstimer1=0;

           while bit_is_set(PINC, PINC5)
           {
              _delay_ms(1);
              secondbuttonpresstimer1++;
           }

		   lcd_clear();
                
			  //final results
		
*/


			  lcd_clear();
                 lcd_line1();
                 lcd_time(buttonpresstimer1);
                 lcd_line2();
                 lcd_time(buttonpresstimer2);
			delay_sec(6);
		lcd_clear();
		
		main();
		
		/*while end*/}

		/* funct end*/	}





/* Displays a menu and inputs user's selection back into the main function */
int menu(void)
{
    int reply;

//this is where i'm struggling... what do i do when the user presses jumpers on PC5 to choose the option

   //option 1 start lcd_line1();
     lcd_string("option 1");
while(bit_is_set(PINC, PINC5));//do nothing

           if (bit_is_clear(PINC, PINC5))
       
           _delay_ms(50);
    reply = 1;
    _delay_ms(10);

	//option 1 end
    return (reply); /*Sends the reply to the main function*/
}

this is one of the things you suggested, (i have removed menus for moment) if you first touch PC4 then that one HAS to be touched next, but what if the other runner gets in first!? i cant get it to stop PC5 jumpers timer if i press that one… do you see what i mean, they both need to be running along side each other almost, rather than one after the other!

There are two ways I can think of that you could code something like you’re talking about, with an arbitrary number of virtual stopwatches starting and stopping independently.

The first way would be an extension of your delay approach, except all contained in one loop.

	unsigned char timing1=0,timing2=0;
	long int stopwatch1=0,stopwatch2=0;

	while(1){
		if(button1pressed()){//start/stop stopwatch 1
			timing1=!timing1;
		}

		if(button2pressed()){//start/stop stopwatch 2
			timing2=!timing2;
		}
		if(button3pressed()){//clear stopwatches 1 and 2
			stopwatch1=0;
			stopwatch2=0;
			timing1=0;
			timing2=0;
		}

		stopwatch1+=timing1;
		stopwatch2+=timing2;

		_delay_ms(1);
	}

timing1 and timing2 are start/stop type variables, so the two “stopwatch” counters are only incremented if their respective timing variables are true. The “!” or “not” operator basically toggles these variables between 0 and 1.

The problem with this approach is that you’re doing more and more stuff in addition to the delay, and the time it takes to do all this is going to start making your counts less accurate. You can try to predict the amount of time the rest of each loop will take, but as your program becomes more complex that time is going to become variable.

The neat thing though is that your microcontroller actually does have little hardware stopwatches built into it, the timer/counters, that can operate entirely independently of what code is being run. Did you check out that Timers Rock tutorial? Like any new hardware, it’s always hard to figure out at first, but once you get used to using them you’ll wonder how you ever did anything without them!

-Adam

they do seem a little intimidating, and would not reall know where to start again, i did have a look but it all seems more complex than standard C i have been used to, i agree the time it takes for the loop to work through will become apparant if it gets any bigger, is using the timers built in a standard line of code? i have used the visual basic timers, and they are nice and simple but something tells me this wont be so nice?

oh and that code you just posted, looks like it will replace the timers loop? as long as i put in the code that grounds the right jumpers where it says button1pressed etc?

Yeah, that was just a little pseudo-code with the sort of structure that would work if the functions did what their names say they should do.

I’m assuming the timers you used in visual basic were software timing functions, right? Microcontroller timers don’t actually have much to do with C or whatever language you’re writing in, they’re actually extra pieces of hardware, little stopwatches etched in the silicon of your microcontroller. You can think of them as peripheral devices on a computer, like a mouse. There’s no such thing as a mouse object type in C, but you can write code that will use the mouse.

You configure a timer by setting register bits, just like how you set specific pins to be outputs or inputs by setting or clearing bits in the DDRx registers. There are a few different operational modes and things to set up, but then they go off and do their thing, and you can check their values at any time, or even have them “interrupt” your code when a certain number is reached. Neat stuff!

Am I remembering correctly that you got the e-book version of C Programming for Microcontrollers? Chapter 7 has a very good explanation of timers, how to use them, and all the neat things you can do with them. The Speedometer sample project might be of particular interest to you (although you can totally skip the clock calibration part!).

-Adam

Hey d’you know what, dell gave me a duff computer and so replaced it, taking the harddrive with them, and i lost the ebook, and cant find the download link in my email, but I found the sourcecode for the speedometer, would you be able to briefly walk me through the timer parts?[code]// Demonstrator.c Speedometer version

#include "PC_Comm.h"
#include "Demonstrator.h"

unsigned char milliseconds = 0;
unsigned int second = 0; // count to 1000 and trigger one second event
unsigned int speed = 0; // IR detector count per second
unsigned int lastspeed = 0; // IR detector count per second

void initializer()
{
	// Calibrate the oscillator:
    OSCCAL_calibration();   
	
	// Initialize the USART
	USARTinit();
	
    // Init port pins
	DDRB |= 0x08; 
    PORTB |= ((1<<PINB4));//|(1<<PINB6)|(1<<PINB7));

    // Enable pin change interrupt on PORTB
	PCMSK1 = ((1<<PINB4));//|(1<<PINB6)|(1<<PINB7));
	EIFR = (1<<6)|(1<<7);
	EIMSK = (1<<6)|(1<<7);
	
	DDRD = 0xFF; // set PORTD for output
  	PORTD = 0XFF; // set LEDs off

	milliSecInit(127); // 50% duty cycle 1kHz signal
	
	// say hello
	sendString("\rPC_Comm.c ready to communicate.\r");   	 
	// identify yourself specifically
	sendString("You are talking to the Speedometer demo.\r");
	sendString("'setxxx' to set speed\r'Hz' to get speed in Hertz\r");

}

void parseInput(char s[])
{
	// parse first character	
	switch (s[0])
	{
		case 's':
			if( (s[1] == 'e') && (s[2] == 't'))
			parse_set(s);
			break;
		case 'H':
			if( (s[1] == 'z'))
			sendSpeed();
			break;
		case 'd':
			if( (s[1] == 'e') && (s[2] == 'm') && (s[3] == 'o') && (s[4] == '?') )
			sendString("You are talking to the Speedometer demo.\r");
			break;
		default:
			sendString("\rYou sent: '");
			sendChar(s[0]);
			sendString("' - I don't understand.\r");
			break;
		
	}
	s[0] = '\0';
}

void sendSpeed()
{
	char spd[11];
	
	sendString("Speed =  ");
	itoa(lastspeed,spd,10);	
	sendString(spd);
	sendChar('\r');	
	
}

int parse_set(char s[])
{
	char set[11];
	unsigned char i = 3, j = 0;

	while( (s[i] != '\0') && (j <= 11) ) 
	{
	
		if( (s[i] >= '0') && (s[i] <= '9') )
		{
			set[j++] = s[i++];
		}
		else
		{
			sendString("Error - Parse_set received a non integer: ");
			sendChar(s[i]);
			sendChar('\r');
			return 0;
		}
	}
	
	set[j] = '\0';
	
	if(j>4)// must be < 256
	{
		sendString("Error - Parse_set number too large\r");
		return 0;
	}
	else
	{
		set_speed(atoi(set));
	}
		
	return 1;
}

void set_speed(int count)
{
	char speed[11];

	sendString("Setting the Compare Timer Count to: ");
	itoa(count,speed,10);	
	sendString(speed);
	sendChar('\r');
	
	milliSecInit(count);
}

/*
The USART init set the system oscillator to 2 mHz. We set the Timer0 prescaler
to clk/8 which gives a 250 kHz input to the timer/counter. A compare of 250 throws
an interrupt every millisecond.
*/
void milliSecInit(unsigned char count)
{
    // Enable timer0 compare interrupt
	TIMSK0 = (1<<OCIE0A);

	// Sets the compare value
	setOCR0A(count);
	
	// Set PWM Phase Correct mode, CLK/8 prescaler
	TCCR0A = (0<<FOC0A)|(0<<WGM01)|(1<<WGM00)|(1<<CS01);

}

void setOCR0A(unsigned char count)
{    
	// Sets the compare value
	OCR0A = count;
}


// Interrupt occurs twice per Millisec, timed for PWM
SIGNAL(SIG_OUTPUT_COMPARE0)
{
	// Toggle PORtD pin 0
	if(PORTD &= 1) cbi(PORTD, 0);
	else sbi(PORTD, 0);
	
	// get the speed count once per second
	if(second++ >= 1000)
	{
		second = 0;
		lastspeed = speed; // store most recent speed in Hz		
		speed = 0;
	}
}

SIGNAL(SIG_PIN_CHANGE1)
{
	speed++;
}

Dont worry if you dont have time, i’ll keep looking for my ebook - they’re not as easy to find as real books…

finally worked out how to use the timers, making led’s and buzzers “go” but cant get te lcd’s to cooperate, i agree timers much better, very simple, why did i think they were so complex…

        // F_CPU tells util/delay.h our clock frequency
        #define F_CPU 8000000UL   // Orangutan frequency (1MHz)

        #include <avr/io.h>
        #include <util/delay.h>

        

        

        
	
		   
       
        

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s'};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


        //STANDARD MAIN FUNCTION

        int main( void )
        {

          //--------------------------------------
          //LCD STUFF TO GO IN MAIN FUNCTION
          //--------------------------------------
         

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------

       
int number = 0;

         //Timer
		   DDRC |= (1<<PC5); //Led output

   TCCR1B |= (1 << CS10); // Set up timer 

   for (;;) 
   { 
      // Check timer value in if statement, true when count matches 1/20 of a second 
      if (TCNT1 >= 50000) 
      { 

	  number++;
        // PORTC ^= (1 << 0); // Toggle the LED 

         TCNT1 = 0; // Reset timer value 
      } 
   } 
		  

          //End Timer

		

        }

i am doing something wrong though, it isnt complete code because i cant get it to even flash led’s at mo…

Great! Glad timers are starting to make sense to you.

It looks like you’re configuring Timer1 properly to operate directly off of the system clock (so it’s counting at the full 8 MHz). You indicate you have an LED+resistor connected to PC5:

DDRC |= (1<<PC5); //Led output

However, the commented out LED toggle line of code actually toggles PC1:

// PORTC ^= (1 << 0); // Toggle the LED

If you do indeed have an LED and resistor connected to PC5, your toggle line should look like this:

PORTC^=(1<<PC5);//Toggle the LED

Also, if you don’t want to use an external LED, you can toggle the Orangutan’s onboard LED by setting PD1 to an output and flipping it:

DDRD|=(1<<PD1); //Led output
PORTD^=(1<<PD1);//Toggle the LED

Either way, running the counter at 8MHz, your code is going to be toggling the LED 160 times a second, which is too fast for you to see (the LED will probably look like it’s on, but a little dim). I suggest you prescale the counter by 64 (as described in the table on page 100 of the ATMega8 datasheet):

TCCR1B|=(1<<CS11)|(1<<CS10);//Set up timer

That way your LED will toggle 2.5 times each second, which you will actually be able to see!

Did you find your copy of the e-book? It also describes how to use the AVR Studio simulator, which is great for spotting things like “I set this pin to be an output, but my code is actually toggling this one”.

-Adam

thanks adam, i know where my copy of the ebook is, its sitting at dell factory…

Adam, this oscillating at what frequency stuff - i dont think ive got it, I’m using your lcd display time function to try and get it to display the milliseconds which update as the led flashes, but its clearly not seconds…

        // F_CPU tells util/delay.h our clock frequency
      //  #define F_CPU 1000000UL   // Orangutan frequency (1MHz)

        #include <avr/io.h>
        #include <util/delay.h>

        

        

        
	
		   
       
        

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s'};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


        //STANDARD MAIN FUNCTION

        int main( void )
        {

          //--------------------------------------
          //LCD STUFF TO GO IN MAIN FUNCTION
          //--------------------------------------
         

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------

       
int number = 0;

         //Timer
		   DDRD|=(1<<PD1); //Led output

   TCCR1B|=(1<<CS11)|(1<<CS10);//Set up timer

   for (;;) 
   { 
      // Check timer value in if statement, true when count matches 1/1000 of a second 
      if (TCNT1 >= 1000) 
      { 

	  number++;
        PORTD ^= (1 << PD1); // Toggle the LED 
		
			lcd_line1();
            lcd_string("time");
			lcd_line2();
            lcd_time(number);

         TCNT1 = 0; // Reset timer value 
      } 
   } 
		  

          //End Timer

		

        }

the #define F_CPU 1000000UL // Orangutan frequency (1MHz) has been commented out, and i have stated the frequency in the fuses as 1mhz…

HI Adam, i am trying to get my push button on PC5 so that the first time it is touched, it saves te time in a variable, then the second time its touched it saves the time in another variable, then will subtract one from the other and thats how long the gap between the two touches was. that way i can have as many timings taken from different push buttons as i like… nice theory…

i think though i am stating the wrong thing and nothing is therefore happening, using an if statement to wait for an input is not the same as lighting an led ;D

        // F_CPU tells util/delay.h our clock frequency
      //  #define F_CPU 1000000UL   // Orangutan frequency (1MHz)

        #include <avr/io.h>
        #include <util/delay.h>

        

        

        
	
		   
       
        

        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------

        #define PORTB_MASK      0x38   // PB3, PB4, PB5
        #define PORTD_MASK      0x80   // PD7

        #define PORTB_SHIFT      3
        #define PORTD_SHIFT      1

        #define LCD_RW         PD3
        #define LCD_RS         PD2
        #define LCD_E         PD4

        #define   LCD_CLEAR      0x01
        #define   LCD_LINE1      0x02
        #define LCD_LINE2      0xC0
        #define LCD_SHOW_BLINK   0x0F
        #define LCD_SHOW_SOLID   0x0E     
        #define LCD_HIDE      0x0C
        #define LCD_CURSOR_L   0x10
        #define LCD_CURSOR_R   0x14
        #define LCD_SHIFT_L      0x18
        #define LCD_SHIFT_R      0x1C


        void lcd_nibble(unsigned char nibble)
        {

           
           nibble &= 0x0F;

           // Shift our nibble so bits 0, 1, and 2 line up with PB3, PB4,
           // and PB5:

           nibble <<= PORTB_SHIFT;

           // Clear those bits out of PORTB so we can write into them:

           PORTB &= ~PORTB_MASK;

           // And load PORTB with those three bits:

           PORTB |= (nibble & PORTB_MASK);

           // Now shift our nibble so bit 3 lines up with PD7:

           nibble <<= PORTD_SHIFT;

           // Clear that bit out of PORTD so we can write into it:

           PORTD &= ~PORTD_MASK;

           // And load pORTD with that last bit:

           PORTD |= (nibble & PORTD_MASK);

           // Delay for 1ms so the LCD can register it's got the nibble:

           _delay_ms(1);



           PORTD |= (1 << LCD_E);
           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Bring E low

           PORTD &= ~(1 << LCD_E);

           asm(
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              "nop" "\n\t"
              ::);

           // Our nibble has now been sent to the LCD.
        }



        void lcd_send(unsigned char data)
        {
           unsigned char    temp_ddrb, temp_portb,
                       temp_ddrd, temp_portd;

           // Store our port settings

           temp_ddrb = DDRB;
           temp_portb = PORTB;
           temp_ddrd = DDRD;
           temp_portd = PORTD;

           // Set up port I/O to match what the LCD needs

           DDRB |= PORTB_MASK;
           DDRD |= PORTD_MASK;

           // Send the data

           lcd_nibble(data >> 4);   // High nibble first
           lcd_nibble(data);      // Low nibble second

           // Restore our port settings

           DDRD = temp_ddrd;
           PORTD = temp_portd;
           DDRB = temp_ddrb;
           PORTB = temp_portb;
        }



        void lcd_cmd(unsigned char cmd)
        {
           // Hold RW and RS low

           PORTD &= !((1 << LCD_RW) | (1 << LCD_RS));

           // Send the command

           lcd_send(cmd);

           // Delay for 1ms to let the command process

           _delay_ms(1);
        }

        void lcd_data(unsigned char data)
        {
           // Hold RW low

           PORTD &= ~(1 << LCD_RW);

           // Hold RS high

           PORTD |= (1 << LCD_RS);

           // Send the data.  No waits, so we can go right into sending more
           // data.

           lcd_send(data);
        }

        // lcd_string sends a string to the LCD.

        void lcd_string(const unsigned char *str)
        {
           while (*str != 0)
              lcd_data(*str++);
        }

        // lcd_int prints an integer.

        void lcd_int(unsigned char n)
        {
           unsigned char st[4] = {0,0,0,0};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".

           // Hundreds place
           st[0] = (n / 100) + 0x30;
           n = n % 100;

           // Tens place
           st[1] = (n / 10) + 0x30;
           n = n % 10;

           // Ones place
           st[2] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        void lcd_time(unsigned long int n)
        {
           unsigned char st[8] = {0,0,0,'.',0,0,0,'s'};

           // The 0x30 addition shifts the decimal number up
           // to the ASCII location of "0".
          
           //100s
           st[0] = (n / 100000) + 0x30;
           n = n % 100000;

           //10s
           st[1] = (n / 10000) + 0x30;
           n = n % 10000;

           // 1s
           st[2] = (n / 1000) + 0x30;
           n = n % 1000;


           // 0.1s
           st[4] = (n / 100) + 0x30;
           n = n % 100;

           // 0.01s
           st[5] = (n / 10) + 0x30;
           n = n % 10;

           // 0.001s
           st[6] = n + 0x30;

           // Print it as a string
           lcd_string(st);
        }


        // lcd_init initializes the LCD and MUST be called prior to
        // every other LCD command.

        void lcd_init(void)
        {

           
           DDRD |= (1 << LCD_RW) | (1 << LCD_RS) | (1 << LCD_E);

           

           _delay_ms(30);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(5);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x30);      // 8-bit mode (wake up!)
           _delay_ms(1);
           lcd_cmd(0x32);      // 4-bit mode

           //telling the lcd everything..

           lcd_cmd(0x20);
           lcd_cmd(0x28);      // 4-bit mode, 2-line, 5x8 dots/char
           lcd_cmd(0x08);      // Display off, cursor off, blink off
           lcd_cmd(0x01);      // Clear display
           lcd_cmd(0x0F);      // Display on, cursor on, blink on
           lcd_cmd(0x02);      // Return home
           lcd_cmd(0x01);      // Clear display

           // At this point we're good to go.

        }



        void lcd_moveto(unsigned char line, unsigned char pos)
        {

         

          lcd_cmd((line == 1 ? 0x80 : 0xC0) + pos);
        }



        void lcd_moverel(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_CURSOR_R : LCD_CURSOR_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        void lcd_shift(unsigned char dir, unsigned char num)
        {
           unsigned char cmd;

           cmd = dir ? LCD_SHIFT_R : LCD_SHIFT_L;
           while(num-- > 0)
              lcd_cmd(cmd);
        }



        #define lcd_clear()   lcd_cmd(LCD_CLEAR)

        // Move the cursor to the beginning of line 1

        #define lcd_line1() lcd_cmd(LCD_LINE1)

        // Move the cursor to the beginning of line 2

        #define lcd_line2() lcd_cmd(LCD_LINE2)

        // Show the cursor as a blinking block.  (A non-blinking cursor is
        // also available.)

        #define lcd_show() lcd_cmd(LCD_SHOW_BLINK)

        // Hide the cursor.

        #define lcd_hide() lcd_cmd(LCD_HIDE)


        void delay_sec(unsigned char sec)
        {
           unsigned int cycles;


           for(cycles = 0; cycles < (sec * 100); cycles ++)
           {
              _delay_ms(10);
           }
        }



        //-----------------------------------------
        //All to do with LCD......................
        //-----------------------------------------


        //STANDARD MAIN FUNCTION

        int main( void )
        {

          //--------------------------------------
          //LCD STUFF TO GO IN MAIN FUNCTION
          //--------------------------------------
         

               // Make sure all our registers are clear
               DDRB = 0;
               DDRC = 0;
               DDRD = 0;

               PORTB = 0;
               PORTC = 0;
               PORTD = 0;

          // Initialize the LCD
          lcd_init();
          //-----------------------------
          //END MAIN FUNCTION LCD STUFF
          //------------------------------
DDRC &= ~(1 << PC5);  
int timing1;       
int number = 0;

         //Timer
		   DDRD|=(1<<PD1); //Led output

   TCCR1B|=(1<<CS11)|(1<<CS10);//Set up timer

   for (;;) 
   { 
      // Check timer value in if statement, true when count matches 1/20 of a second 
      if (TCNT1 >= 50000) 
      { 

	  number++;
        PORTD ^= (1 << PD1); // Toggle the LED 
		
			

         TCNT1 = 0; // Reset timer value 
      } 
   } 
		  
if(PORTC |= (1<< PC5)){
if (PORTC |= (1<< PC5))
 _delay_ms(50);
           while (PORTC |= (1<< PC5))
           _delay_ms(50);
		   timing1 = number;
		   }

          lcd_line1();
            lcd_string("time");
			lcd_line2();
            lcd_time(timing1);
		  //End Timer

		

        }

the varibale timing1 is supposed to hold the first time, and i wanted it to display it on the LCD but not happening.

also i dont know if you ever get it, but when i write to the mega8 and it starts sometimes absolute junk appears on the screen, and i have to turn it on and off a few times for it to run through correctly?

Glad it sounds like you got the LCD working again.

The way I was telling you to set your timer before was just to be able to see the LED blink, and I assumed you had the internal clock set to 8MHz. Take a look at table 40 on page 100 of the ATMega8 datasheet. It shows the different counter “prescaler” options. With CS11 and CS10 set, you are dividing the 1MHz clock by 64, so Timer1 increases by 1 for every 64 clock ticks. So, your LED toggles 1000000/50000/64=0.3125 times per second, or once every 3.2 seconds. You can set it back the way you had it, so it’s counting at the full 1MHz:

TCCR1B|=(1<<CS10);//Set up timer

This way the LED will toggle 20 times each second, like your program currently assumes. Also, to set up PC5 as a button that you press by connecting it to ground, you need to do three things:

  1. Make sure PC5 is an input (you’re already doing this):
    DDRC&=~(1<<PC5);
    This is what the command “cbi(DDRC, DDC5);” did in older versions of your program.

  2. Pull PC5 high internally, so that when you ground it there will be a level change to detect:
    PORTC|=(1<<PC5);
    This is what the command “sbi(PORTC, PC5);” did in older versions of your program.

  3. Since PC5 is being pulled high (by a virtual internal resistor connected between PC5 and +5V) it’s bit in the input register PINC will read high when the button is not being pressed. When you connect PC5 to ground, the PC5 bit in PINC will read low, or clear, so you would check:
    if(!(PINC&(1<<PC5)))
    This is what the command “if(bit_is_clear(PINC, PINC5))” did in older versions of your program.

Hope that gets you going again.

-Adam

P.S. ‘Junk’ appearing on the LCD screen after programming is actually normal. Some of the ATmega8 programming lines are also used as LCD control lines. When you’re running a program that has initialized the screen, and you download a new program, the screen’s controller chip may misinterpret the programming signals as commands, which can write garbage to the screen and mess up its configuration. The LCD module doesn’t have a reset pin, so physically turning the power off and back on is the way to clear it (just hitting the reset button probably won’t fix it). You should only have to cycle the power once though.

so everyone gets a bit of garbage? hmmm…

Right ok so where i got that old code from, was telling the program it wanted to use its own syntax, how confusing…

I have made the adjustments and shifted the code that watches for the button press in to the loop so now I am very close, I also adjusted the number that 1MHZ is divided by so that it “should” update every millisecond. The led has gone quite dim now though and amost looks like its not flashing regularly. Her is the little chunk of code that controls what happens after every clock refresh:

DDRC &= ~(1 << PC5);  
int timing1, timing2, finaltimer;       
int number = 0;
PORTC|=(1<<PC5); 

         //Timer
         DDRD|=(1<<PD1); //Led output

 TCCR1B|=(1<<CS10);//Set up timer

   for (;;) 
   { 
      // Check timer value in if statement, true when count matches 1/20 of a second 
      if (TCNT1 >= 1000) 
      { 

     number++;
        PORTD ^= (1 << PD1); // Toggle the LED 
  
  
      if(!(PINC&(1<<PC5)))
{
_delay_ms(50);
           
         timing1 = number;
		 }

		 while((PINC&(1<<PC5)))
		 {
		 }
{
_delay_ms(50);
           
         timing2 = number;
		 finaltimer = timing2 - timing1;
         
          lcd_line1();
            lcd_string("time");
         lcd_line2();
            lcd_time(finaltimer);
        //End Timer
         number = 0;

         TCNT1 = 0; // Reset timer value 
      } 
   } 
   }

	}

This line: if (TCNT1 >= 1000)
is meant to be how often it updates a second, well actually 1 million divided by that number = number of times a scond,

Its not far from the truth actually. Its supposed to tell me the time between two button presses, the first one being the If statement, and the second one is the while statement waiting until PORTC is low. Naturally it doesnt work, but I think i;m close - probably stupid somewhere…

Sorry for all the questions over this “real one second” stuff, i’ll get there eventually!

going to start new thread, this ones massive…