Cheat sheet

Hi, I have been learning about microcontrollers for a while now, and have used quite a few of their functions. I want to create a cheet sheet so looking up how to use something when i forget it is easy, it is below. Please can anyone comment so i can update it, and check to see whether i have made any mistakes, or anything should be changed. Once it is pretty accurate i;m sure it will help others as well!

Cheat sheet based on the pololu orangutan mega8…

A few regular possible headers:

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

Possible constant array:

const unsigned char single_zero_wheel[37]={0,32,15,19,4,21,2,25,17,34,6,
                                 27,13,36,11,30,8,23,10,5,24,
                                 16,33,1,20,14,31,9,22,18,29,
                                 7,28,12,35,3,26};

Initialising onboard ADC:

//-----------------------------------------
//All to do with ADC......................
//-----------------------------------------
void analog_init(void)
{

ADMUX = (1 << REFS0);

ADCSRA = (6 << ADPS0);


ADCSRA |= (1 << ADEN);
}

unsigned int analog10(unsigned char channel)
{

ADMUX &= ~0x1F;

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);
}
	//-----------------------------------------
        //Finish - All to do with ADC......................
        //-----------------------------------------

Initialising LCD display:

//-----------------------------------------
        //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[9] = {0,0,0,'.',0,0,0,'s',0};

           // 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);
           }
        }



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

Waiting for a button press:

while (PINC&(1<<PC5));
{

//do this
}[/code]
[b]Waiting for button release:[/b]

[code]while (!(PINC&(1<<PC5)));

{

//do this
}

Display on LCD:

lcd_line1();// display the times
    lcd_time(time_ms1);

Delay (if delay header included):

_delay_ms(1000);

Initialize the ADC in main code:
analog_init();

Initilize LCD in main function:

//--------------------------------------
   //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
   //------------------------------

Opening ports as inputs:

DDRC &= ~(1 << PC5);
   PORTC|=(1<<PC5); 
   
   DDRC &= ~(1 << PC4);
   PORTC|=(1<<PC4);

   DDRC &= ~(1 << PC0);
   PORTC|=(1<<PC0);

Onboard timer initialisation (mega8)

//initialize timer 0
   TCNT0=~(124);//preload counter to overflow after 1 ms (125 counts)
   TIMSK=(1<<TOIE0);//enable interrupt on timer0 overflow
   TCCR0=(1<<CS01)|(1<<CS00);//set timer to normal mode with CPU clock/64 (125 kHz)
   

Initialising interupts:

sei();//enable all interrupts

Waiting for user input:

while(1){
      if (!(PINC&(1<<PC4))){
         _delay_ms(10);//delay for 10 ms to debounce the press
         
         break;
      }else if(!(PINC&(1<<PC5))){
         _delay_ms(10);//delay for 10 ms to debounce the press
        	
         break;
      }else if(!(PINC&(1<<PC0))){
         _delay_ms(10);//delay for 10 ms to debounce the press
         
         break;
      }
   }

Interupt function:

/*
TIMER 0 overflow interrupt service routine
This routine is called every millisecond
Operation: increment global variable timer_tick, reload TCNT0 to count 125 clock cycles
*/

ISR(TIMER0_OVF_vect)
{
   timer_tick++;
   timer_tick_wheel++;
   TCNT0 = ~(125);         //preload counter to overflow after 1 ms (125 counts)
}

If button press:

if (!(PINC&(1<<PC5)));
{

//do this
}

Thanks for anyone who comments, i shall keep updating this thread as comments come in!

I am looking for some code that will read the pulses of a hobby R/C receiver and convert them to a number.

I think the code would go like so:

ISR(pin change){
if pin == high
   start timer
elseif pin == low
   stop timer, read value of timer, save to a variable
end
}
main(){
while(1)
}

I’ve been working on some code but I’m completely new to AVRs and C programming in general so it would be nice to have a baseline that worked.

Hello.

Please take a look at this thread:

And the one I link to from my post in that thread. The code there might help you accomplish what you’re trying to do, though it might need to be modified depending on which AVR your’re using. Please post if you have any questions or troubles getting it to work.

Also, external interrupts are somewhat easier to use than pin-change interrupts, so if you can choose an AVR pin that can be used as an external interrupt, it might make your task easier.

- Ben