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!