AVR Microcontroller Programming: LCD, Keypad, 7-Segment & Assembly Examples
Posted by Anonymous and classified in Electronics
Written on in
English with a size of 11.15 KB
AVR Microcontroller Programming Examples
This collection of embedded C and AVR assembly examples covers common hardware interfacing and programming techniques for AVR microcontrollers, including LCD display control, matrix keypad scanning, 7-segment displays, bit manipulation, delays, and I/O port handling.
LCD Display
The following program initializes a 16x2 LCD in 8-bit mode and prints text on both lines.
#define F_CPU 1000000UL //1 MHz clock
#include <avr/io.h>
#include <util/delay.h>
void lcdCommand(unsigned char cmnd)
{
PORTA = cmnd;
PORTB &= ~(1<<0); //RS = 0 for command
PORTB &= ~(1<<1); //RW = 0 for write
PORTB |= (1<<2); //EN = 1 for H to L pulse
_delay_us(1);
PORTB &= ~(1<<2); //EN = 0 for H to L pulse
_delay_us(100);
}
void lcdData(unsigned char data)
{
PORTA = data;
PORTB |= (1<<0); //RS = 1 for data
PORTB &= ~(1<<1); //RW = 0 for write
PORTB |= (1<<2); //EN = 1 for H to L pulse
_delay_us(1);
PORTB &= ~(1<<2); //EN = 0 for H to L pulse
_delay_us(100);
}
void lcd_print(char *str)
{
unsigned char i = 0;
while(str[i] != 0)
{
lcdData(str[i]);
i++;
}
}
int main(void)
{
DDRA = 0xFF; //LCD data pins connected to Port A
DDRB = 0xFF; //LCD control pins connected to Port B
PORTB &= ~(1<<2); //EN = 0
_delay_us(2000);
lcdCommand(0x38); //2 line 5x7 matrix
lcdCommand(0x0E); //display on, cursor on
lcdCommand(0x01); //clear LCD
_delay_us(2000);
lcdCommand(0x06); //shift cursor right
lcdCommand(0x80);
lcd_print("Electronics Dept");
lcdCommand(0xC0);
lcd_print("GPTC Kottayam");
while(1);
return 0;
}Matrix Keyboard
This program scans a 4x3 matrix keypad connected to Port C and outputs the pressed key value on Port D.
#define F_CPU 1000000UL //1 MHz clock
#include <avr/io.h>
#include <util/delay.h>
unsigned char keypad[4][3] = {'1','2','3',
'4','5','6',
'7','8','9',
'*','0','#'};
int main(void)
{
unsigned char colloc, rowloc;
DDRD = 0xFF;
DDRC = 0xF8;
PORTC = 0xFF;
while(1) //repeat forever
{
while(1)
{
PORTC = 0xEF; //ground row A
colloc = (PINC & 0x07); //read the columns
if (colloc != 0x07)
{
rowloc = 0;
break;
}
PORTC = 0xDF; //ground row B
colloc = (PINC & 0x07);
if (colloc != 0x07)
{
rowloc = 1;
break;
}
PORTC = 0xBF; //ground row C
colloc = (PINC & 0x07);
if (colloc != 0x07)
{
rowloc = 2;
break;
}
PORTC = 0x7F; //ground row D
colloc = (PINC & 0x07);
if (colloc != 0x07)
{
rowloc = 3;
break;
}
}
if(colloc == 0x06)
{
PORTD = keypad[rowloc][0];
}
else if(colloc == 0x05)
{
PORTD = keypad[rowloc][1];
}
else
{
PORTD = keypad[rowloc][2];
}
}
return 0;
}7-Segment Display
This program counts from 0 to 9 on a common-cathode 7-segment display connected to Port C.
#define F_CPU 1000000UL //1 MHz clock
#include <avr/io.h>
#include <util/delay.h>
char seg_7[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
int main(void)
{
DDRC = 0xFF; //Port C is output
PORTC = 0x00;
int i = 0;
while(1)
{
PORTC = seg_7[i];
_delay_ms(1000);
i += 1;
if(i >= 10)
{
i = 0;
}
}
return 0;
}Usage of For Loop
This example uses a for loop to send values from 0 to 20 to Port B with a 100 ms delay between each value.
#define F_CPU 100000UL
#include <avr/io.h> // standard AVR header
#include <util/delay.h> // delay loop function
int main(void)
{
unsigned char z;
DDRB = 0xFF; // setting PORTB as output
while (1)
{
for (z = 0; z <= 20; z++)
{
PORTB = z; // value sent to PORTB
_delay_ms(100); // delay 100 ms
}
}
return 0;
}Bit Manipulation
This program controls a relay and a buzzer using bit manipulation on Port C.
#include <avr/io.h> // standard AVR header
#include <util/delay.h> // delay loop function
#define buzzer PC5
#define relay PC4
#define PORT PORTC
void InitPort(void)
{
DDRB = 0xFF; // PORTB pins defined as output
DDRC = 0xFF; // PORTC pins defined as output
PORT |= (1 << relay); // relay ON
}
int main(void)
{
InitPort(); // calling port initialization function
while (1) // indefinite loop
{
_delay_ms(1000); // 1 sec delay
PORTB = 0xFF; // PORTB on
PORT |= (1 << buzzer); // buzzer ON
_delay_ms(1000); // 1 sec delay
PORTB = 0x00; // PORTB off
PORT &= ~(1 << buzzer); // buzzer OFF
}
}Software Delay
This program toggles PORTB and PORTC every second using a software delay.
#define F_CPU 1000000UL
#include <avr/io.h> // standard AVR header
#include <util/delay.h> // delay loop function
int main(void)
{
DDRB = 0xFF; // setting PORTB as output
DDRC = 0xFF; // setting PORTC as output
PORTB = 0xFF; // setting value for PORTB
PORTC = 0xFF; // setting value for PORTC
while (1) // indefinite loop
{
_delay_ms(1000); // delay of 1 sec
PORTB = ~PORTB; // toggle PORTB
PORTC = ~PORTC; // toggle PORTC
}
return 0;
}Port Pin as Input and Output
This program reads the state of PORTD and writes it to PORTB.
#include <avr/io.h> // standard AVR header
void InitPort(void)
{
DDRB = 0xFF; // PORTB pins defined as output
DDRD = 0x00; // PORTD pins defined as input
}
int main(void)
{
InitPort(); // calling port initialization function
while (1) // indefinite loop
{
PORTB = PIND; // reading PORTD and writing the value to PORTB
}
}I/O Port Programming 1: Delay (Assembly)
This ATmega32 assembly program initializes the stack, outputs alternating patterns on PORTB, reads PORTB as input, and displays the value on PORTA.
.INCLUDE "M32DEF.INC"
.ORG 0
LDI R16, HIGH(RAMEND) ; Initialize the Stack Pointer
OUT SPH, R16
LDI R16, LOW(RAMEND) ; Initialize the Stack Pointer
OUT SPL, R16
LDI R16, 0XFF ; R16 = FF
OUT DDRA, R16 ; Make PORTA as output
LDI R17, 0XFF ; R17 = FF
OUT DDRB, R17 ; Make PORTB as output
LDI R16, 0X55 ; Load R16 with 0x55
BACK:
OUT PORTB, R16 ; Load PORTB = R16
CALL DELAY ; Time delay
COM R16 ; Complement R16
OUT PORTB, R16 ; Load PORTB = R16
LDI R20, 0X00
OUT DDRB, R20 ; Make PORTB as input
IN R16, PINB ; Move from pins of PORTB to R16
OUT PORTA, R16 ; PORTA = PORTB
RJMP BACK
DELAY:
LDI R17, 0XF ; Load R17 = 0F
LOOP:
NOP ; No operation
DEC R17
BRNE LOOP ; Repeat until R17 becomes 0
RETLED Blink (Assembly)
This program lights LEDs on PORTB one at a time with a delay between each.
.INCLUDE "M32DEF.INC"
LDI R16, HIGH(RAMEND) ; Initialize the Stack Pointer
OUT SPH, R16
LDI R16, LOW(RAMEND) ; Initialize the Stack Pointer
OUT SPL, R16
LDI R20, 0XFF
OUT DDRB, R20 ; Configure PORTB as output
SBI PORTB, 0 ; Set bit PB0
CALL DELAY ; Delay before next one
SBI PORTB, 1 ; Turn ON PB1
CALL DELAY
SBI PORTB, 2 ; Turn ON PB2
CALL DELAY
SBI PORTB, 3 ; Turn ON PB3
CALL DELAY
SBI PORTB, 4 ; Turn ON PB4
CALL DELAY
SBI PORTB, 5 ; Turn ON PB5
CALL DELAY
SBI PORTB, 6 ; Turn ON PB6
CALL DELAY
SBI PORTB, 7 ; Turn ON PB7
CALL DELAY
HERE: RJMP HERE
DELAY:
LDI R17, 0X5 ; Load R17 = 05
LOOP:
NOP ; No operation
DEC R17
BRNE LOOP ; Repeat until R17 becomes 0
RETShift and Rotate (Assembly)
This program demonstrates ROR, ROL, LSL, LSR, ASR, and SWAP instructions on a value stored in SRAM.
.INCLUDE "M32DEF.INC" ; Include the appropriate register definition
.ORG 00 ; Start at address 00
LDI R16, HIGH(RAMEND) ; Load SPH
OUT SPH, R16
LDI R16, LOW(RAMEND) ; Load SPL
OUT SPL, R16
LDI R20, 0XD5 ; Load R20 with 0xD5
STS 0x400, R20 ; Store R20 in memory location 0x400
LDS R22, 0X400 ; Load from memory location 0x400 to R22
ROR R22 ; Rotate R22 right through carry
STS 0x301, R22 ; Save the result in location 0x301
LDS R22, 0X400
ROL R22 ; Rotate R22 left through carry
STS 0x302, R22 ; Save the result in location 0x302
LDS R22, 0X400
LSL R22 ; Logical shift left
STS 0x303, R22 ; Save the result in location 0x303
LDS R22, 0X400
LSR R22 ; Logical shift right
STS 0x304, R22 ; Save the result in location 0x304
LDS R22, 0X400
ASR R22 ; Arithmetic shift right
STS 0x305, R22 ; Save the result in location 0x305
LDS R22, 0X400
SWAP R22 ; Swap nibbles
STS 0x306, R22 ; Save the result in location 0x306
OUT PORTA, R22
IN R23, PORTA
STAY: RJMP STAY ; Stay here foreverArithmetic Operations (Assembly)
This program performs addition, subtraction, and multiplication on two values and stores the results in SRAM.
.INCLUDE "M32DEF.INC" ; Include the appropriate register definition
.EQU SUM=0X300 ; SRAM location 0x300 for SUM
.EQU SUBB=0X301 ; SRAM location 0x301 for SUB
.EQU MULL=0X302 ; SRAM location 0x302 for MULL
.EQU MULH=0X303 ; SRAM location 0x303 for MULH
.ORG 00 ; Start at address 00
LDI R16, HIGH(RAMEND) ; Load SPH
OUT SPH, R16
LDI R16, LOW(RAMEND) ; Load SPL
OUT SPL, R16
LDI R20, 0X55 ; Load R20 with 0x55
LDI R21, 0XAA ; Load R21 with 0xAA
STS 0x400, R20 ; Store R20 in memory location 0x400
STS 0x401, R21 ; Store R21 in memory location 0x401
ADD R20, R21 ; Add R21 to R20
STS SUM, R20 ; Save the SUM in location 0x300
LDS R16, 0X400 ; Load from memory location 0x400 to R16
LDS R17, 0X401 ; Load from memory location 0x401 to R17
SUB R16, R17 ; Subtract R17 from R16
STS SUBB, R16 ; Save the SUB in location 0x301
MUL R16, R17 ; Multiply R16 and R17
STS MULL, R0 ; Save the low byte of MUL in location 0x302
STS MULH, R16 ; Save the high byte in location 0x303
HERE: JMP HERE ; Stay here forever