2023-01-06 04:04:06 +00:00
|
|
|
/*
|
|
|
|
* Author: Jake Goodwin
|
|
|
|
* Date: 2022
|
|
|
|
* Description: Interfacing with a 1602LCD only with the uc no perifs
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <avr/io.h>
|
|
|
|
#include <avr/interrupt.h>
|
|
|
|
#include <avr/sleep.h>
|
|
|
|
#include <util/delay.h>
|
|
|
|
|
|
|
|
|
|
|
|
#define RS_PORT PORTD
|
|
|
|
#define RS_PIN PIND0
|
|
|
|
#define RS_DDR DDD0
|
|
|
|
|
|
|
|
|
2023-01-07 00:32:08 +00:00
|
|
|
//#define RW_PORT PORTD
|
|
|
|
//#define RW_PIN PIND1
|
|
|
|
//#define RW_DDR DDD1
|
2023-01-06 04:04:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define ENA_PORT PORTD
|
2023-01-07 00:32:08 +00:00
|
|
|
#define ENA_PIN PIND1
|
|
|
|
#define ENA_DDR DDD1
|
2023-01-06 04:04:06 +00:00
|
|
|
|
|
|
|
#define BIT4_PORT PORTD
|
2023-01-07 00:32:08 +00:00
|
|
|
#define BIT4_PIN PIND4
|
|
|
|
#define BIT4_DDR DDD4
|
2023-01-06 04:04:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define BIT5_PORT PORTD
|
2023-01-07 00:32:08 +00:00
|
|
|
#define BIT5_PIN PIND5
|
|
|
|
#define BIT5_DDR DDD5
|
2023-01-06 04:04:06 +00:00
|
|
|
|
|
|
|
#define BIT6_PORT PORTD
|
2023-01-07 00:32:08 +00:00
|
|
|
#define BIT6_PIN PIND6
|
|
|
|
#define BIT6_DDR DDD6
|
2023-01-06 04:04:06 +00:00
|
|
|
|
|
|
|
#define BIT7_PORT PORTD
|
2023-01-07 00:32:08 +00:00
|
|
|
#define BIT7_PIN PIND7
|
|
|
|
#define BIT7_DDR DDD7
|
2023-01-06 04:04:06 +00:00
|
|
|
|
|
|
|
#define LED_PIN PINC0
|
|
|
|
#define LED_PORT PORTC
|
|
|
|
#define LED_DDR DDC0
|
|
|
|
|
2023-01-07 00:32:08 +00:00
|
|
|
//LCD CONNECTIONS:
|
|
|
|
/*
|
|
|
|
* VSS --> GND
|
|
|
|
* VDD --> VCC
|
|
|
|
* V0 --> POT --> GND
|
|
|
|
* RS --> PD0(AVR)
|
|
|
|
* RW --> GND
|
|
|
|
* E --> PD1(AVR)
|
|
|
|
* D4 --> PD4(AVR)
|
|
|
|
* D5 --> PD5(AVR)
|
|
|
|
* D6 --> PD6(AVR)
|
|
|
|
* D7 --> PD7(AVR)
|
|
|
|
*
|
|
|
|
* PURPOSE:
|
|
|
|
* RS: register select,
|
|
|
|
* RW: Read/Write select signal,
|
|
|
|
* E: Operation(data read/write) enable signal.
|
|
|
|
* DB0~DB3: not used for 4bit operations.
|
|
|
|
* DB4~DB7: high order three-state data lines.
|
|
|
|
*/
|
|
|
|
|
2023-01-08 01:24:18 +00:00
|
|
|
|
2023-01-07 00:32:08 +00:00
|
|
|
//#############################
|
|
|
|
//MACROS
|
|
|
|
//#############################
|
|
|
|
|
|
|
|
//already defined
|
|
|
|
//#define _BV(bit) (1 << bit)
|
|
|
|
#define setbit(port, bit) (port) |= (1 << (bit))
|
|
|
|
#define clearbit(port, bit) (port) &= ~(1 << (bit))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#############################
|
|
|
|
//FUNCTION PROTOTYPES
|
|
|
|
//#############################
|
|
|
|
|
|
|
|
|
|
|
|
void init_lcd(void);
|
2023-01-08 01:24:18 +00:00
|
|
|
void cmd_lcd(uint8_t cmd);
|
2023-01-07 00:32:08 +00:00
|
|
|
void cmd_nibble_lcd(uint8_t cmd);
|
|
|
|
void clear_lcd(void);
|
|
|
|
static void led_blink(void);
|
|
|
|
void set_lcd_one_line_(void);
|
|
|
|
void set_lcd_two_line(void);
|
|
|
|
void return_home_lcd(void);
|
|
|
|
void turn_off_lcd(void);
|
|
|
|
void turn_on_lcd(void);
|
|
|
|
void set_cgram_lcd_address(uint8_t addr);
|
|
|
|
void set_ddram_lcd_address(uint8_t addr);
|
|
|
|
void write_lcd_address(uint8_t addr);
|
2023-01-08 05:02:48 +00:00
|
|
|
void set_entry_mode_increment_lcd(void);
|
|
|
|
void set_entry_mode_decrement_lcd(void);
|
|
|
|
void shift_right_lcd(void);
|
|
|
|
void shift_left_lcd(void);
|
|
|
|
void bbs(void);
|
|
|
|
void clear_buf_lcd();
|
2023-01-07 00:32:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
int main() {
|
2023-01-08 05:02:48 +00:00
|
|
|
PORTD = 0x00;
|
|
|
|
DDRD = 0xff;
|
|
|
|
|
2023-01-07 00:32:08 +00:00
|
|
|
//SETUP HERE.
|
2023-01-08 05:02:48 +00:00
|
|
|
led_blink();
|
|
|
|
led_blink();
|
|
|
|
init_lcd();
|
|
|
|
_delay_ms(500);
|
|
|
|
|
|
|
|
return_home_lcd();
|
2023-01-08 01:24:18 +00:00
|
|
|
|
2023-01-07 00:32:08 +00:00
|
|
|
while(1) {
|
|
|
|
led_blink();
|
|
|
|
_delay_ms(1000);
|
2023-01-08 05:02:48 +00:00
|
|
|
|
|
|
|
set_entry_mode_increment_lcd();
|
|
|
|
for(uint8_t i = 0; i < 15; i++) {
|
|
|
|
//shift_right_lcd();
|
|
|
|
write_lcd_address(0x7e);
|
|
|
|
_delay_ms(100);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_entry_mode_decrement_lcd();
|
|
|
|
for(uint8_t i = 0; i < 15; i++) {
|
|
|
|
//shift_left_lcd();
|
|
|
|
write_lcd_address(0x7f);
|
|
|
|
_delay_ms(100);
|
|
|
|
}
|
|
|
|
//set_cgram_lcd_address(0x00);
|
|
|
|
//set_entry_mode_increment_lcd();
|
|
|
|
//bbs();
|
|
|
|
_delay_ms(1000);
|
|
|
|
clear_lcd();
|
|
|
|
PORTD = 0x00;
|
|
|
|
led_blink();
|
|
|
|
led_blink();
|
|
|
|
led_blink();
|
|
|
|
_delay_ms(1000);
|
|
|
|
_delay_ms(1000);
|
|
|
|
_delay_ms(1000);
|
|
|
|
_delay_ms(1000);
|
2023-01-07 00:32:08 +00:00
|
|
|
_delay_ms(1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-06 04:04:06 +00:00
|
|
|
|
|
|
|
//#############################
|
|
|
|
//FUNCTIONS
|
|
|
|
//#############################
|
|
|
|
|
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
void bbs(void) {
|
|
|
|
_delay_ms(500);
|
|
|
|
write_lcd_address(0x42);
|
|
|
|
write_lcd_address(0x4f);
|
|
|
|
write_lcd_address(0x4f);
|
|
|
|
write_lcd_address(0x42);
|
|
|
|
write_lcd_address(0x49);
|
|
|
|
write_lcd_address(0x45);
|
|
|
|
write_lcd_address(0x53);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Input: none
|
|
|
|
* Output: none
|
|
|
|
* Description: setsup the lcd for two line display and sets start posistion.
|
|
|
|
*/
|
|
|
|
void init_lcd(void) {
|
|
|
|
_delay_ms(500);
|
|
|
|
clear_buf_lcd();
|
|
|
|
clear_buf_lcd();
|
|
|
|
_delay_ms(10);
|
|
|
|
turn_on_lcd();
|
|
|
|
_delay_ms(10);
|
2023-01-07 00:32:08 +00:00
|
|
|
|
|
|
|
set_lcd_two_line();
|
2023-01-08 05:02:48 +00:00
|
|
|
_delay_ms(10);
|
|
|
|
|
|
|
|
//clear_lcd();
|
|
|
|
_delay_ms(5);
|
|
|
|
|
|
|
|
//return_home_lcd();
|
|
|
|
_delay_ms(5);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
2023-01-06 04:04:06 +00:00
|
|
|
|
|
|
|
|
2023-01-07 00:32:08 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description: Sets the LCD into 4bit two line display mode.
|
|
|
|
*/
|
|
|
|
void set_lcd_two_line(void) {
|
2023-01-08 01:24:18 +00:00
|
|
|
cmd_lcd(0x28);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
2023-01-06 04:04:06 +00:00
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description: Sets the LCD into 4bit one line display mode.
|
|
|
|
*/
|
2023-01-07 00:32:08 +00:00
|
|
|
void set_lcd_one_line(void) {
|
2023-01-08 01:24:18 +00:00
|
|
|
cmd_lcd(0x20);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description: Sends the clear screen command to the LCD
|
|
|
|
*/
|
2023-01-07 00:32:08 +00:00
|
|
|
void clear_lcd(void) {
|
2023-01-08 01:24:18 +00:00
|
|
|
cmd_lcd(0x01);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description: Returns the LCD cursor to home position.
|
|
|
|
*/
|
2023-01-07 00:32:08 +00:00
|
|
|
void return_home_lcd(void) {
|
2023-01-08 01:24:18 +00:00
|
|
|
cmd_lcd(0x02);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Output: None
|
|
|
|
* Description: Shifts cusor to the right one char.
|
|
|
|
*/
|
|
|
|
void shift_right_lcd(void) {
|
|
|
|
cmd_lcd(0x14);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Output: None
|
|
|
|
* Description: Shifts cusor to the left one char.
|
|
|
|
*/
|
|
|
|
void shift_left_lcd(void) {
|
|
|
|
cmd_lcd(0x10);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description: Toggles the LCD power state.
|
|
|
|
*/
|
|
|
|
void turn_off_lcd(void) {
|
2023-01-08 01:24:18 +00:00
|
|
|
cmd_lcd(0x08);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
2023-01-06 04:04:06 +00:00
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description: Toggles the LCD power state.
|
|
|
|
*/
|
|
|
|
void turn_on_lcd(void) {
|
|
|
|
cmd_lcd(0x0f);
|
|
|
|
}
|
2023-01-06 04:04:06 +00:00
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description:
|
|
|
|
*/
|
2023-01-07 00:32:08 +00:00
|
|
|
void set_cgram_lcd_address(uint8_t addr) {
|
2023-01-08 05:02:48 +00:00
|
|
|
uint8_t cmd = 0x40;
|
|
|
|
cmd |= addr;
|
|
|
|
cmd_lcd(cmd);
|
2023-01-06 04:04:06 +00:00
|
|
|
}
|
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description:
|
|
|
|
*/
|
2023-01-07 00:32:08 +00:00
|
|
|
void set_ddram_lcd_address(uint8_t addr) {
|
2023-01-08 05:02:48 +00:00
|
|
|
uint8_t cmd = 0x80;
|
|
|
|
cmd |= addr;
|
|
|
|
cmd_lcd(cmd);
|
2023-01-06 04:04:06 +00:00
|
|
|
}
|
|
|
|
|
2023-01-08 05:02:48 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Outupt: None
|
|
|
|
* Description:
|
|
|
|
*/
|
2023-01-07 00:32:08 +00:00
|
|
|
void write_lcd_address(uint8_t addr) {
|
2023-01-08 05:02:48 +00:00
|
|
|
setbit(PORTD, RS_PIN);
|
|
|
|
cmd_lcd(addr);
|
|
|
|
clearbit(PORTD, RS_PIN);
|
|
|
|
_delay_ms(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_entry_mode_increment_lcd(void) {
|
|
|
|
cmd_lcd(0x06);
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_entry_mode_decrement_lcd(void) {
|
|
|
|
cmd_lcd(0x04);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear_buf_lcd() {
|
|
|
|
DDRD = 0xff;
|
|
|
|
PORTD &=0x0f;
|
|
|
|
setbit(PORTD, ENA_PIN);
|
|
|
|
_delay_ms(5);
|
|
|
|
clearbit(PORTD, ENA_PIN);
|
|
|
|
|
|
|
|
_delay_ms(2);
|
|
|
|
|
|
|
|
setbit(PORTD, ENA_PIN);
|
|
|
|
_delay_ms(5);
|
|
|
|
clearbit(PORTD, ENA_PIN);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-08 01:24:18 +00:00
|
|
|
/*
|
|
|
|
* Input: uint8_t, a 8bit command code.
|
|
|
|
* Output: none
|
|
|
|
* Description: Takes a 8bit command code and sends it as two 4bit nibbles
|
|
|
|
* to the 1602LCD. The timing of delays is very important to match the
|
|
|
|
* datasheets timing diagrams.
|
|
|
|
*/
|
2023-01-07 00:32:08 +00:00
|
|
|
void cmd_lcd(uint8_t cmd) {
|
2023-01-08 01:24:18 +00:00
|
|
|
DDRD = 0xff;
|
|
|
|
PORTD &=0x0f;
|
|
|
|
|
|
|
|
//Send first nibble
|
|
|
|
setbit(PORTD, ENA_PIN);
|
|
|
|
PORTD |= (cmd & 0xf0);
|
|
|
|
_delay_ms(1);
|
|
|
|
clearbit(PORTD, ENA_PIN);
|
2023-01-08 05:02:48 +00:00
|
|
|
_delay_ms(3);
|
2023-01-08 01:24:18 +00:00
|
|
|
|
|
|
|
//Send the second nibble and shift cmd by four.
|
|
|
|
PORTD &= 0x0f;
|
|
|
|
setbit(PORTD, ENA_PIN);
|
|
|
|
PORTD |= (cmd<<4);
|
|
|
|
_delay_ms(1);
|
|
|
|
clearbit(PORTD, ENA_PIN);
|
2023-01-08 05:02:48 +00:00
|
|
|
_delay_ms(3);
|
2023-01-07 00:32:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-06 04:04:06 +00:00
|
|
|
/*
|
|
|
|
* Input: None
|
|
|
|
* Output: None
|
|
|
|
* Description: Toggles the pin for the LED indicator.
|
|
|
|
*/
|
|
|
|
static void led_blink(void) {
|
|
|
|
//Set the DDR for output.
|
|
|
|
DDRC |= (1<<LED_PIN);
|
|
|
|
|
|
|
|
PORTC ^= (1<<LED_PIN);
|
|
|
|
_delay_ms(250);
|
|
|
|
PORTC ^= (1<<LED_PIN);
|
|
|
|
_delay_ms(250);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|