
cpu구조
RISC-5
CISC
RISC
AMBA
AXI4
APB
AHB
ASB
명령어 요약


오른쪽 솔루션 창에서 솔루션 우클릭 add->new project, 생성된 프로젝트에서 우클릭 add->new item(헤더파일 또는 코드파일 생성)
DDRx: GPIO 핀의 데이터 방향을 설정 (입력 또는 출력).
PORTx: 출력 핀의 상태를 설정하거나 입력 핀의 풀업 저항을 활성화.
PINx: 입력 핀의 현재 상태를 읽음
VO에 저항을 연결하여 문자의 밝기 조절, 가변 저항을 달아 조절가능

#include "lcd.h"
void LCD_DATA(uint8_t data)
{
LCD_DATA_PORT = data; //데이터 핀에 8비트 출력
}
//void LCD_DATA4bit(uint8_t data);
void LCD_WritePin()
{ // LOW로 만들기 위함
LCD_RW_PORT &= ~(1<<LCD_RW); //RW핀을 LOW -> 쓰기모드 진입, LCD_RW는 6으로 정의
}
void LCD_ReadPin()
{
LCD_RW_PORT |= (1<<LCD_RW); //RW핀을 High -> 읽기 모드
}
void LCD_EnablePin()
{
LCD_E_PORT &= ~(1<<LCD_E); //E핀을 Low로 설정
LCD_E_PORT |= (1<<LCD_E); //E핀을 High로 설정 -> 동작 신호를 전송
LCD_E_PORT &= ~(1<<LCD_E); //E핀을 Low로 설정
_delay_us(1600);
}
void LCD_WriteCommand(uint8_t commandData)
{
LCD_RS_PORT &= ~(1<<LCD_RS); //RS핀을 Low설정 -> 명령어모드 진입
LCD_WritePin(); //데이터 쓰기 모드
LCD_DATA(commandData); //명령어를 데이터핀에 출력
LCD_EnablePin(); //LCD 동작신호 전송
}
void LCD_WriteData(uint8_t charData)
{
LCD_RS_PORT |= (1<<LCD_RS); //RS핀을 High설정 -> 문자모드 진입
LCD_WritePin(); //데이터 쓰기 모드
LCD_DATA(charData); //명령어를 데이터핀에 출력
LCD_EnablePin(); //LCD 동작신호 전송
}
void LCD_GotoXY(uint8_t row, uint8_t col)
{
col %= 16;
row %= 2;
uint8_t address = (0x40 * row) + col; //주소계산
uint8_t command = 0x80 + address; //커맨드 값계산(주소설정)
LCD_WriteCommand(command); //주소커맨드 전송
}
void LCD_WriteString(char *string)
{
for (uint8_t i = 0; string[i]; i++)
{
LCD_WriteData(string[i]); //문자 출력
}
}
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string)
{
LCD_GotoXY(row, col);
LCD_WriteString(string);
}
void LCDInit()
{
LCD_DATA_DDR = 0xff;
LCD_RS_DDR |= (1<<LCD_RS);
LCD_RW_DDR |= (1<<LCD_RW);
LCD_E_DDR |= (1<<LCD_E);
_delay_ms(20);
LCD_WriteCommand(COMMAND_8_BIT_MODE);
_delay_ms(5);
LCD_WriteCommand(COMMAND_8_BIT_MODE);
_delay_ms(1);
LCD_WriteCommand(COMMAND_8_BIT_MODE);
LCD_WriteCommand(COMMAND_8_BIT_MODE);
LCD_WriteCommand(COMMAND_DISPLAY_OFF);
LCD_WriteCommand(COMMAND_DISPLAY_CLEAR);
//LCD_WriteCommand(COMMAND_DISPLAY_ON);
LCD_WriteCommand(COMMAND_ENTRY_MODE);
LCD_WriteCommand(COMMAND_DISPLAY_ON);
}
#ifndef LCD_H_
#define LCD_H_
#define F_CPU 16000000UL
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#define LCD_DATA_DDR DDRF
#define LCD_DATA_PORT PORTF
#define LCD_DATA_PIN PINF
#define LCD_RS_DDR DDRE
#define LCD_RW_DDR DDRE
#define LCD_E_DDR DDRE
#define LCD_RS_PORT PORTE
#define LCD_RW_PORT PORTE
#define LCD_E_PORT PORTE
#define LCD_RS 5
#define LCD_RW 6
#define LCD_E 7
#define COMMAND_DISPLAY_CLEAR 0x01 //화면 clear
#define COMMAND_DISPLAY_ON 0x0c //디스플레이on, 커서off
#define COMMAND_DISPLAY_OFF 0x08 //디스플레이off, 커서off
#define COMMAND_ENTRY_MODE 0x06 //커서 우측 이동, 화면이동 없음
#define COMMAND_8_BIT_MODE 0x38 //8비트, 화면2행, 5x8 font
#define COMMAND_4_BIT_MODE 0x28 //4비트, 화면2행, 5x8 font
void LCD_DATA(uint8_t data);
//void LCD_DATA4bit(uint8_t data); //4bit 모드
void LCD_WritePin();
void LCD_ReadPin();
void LCD_EnablePin();
void LCD_WriteCommand(uint8_t commandData);
void LCD_WriteData(uint8_t charData);
void LCD_GotoXY(uint8_t row, uint8_t col);
void LCD_WriteString(char *string);
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string);
void LCDInit();
#endif /* LCD_H_ */
//#define F_CPU 16000000UL
//#include <avr/io.h>
//#include <util/delay.h>
//#include <stdio.h>
#include "lcd.h"
int main(void)
{
LCDInit();
LCD_GotoXY(0,0);
LCD_WriteString("Hello AVR");
LCD_GotoXY(1,0);
LCD_WriteString("Good ATmega128A");
while (1)
{
}
}
#include "lcd.h"
//void LCD_DATA(uint8_t data)
//{
//LCD_DATA_PORT = data; //데이터 핀에 8비트 출력
//}
void LCD_DATA4bit(uint8_t data)
{
LCD_DATA_PORT = (LCD_DATA_PORT & 0x0f) | (data & 0xf0); //LCD_DATA_PORT변수 초기화 후, 상위 4비트 출력
LCD_EnablePin(); //LCD 동작 신호 전송
LCD_DATA_PORT = (LCD_DATA_PORT & 0x0f) | (data & 0x0f) << 4; //LCD_DATA_PORT변수 초기화 후, 하위 4비트 출력
LCD_EnablePin(); //LCD 동작 신호 전송
}
void LCD_WritePin()
{ // LOW로 만들기 위함
LCD_RW_PORT &= ~(1<<LCD_RW); //RW핀을 LOW -> 쓰기모드 진입, LCD_RW는 6으로 정의
}
void LCD_ReadPin()
{
LCD_RW_PORT |= (1<<LCD_RW); //RW핀을 High -> 읽기 모드
}
void LCD_EnablePin()
{
LCD_E_PORT &= ~(1<<LCD_E); //E핀을 Low로 설정
LCD_E_PORT |= (1<<LCD_E); //E핀을 High로 설정 -> 동작 신호를 전송
LCD_E_PORT &= ~(1<<LCD_E); //E핀을 Low로 설정
_delay_us(2000);
}
void LCD_WriteCommand(uint8_t commandData)
{
LCD_RS_PORT &= ~(1<<LCD_RS); //RS핀을 Low설정 -> 명령어모드 진입
LCD_WritePin(); //데이터 쓰기 모드
LCD_DATA4bit(commandData); //명령어를 데이터핀에 출력
//LCD_EnablePin(); //LCD 동작신호 전송
}
void LCD_WriteData(uint8_t charData)
{
LCD_RS_PORT |= (1<<LCD_RS); //RS핀을 High설정 -> 문자모드 진입
LCD_WritePin(); //데이터 쓰기 모드
LCD_DATA4bit(charData); //명령어를 데이터핀에 출력
//LCD_EnablePin(); //LCD 동작신호 전송
}
void LCD_GotoXY(uint8_t row, uint8_t col)
{
col %= 16;
row %= 2;
uint8_t address = (0x40 * row) + col; //주소계산
uint8_t command = 0x80 + address; //커맨드 값계산(주소설정)
LCD_WriteCommand(command); //주소커맨드 전송
}
void LCD_WriteString(char *string)
{
for (uint8_t i = 0; string[i]; i++)
{
LCD_WriteData(string[i]); //문자 출력
}
}
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string)
{
LCD_GotoXY(row, col);
LCD_WriteString(string);
}
void LCDInit()
{
LCD_DATA_DDR = 0xff;
LCD_RS_DDR |= (1<<LCD_RS);
LCD_RW_DDR |= (1<<LCD_RW);
LCD_E_DDR |= (1<<LCD_E);
_delay_ms(20);
LCD_WriteCommand(0x03);
_delay_ms(5);
LCD_WriteCommand(0x03);
_delay_ms(1);
LCD_WriteCommand(0x03);
LCD_WriteCommand(0x02);
LCD_WriteCommand(COMMAND_4_BIT_MODE); //8비트 보다 한 라인 추가
LCD_WriteCommand(COMMAND_DISPLAY_OFF);
LCD_WriteCommand(COMMAND_DISPLAY_CLEAR);
LCD_WriteCommand(COMMAND_DISPLAY_ON);
LCD_WriteCommand(COMMAND_ENTRY_MODE);
//LCD_WriteCommand(COMMAND_DISPLAY_ON);
}
#ifndef LCD_H_
#define LCD_H_
#define F_CPU 16000000UL
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#define LCD_DATA_DDR DDRF
#define LCD_DATA_PORT PORTF
#define LCD_DATA_PIN PINF
#define LCD_RS_DDR DDRE
#define LCD_RW_DDR DDRE
#define LCD_E_DDR DDRE
#define LCD_RS_PORT PORTE
#define LCD_RW_PORT PORTE
#define LCD_E_PORT PORTE
#define LCD_RS 5
#define LCD_RW 6
#define LCD_E 7
#define COMMAND_DISPLAY_CLEAR 0x01 //화면 clear
#define COMMAND_DISPLAY_ON 0x0c //디스플레이on, 커서off
#define COMMAND_DISPLAY_OFF 0x08 //디스플레이off, 커서off
#define COMMAND_ENTRY_MODE 0x06 //커서 우측 이동, 화면이동 없음
#define COMMAND_8_BIT_MODE 0x38 //8비트, 화면2행, 5x8 font
#define COMMAND_4_BIT_MODE 0x28 //4비트, 화면2행, 5x8 font
void LCD_DATA(uint8_t data);
void LCD_DATA4bit(uint8_t data); //4bit 모드
void LCD_WritePin();
void LCD_ReadPin();
void LCD_EnablePin();
void LCD_WriteCommand(uint8_t commandData);
void LCD_WriteData(uint8_t charData);
void LCD_GotoXY(uint8_t row, uint8_t col);
void LCD_WriteString(char *string);
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string);
void LCDInit();
#endif /* LCD_H_ */
#include "lcd.h"
int main(void)
{
LCDInit();
LCD_GotoXY(0,0);
LCD_WriteString("Hello 4BIT");
LCD_GotoXY(1,0);
LCD_WriteString("4BIT GOOD");
while (1)
{
}
}

#ifndef DEF_H_
#define DEF_H_
#define F_CPU 16000000UL
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <stdbool.h>
#include <stdint.h>
#endif /* DEF_H_ */
TWBR 계산 공식



#include "I2C.h"
void I2C_Init() {
I2C_DDR |= (1<<I2C_SDA | 1<<I2C_SCL);
// ATmega 128A의 DataSheet 참고
TWBR = 72; // 100KHz
// TWBR = 72; // 200KHz
// TWBR = 72; // 400KHz
}
void I2C_start() {
TWCR = (1<<TWINT | 1<<TWSTA | 1<<TWEN);
while(!(TWCR & (1<<TWINT))); // TWint 시점 결정
}
void I2C_Stop() {
TWCR = (1<<TWINT | 1<<TWEN | 1<<TWSTO);
}
void I2C_TxData(uint8_t data) { // 1Byte 전송
TWDR = data;
TWCR = (1<<TWINT | 1<<TWEN);
while(!(TWCR & (1<<TWINT))); // 전송 완료 대기
}
void I2C_TxByte(uint8_t devAddress, uint8_t data) {
I2C_start();
I2C_TxData(devAddress);
I2C_TxData(data);
I2C_Stop();
}
/*
#include "I2C.h"
void I2C_Init() {
I2C_DDR |= (1<<I2C_SDA | 1<<I2C_SCL);
// ATmega 128A의 DataSheet 참고
TWBR = 72; // 100KHz
// TWBR = 72; // 200KHz
// TWBR = 72; // 400KHz
}
void I2C_start() {
TWCR = (1<<TWINT | 1<<TWSTA | 1<<TWEN);
while(!(TWCR & (1<<TWINT))); // TWint 시점 결정
}
void I2C_Stop() {
TWCR = (1<<TWINT | 1<<TWEN | 1<<TWSTO);
}
void I2C_TxData(uint8_t data) { // 1Byte 전송
TWDR = data;
TWCR = (1<<TWINT | 1<<TWEN);
while(!(TWCR & (1<<TWINT))); // 전송 완료 대기
}
void I2C_TxByte(uint8_t devAddress, uint8_t data) {
I2C_start();
I2C_TxData(devAddress);
I2C_TxData(data);
I2C_Stop();
}
*/
#ifndef I2C_H_
#define I2C_H_
#include "def.h"
#define I2C_DDR DDRD
#define I2C_SCL PORTD0
#define I2C_SDA PORTD1
void I2C_Init();
void I2C_Start();
void I2C_Stop();
void I2C_TxData(uint8_t data);
void I2C_TxByte(uint8_t devAddress, uint8_t data);
#endif /* I2C_H_ */
#include "I2C_LCD.h"
uint8_t I2C_LCD_Data;
void LCD_DATA4bit(uint8_t data)
{
I2C_LCD_Data = (I2C_LCD_Data & 0x0f) | (data & 0xf0); //LCD_DATA_PORT변수 초기화 후, 상위 4비트 출력
LCD_EnablePin(); //LCD 동작 신호 전송
I2C_LCD_Data = (I2C_LCD_Data & 0x0f) | (data & 0x0f) << 4; //LCD_DATA_PORT변수 초기화 후, 하위 4비트 출력
LCD_EnablePin(); //LCD 동작 신호 전송
}
void LCD_EnablePin()
{
I2C_LCD_Data &= ~(1<<LCD_E); //E LOW
I2C_TxByte(LCD_DEV_ADDR, I2C_LCD_Data);
I2C_LCD_Data |= (1<<LCD_E); //E HIGH
I2C_TxByte(LCD_DEV_ADDR, I2C_LCD_Data);
I2C_LCD_Data &= ~(1<<LCD_E); //E LOW
I2C_TxByte(LCD_DEV_ADDR, I2C_LCD_Data);
_delay_us(1600);
}
void LCD_WriteCommand(uint8_t commadData)
{
I2C_LCD_Data &= ~(1<<LCD_RS);
I2C_LCD_Data &= ~(1<<LCD_RW);
LCD_DATA4bit(commadData);
}
void LCD_WriteData(uint8_t charData)
{
I2C_LCD_Data |= (1<<LCD_RS);
I2C_LCD_Data &= ~(1<<LCD_RW);
LCD_DATA4bit(charData);
}
void LCD_BacklightOn()
{
I2C_LCD_Data |= (1<<LCD_BACKLIGHT);
I2C_TxByte(LCD_DEV_ADDR, I2C_LCD_Data);
}
void LCD_GotoXY(uint8_t row, uint8_t col)
{
col %= 16;
row %= 2;
uint8_t address = (0x40 * row) + col; //주소계산
uint8_t command = 0x80 + address; //커맨드 값계산(주소설정)
LCD_WriteCommand(command); //주소커맨드 전송
}
void LCD_WriteString(char *string)
{
for (uint8_t i = 0; string[i]; i++)
{
LCD_WriteData(string[i]); //문자 출력
}
}
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string)
{
LCD_GotoXY(row, col);
LCD_WriteString(string);
}
void LCD_Init()
{
I2C_Init();
//LCD_DATA_DDR = 0xff;
//LCD_RS_DDR |= (1<<LCD_RS);
//LCD_RW_DDR |= (1<<LCD_RW);
//LCD_E_DDR |= (1<<LCD_E);
_delay_ms(20);
LCD_WriteCommand(0x03);
_delay_ms(5);
LCD_WriteCommand(0x03);
_delay_ms(1);
LCD_WriteCommand(0x03);
LCD_WriteCommand(0x02);
LCD_WriteCommand(COMMAND_4_BIT_MODE); //8비트 보다 한 라인 추가
LCD_WriteCommand(COMMAND_DISPLAY_OFF);
LCD_WriteCommand(COMMAND_DISPLAY_CLEAR);
LCD_WriteCommand(COMMAND_DISPLAY_ON);
LCD_WriteCommand(COMMAND_ENTRY_MODE);
//LCD_WriteCommand(COMMAND_DISPLAY_ON);
LCD_BacklightOn();
}
#ifndef I2C_LCD_H_
#define I2C_LCD_H_
#include "def.h"
#include "I2C.h"
#define LCD_RS 0
#define LCD_RW 1
#define LCD_E 2
#define LCD_BACKLIGHT 3
#define LCD_DEV_ADDR (0x27<<1)
#define COMMAND_DISPLAY_CLEAR 0x01 //화면 clear
#define COMMAND_DISPLAY_ON 0x0c //디스플레이on, 커서off
#define COMMAND_DISPLAY_OFF 0x08 //디스플레이off, 커서off
#define COMMAND_ENTRY_MODE 0x06 //커서 우측 이동, 화면이동 없음
#define COMMAND_4_BIT_MODE 0x28 //4비트, 화면2행, 5x8 font
void LCD_DATA4bit(uint8_t data);
void LCD_EnablePin();
void LCD_WriteCommand(uint8_t commadData);
void LCD_WriteData(uint8_t charData);
void LCD_BacklightOn();
void LCD_GotoXY(uint8_t row, uint8_t col);
void LCD_WriteString(char *string);
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string);
void LCD_Init();
#endif /* I2C_LCD_H_ */
#include "I2C_LCD.h"
int main(void)
{
uint16_t count = 0;
uint8_t buff[30];
LCD_Init();
LCD_WriteStringXY(0,0,"Hello ATmega128a");
while (1)
{
sprintf(buff, "count : %-5d", count++);
LCD_WriteStringXY(1,0,buff);
_delay_ms(200);
}
}

8bit 방식의 초기화 순서이다. 이 때 약간의 시간을 두고 초기화 신호를 0x3?의 신호를 3번 보내게 된다.
그 후

이 부분은 어떤식으로 설정해도 된다는 것을 확인했다. 결국 처음 3번 같은 신호를 보내는 것이 끝나면 LCD를 동작시키기 위한 초기화는 끝이고 그 다음은 디스플레이나 커서를 어떻게 설정할지 초기화 할지인것같다. 아마 4bit 방식도 같을 것으로 예상됨