embeded/AVR (ATmega,ATtiny)2013. 12. 31. 08:40
역시 눈에 들어 오는게 최고지 ㅋㅋ
ATmega128에는 총 4개
Atmega8에는 총 3개의 timer/counter가 존재한다.

UI상으로는 Timer1/3이 16bit로 사용가능하며
TCNT1/TCNT3은
TCNT1H / TCNT1L 이런식으로 16bit 로 확장되어 있으나
TCNT1이 TCNT1L과 동일 메모리 주소로 설정되어 8bit/16bit로 사용이 가능해진다.
(Atmega8은 Timer3가 없으며 Timer1이 유일한 16bit 타이머이다)





문제는... Timer는 우선순위가 높아야 하는데 Timer3는 UART0 보다 우선순위가 낮으므로
Timer1 번을 이용해서 16bit Timer를 사용하는게 가장 무난한 선택으로 생각된다. (Timer0 8bit를 포기!)

 
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 30. 23:47
메모리나 플래시 용량이 크지 않은 micom 특성상 용량을 줄이기 위해서 발악을 해야하는데
사소한 팁이라고 해야하려나... 

inline void init_timer(void)
{
TCCR0 = 0x04;     // Prescaler 설정
TCNT0 = OVERFLOW - (F_CPU / TICKS_PER_SEC / Prescaler);// 오버플로우에 사용될 초기값
TIMSK = 0x01;     // 오버플로우 인터럽트 허용
}

int main(void)
{
int idx = 0;
int val = 1500;

DDRB = 0xFF;
PORTB = 0x00;

init_timer();
while(1)
{
;
}

return 0;
}

inline 사용시
AVR Memory Usage
----------------
Device: atmega8

Program:     146 bytes (1.8% Full)
(.text + .data + .bootloader)

Data:          2 bytes (0.2% Full)
(.data + .bss + .noinit)
 

inline 사용시
AVR Memory Usage
----------------
Device: atmega8

Program:     160 bytes (2.0% Full)
(.text + .data + .bootloader)

Data:          2 bytes (0.2% Full)
(.data + .bss + .noinit)

정말 사소한 용량 차이이지만 하나하나 쌓이면 은근 커지기에..
나중에 switch 테스트 예정 
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 30. 19:40
아래와 같이 EEMEM 이라는 접두를 이용해서 선언하면 되는데
avr/eeprom.h를 포함해야 한다.
#include <avr/eeprom.h>
EEMEM char test[128]; 

만약 include 하지 않으면 아래와 같은 에러가 발생한다.
 ../servo.c:29: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'char' 

컴파일 성공시에는 아래와 같이 메시지가 나타나는데
EEPROM 이라는게 추가 되어 나타난다. 
AVR Memory Usage
----------------
Device: atmega8

Program:     392 bytes (4.8% Full)
(.text + .data + .bootloader)

Data:          2 bytes (0.2% Full)
(.data + .bss + .noinit)

EEPROM:      128 bytes (25.0% Full)
(.eeprom) 

[링크 : http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html]
2012/01/03 - [embeded/ATmega/ATtiny (AVR)] - AVR EEPROM / CODE section 관련

Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 30. 17:26
1500us 센터 +-800usec 총 1600usec/180degree
아무래도 타이머를 이용한다고 하여도 16MHz 쓰는 이상
1usec 이상의 해상도는 무리라고 판단된다.

1600usec/180도 = 8usec/1도 
1usec = 0.125도

아무튼.. 계산을 해보니
정수형에 의한 오차가 발생할 수 밖에 없지만
0.1도를 한계(angle resolution)로 주고 0.05도 반올림 하여 사용하는게 전반적인 오차가 적을 것으로 생각된다.

 
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 29. 14:14
걍 귀찮아서.. 날로 먹은 소스코드임
일단 거상인 ATmega8 보드와 엘레파츠에서 이제는 매진되버린(!) 서보 모터를 사용함

[링크 : http://www.eleparts.co.kr/EPX33N6R] ES-311
[링크 : http://www.gersangin.com/shop/goods/goods_view.php?&goodsno=1092&category=] ATmega8

AVR Studio 프로젝트 설정시 ATmega8 과 클럭은 8,000,000 Hz(8MHz)로 설정한다.


퓨즈비트는 귀찮으니.. 내부 RC 8MHz 클럭으로.. 물론 보드에 16MHz 외부 크리스탈 있으니
필요하다면 변경하고 위의 주파수를 설정해주면 된다.


일단.. 가장 중요한건.. 전원이 부족해서 USB 파워로는 안될건 뻔하고..
그렇기에 전원을 분리했더니 그라운드가 달라서 오작동을 한다.(미친듯이 왼쪽으로만 끝까지 가버리는...)
그런 이유로 보드에 인가되는 전원 그라운드와 서보에 인가되는 전원 그라운드를 묶어주어야 한다.
(이러면.. 아날로그노이즈가 타고 오지 않으려나? ㅠㅠ)


일단은 GPIO를 이용해서 간단하게 중앙 - 좌 - 중앙 - 우
왕복시키는 코드이다. 이제 갯수도 늘려봐야 하는데 크앙!
서보 특성상 20ms 주기로 PWM 신호를 보내주고
신호의 길이는 1500usec이 neutral(중앙/센터)
+- 800usec인 700usec / 2300usec 범위에서 제어를 한다.

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

/******************************************/
int main(void)
{
	int idx = 0;
	int val = 1500;

	DDRB = 0xFF;
	PORTB = 0x00;
	
	while(1)
	{
		for(idx = 0; idx < 50; idx++)
		{
			PORTB = 0xFF;
			_delay_us(1500);

			PORTB = 0x00;
			_delay_us(20000 - 1500);
		}

		for(idx = 0; idx < 50; idx++)
		{
			PORTB = 0xFF;
			_delay_us(700);

			PORTB = 0x00;
			_delay_us(20000 - 700);
		}

		for(idx = 0; idx < 50; idx++)
		{
			PORTB = 0xFF;
			_delay_us(1500);

			PORTB = 0x00;
			_delay_us(20000 - 1500);
		}

		for(idx = 0; idx < 50; idx++)
		{
			PORTB = 0xFF;
			_delay_us(2300);

			PORTB = 0x00;
			_delay_us(20000 - 2300);
		}
	}

	return 0;
}
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 27. 20:59
학원 알아보러 가는 김에 겸사겸사
세운상가에 가서 개당 1000원에 구매!
16MHz 짜리를 사려고 했으나 없다고 하셔서 이거라도 일단 get!


동일한 모델이 없어서 고민때리다
대충 오실레이터 잡아서 데이터시트 보고 연결!

[링크 : http://devicemart.co.kr/goods/view.php?seq=5679]

ATtiny 3개중에 2개는 살리고
거상인 ATmega8도 살리고 아싸 조으다 조으다 ㅋㅋㅋ

2013/12/20 - [embeded/ATmega/ATtiny (AVR)] - Atmega8 으앙 쥬금!!! ㅠㅠ


+ 이거 전에 다른 ATmega128에서
 while(1) { PORTA = 0xFF; PORTA=0x00; } 

이런 간략한 소스로 8MHz 정도 나오지 않을까.. 라는 소스를 작성해서 해보았느나
접점의 문제인지 클럭이 깔끔하지 않아서 인지.. 인공호흡 실패 ㅠㅠ 
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 25. 00:41


사용부품
[링크 : http://www.us-technology.co.kr/product/product_main.asp?mode=101&smode=9] v3.0 보드
[링크 : http://devicemart.co.kr/goods/view.php?seq=1075057 ] LC1628 (동일 부품 아닐수도 있음)

참고소스
[링크 : http://www.avrprojects.net/attachments/lcdinterface.c]

참고 데이터시트
[링크 : http://www.ganasys.co.kr/kor/support_board2/pds_file/LC1628-BMDWH6Rev1.0.pdf]



lc1628.h
/*******************************************************
	LC1628 definition
*******************************************************/

/***************** position *****************/
#define	CLCD_RS	0x01
#define	CLCD_RW	0x02
#define	CLCD_E	0x04
#define	CLCD_DA	0xF0

/***************** command *****************/
/* RS R/W = 0x00 */
#define CMD_CLS 0x01	// Clear Display
#define CMD_RTH 0x02	// Return HOME
#define CMD_MOD 0x04	// Entry Mode Set
	#define MOD_INC 0x02
	#define MOD_DEC 0x00
	#define MOD_SHL 0x01
	#define MOD_SHR 0x00
#define CMD_DIS 0x08	// Display on/off
	#define DIS_ON  0x04
	#define DIS_CUR 0x02
	#define DIS_BLK	0x01
#define CMD_CUR 0x10	// Cursor or Display Shift
	#define CUR_CUR 0x08
	#define CUR_ALL	0x00
	#define CUR_LEF 0x04
	#define CUR_RIG 0x00
#define CMD_FNC 0x20	// Function Set
	#define FNC_DL8 0x10
	#define FNC_DL4 0x00
	#define FNC_DN2 0x08
	#define FNC_DN1 0x00
	#define FNC_H10	0x04
	#define FNC_H07	0x00
#define CMD_CGA 0x40	// Set CGRAM Address
	#define CRA_ADR 0x3F
#define CMD_DDA 0x80	// Set DDRAM Address

lc1628.c
#include < stdio.h >
#include < avr/io.h >
#include < util/delay.h >
#include "lc1628.h"

#define DEFAULT_DLY	20

static int uart_putchar(char c, FILE *stream)
{
	if (c == '\n') uart_putchar('\r', stream);
	loop_until_bit_is_set(UCSR0A, UDRE);
	UDR0 = c;

  return 0;
}

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);


/*************************************************/
void ls1628_write_cmd(char cmd)
{
	/**************************************/
	// set RS & R/W
	PORTC = 0x00;

	// set E clock to high
	_delay_us(DEFAULT_DLY); // 40ns delay
	PORTC |= CLCD_E;

	// data set - high nibble
	PORTC |= (cmd & 0xF0);
	_delay_us(DEFAULT_DLY); // 80ns delay

	// set E clock to low
	PORTC &= (~CLCD_E);
	_delay_us(DEFAULT_DLY); // 10ns delay

	// release RW
	PORTC &= (~CLCD_RW);


	/**************************************/
	// set RS & R/W
	PORTC = 0x00;

	// set E clock to high
	_delay_us(DEFAULT_DLY); // 40ns delay
	PORTC |= CLCD_E;

	// data set - low nibble
	PORTC |= ((cmd & 0x0F) << 4);
	_delay_us(DEFAULT_DLY); // 80ns delay

	// set E clock to low
	PORTC &= (~CLCD_E);
	_delay_us(DEFAULT_DLY); // 10ns delay

	// release RW
	PORTC &= (~CLCD_RW);
}

void ls1628_write_char(char data)
{
	/**************************************/
	// set RS & R/W
	PORTC = CLCD_RS;

	// set E clock to high
	_delay_us(DEFAULT_DLY); // 40ns delay
	PORTC |= CLCD_E;

	// data set - high nibble
	PORTC |= (data & 0xF0);
	_delay_us(DEFAULT_DLY); // 80ns delay

	// set E clock to low
	PORTC &= (~CLCD_E);
	_delay_us(DEFAULT_DLY); // 10ns delay

	// release RW
	PORTC &= (~CLCD_RW);


	/**************************************/
	// set RS & R/W
	PORTC = CLCD_RS;

	// set E clock to high
	_delay_us(DEFAULT_DLY); // 40ns delay
	PORTC |= CLCD_E;

	// data set - low nibble
	PORTC |= ((data & 0x0F) << 4);
	_delay_us(DEFAULT_DLY); // 80ns delay

	// set E clock to low
	PORTC &= (~CLCD_E);
	_delay_us(DEFAULT_DLY); // 10ns delay

	// release RW
	PORTC &= (~CLCD_RW);
}

/*************************************************/
void ls1628_cmd_clear()
{
	ls1628_write_cmd(CMD_CLS);
}

void li1628_cmd_setpos(char y, char x)
{
	// y must 0(1st line) or 1(2nd line)
	ls1628_write_cmd(CMD_DDA | (y * 0x40 + x));
}

void ls1628_write_string(char *data)
{
	int idx = 0;

	while(data[idx] != 0x00)
		ls1628_write_char(data[idx++]);
}

/*************************************************/
void init_clcd(void)
{
	_delay_ms(50);
	ls1628_write_cmd(CMD_FNC | FNC_DL4 | FNC_DN2 | FNC_H07);	// fuction set
	PORTC = CLCD_E; // unknown

	_delay_us(80);	 											// 39 us wait
	ls1628_write_cmd(CMD_DIS | DIS_ON | DIS_CUR | DIS_BLK);		// disp on/off control
	_delay_us(80);	 											// 39 us wait
	ls1628_write_cmd(CMD_CLS);									// disp clear
	_delay_ms(2);												// 1.53ms wait
	ls1628_write_cmd(CMD_MOD | MOD_INC | MOD_SHR);				// entry mode set CMD_MOD
	_delay_us(80);
	ls1628_write_cmd(CMD_DDA);
	_delay_us(80);
}

void init_uart0(void)
{
	/* UART0 115200-N-8-1 */
	UBRR0H = 0;
	UBRR0L = 8; // 115k with U2X = 0
	UCSR0A = 0x00; // U2X = 0;
	UCSR0B = 0xD8;
	UCSR0C = 0x06; //Asyncronous - no parity - 1bits(stop) - 8bits(data)

    stdout = &mystdout;

	printf("\n\n\n\n\n");
}

void init_atmega(void)
{
	DDRC = 0xFF;
	PORTC = 0xFF;

	SFIOR = SFIOR | 0x04;

	init_uart0();
}

int main(void)
{
	init_atmega();
	init_clcd();

	li1628_cmd_setpos(0,3);
	ls1628_write_string("Hello World");
	li1628_cmd_setpos(1,0);
	ls1628_write_string("ATmega128 CLCD");

	return 0;
}

'embeded > AVR (ATmega,ATtiny)' 카테고리의 다른 글

ATmega8 로 ES-311(HS-311) 서보 제어하기  (2) 2013.12.29
ATtiny2313 / ATmega8 인공호흡!  (0) 2013.12.27
ATmega128 + LC1628 제어하기 2  (0) 2013.12.24
ATmega128 + LC1628 제어하기 1  (0) 2013.12.24
lc1628 예제 소스  (0) 2013.12.20
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 24. 23:54
명령어와 데이터 관련 GPIO 제어루틴

귀찮으니 대충 정리해서
명령어는
Step 1. RS/RW가 동시에 Low로 이동 (40ns delay)
Step 2. E가 High로 이동 / Data 설정(상위 4비트)
Step 3. E가 Low로 이동 (10ns delay)
Step 4. RW 해제
 

Step 5. RS/RW가 동시에 Low로 이동
Step 6. E가 High로 이동 / Data 설정 (하위 4비트) - Step 2 반복
Step 7. E가 Low로 이동 (10ns delay) - Step 3 반복
Step 8. RS/RW가 동시에 High로 이동

DDRAM/CGRAM 데이터는
Step 1. RS는 High RW는 Low로 이동 (40ns delay)
Step 2. E가 High로 이동 / Data 설정(상위 4비트)
Step 3. E가 Low로 이동 (10ns delay)
Step 4. RW 해제
 

Step 5. RS는 High RW는 Low로 이동
Step 6. E가 High로 이동 / Data 설정 (하위 4비트) - Step 2 반복
Step 7. E가 Low로 이동 (10ns delay) - Step 3 반복
Step 8. RS/RW가 동시에 High로 이동


#define	CLCD_RS	0x01
#define	CLCD_RW	0x02
#define	CLCD_E	0x04

#define DEFAULT_DLY	20

void ls1628_write_cmd(char cmd)
{
	/**************************************/
	// set RS & R/W
	PORTC = 0x00;

	// set E clock to high
	_delay_us(DEFAULT_DLY); // 40ns delay
	PORTC |= CLCD_E;

	// data set - high nibble
	PORTC |= (cmd & 0xF0);
	_delay_us(DEFAULT_DLY); // 80ns delay

	// set E clock to low
	PORTC &= (~CLCD_E);
	_delay_us(DEFAULT_DLY); // 10ns delay

	// release RW
	PORTC &= (~CLCD_RW);


	/**************************************/
	// set RS & R/W
	PORTC = 0x00;

	// set E clock to high
	_delay_us(DEFAULT_DLY); // 40ns delay
	PORTC |= CLCD_E;

	// data set - low nibble
	PORTC |= ((cmd & 0x0F) << 4);
	_delay_us(DEFAULT_DLY); // 80ns delay

	// set E clock to low
	PORTC &= (~CLCD_E);
	_delay_us(DEFAULT_DLY); // 10ns delay

	// release RW
	PORTC &= (~CLCD_RW);
}

void ls1628_write_char(char data)
{
	/**************************************/
	// set RS & R/W
	PORTC = CLCD_RS;

	// set E clock to high
	_delay_us(DEFAULT_DLY); // 40ns delay
	PORTC |= CLCD_E;

	// data set - high nibble
	PORTC |= (data & 0xF0);
	_delay_us(DEFAULT_DLY); // 80ns delay

	// set E clock to low
	PORTC &= (~CLCD_E);
	_delay_us(DEFAULT_DLY); // 10ns delay

	// release RW
	PORTC &= (~CLCD_RW);


	/**************************************/
	// set RS & R/W
	PORTC = CLCD_RS;

	// set E clock to high
	_delay_us(DEFAULT_DLY); // 40ns delay
	PORTC |= CLCD_E;

	// data set - low nibble
	PORTC |= ((data & 0x0F) << 4);
	_delay_us(DEFAULT_DLY); // 80ns delay

	// set E clock to low
	PORTC &= (~CLCD_E);
	_delay_us(DEFAULT_DLY); // 10ns delay

	// release RW
	PORTC &= (~CLCD_RW);
}

CLCD 초기화는 아래와 같이 수행해 준다.
그런데.. Function set 이후에 왜 E를 High로 해주어야 하는건지... 이유를 모르겠다!!!
#define CMD_CLS 0x01	// Clear Display
#define CMD_RTH 0x02	// Return HOME
#define CMD_MOD 0x04	// Entry Mode Set
	#define MOD_INC 0x02
	#define MOD_DEC 0x00
	#define MOD_SHL 0x01
	#define MOD_SHR 0x00
#define CMD_DIS 0x08	// Display on/off
	#define DIS_ON  0x04
	#define DIS_CUR 0x02
	#define DIS_BLK	0x01
#define CMD_CUR 0x10	// Cursor or Display Shift
	#define CUR_CUR 0x08
	#define CUR_ALL	0x00
	#define CUR_LEF 0x04
	#define CUR_RIG 0x00
#define CMD_FNC 0x20	// Function Set
	#define FNC_DL8 0x10
	#define FNC_DL4 0x00
	#define FNC_DN2 0x08
	#define FNC_DN1 0x00
	#define FNC_H10	0x04
	#define FNC_H07	0x00
#define CMD_CGA 0x40	// Set CGRAM Address
	#define CRA_ADR 0x3F
#define CMD_DDA 0x80	// Set DDRAM Address

void init_clcd(void)
{
	_delay_ms(50);
	ls1628_write_cmd(CMD_FNC | FNC_DL4 | FNC_DN2 | FNC_H07);	// fuction set
	PORTC = CLCD_E; // unknown

	_delay_us(80);	 											// 39 us wait
	ls1628_write_cmd(CMD_DIS | DIS_ON | DIS_CUR | DIS_BLK);		// disp on/off control
	_delay_us(80);	 											// 39 us wait
	ls1628_write_cmd(CMD_CLS);									// disp clear
	_delay_ms(2);												// 1.53ms wait
	ls1628_write_cmd(CMD_MOD | MOD_INC | MOD_SHR);				// entry mode set CMD_MOD
	_delay_us(80);
	ls1628_write_cmd(CMD_DDA);
	_delay_us(80);
}

'embeded > AVR (ATmega,ATtiny)' 카테고리의 다른 글

ATtiny2313 / ATmega8 인공호흡!  (0) 2013.12.27
ATmega128 + LC1628 제어하기 3  (2) 2013.12.25
ATmega128 + LC1628 제어하기 1  (0) 2013.12.24
lc1628 예제 소스  (0) 2013.12.20
Atmega8 으앙 쥬금!!! ㅠㅠ  (0) 2013.12.20
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 24. 23:46
현재는 DDRAM에 문자만 넣는 정도로 간략하게 출력하는 예제이다.

PORTC 에
7654(DATA) 2(E) 1(RW) 0(RS) 로 회로가 구성된 경우의 소스이다.

일단 LC1628의 타이밍 차트는 아래와 같으며
RS/RW 가 동시에 움직이고
E의 falling edge에서 Data를 읽어 가도록 되어있다.



8bit도 해봐야 하는데.. 회로 구성이 일단 4bit로 되어있으니
4비트 강제 설정을 해주어야 하는데
문서의 실수인지 Function Set이 12 비트이다..
그냥 무시하고 8바이트로 보내도 문제는 없는 것 같긴하다.


기본 설정시의 DDRAM 주소이다.
0x40을 더해주면 2번째 라인으로 이동된다.


'embeded > AVR (ATmega,ATtiny)' 카테고리의 다른 글

ATmega128 + LC1628 제어하기 3  (2) 2013.12.25
ATmega128 + LC1628 제어하기 2  (0) 2013.12.24
lc1628 예제 소스  (0) 2013.12.20
Atmega8 으앙 쥬금!!! ㅠㅠ  (0) 2013.12.20
avr pud(pull up disable)  (0) 2013.12.19
Posted by 구차니
embeded/AVR (ATmega,ATtiny)2013. 12. 20. 15:48
원래 링크의 카페는 막혀있어서
회로 구성이라던가 이런걸 알 수 없지만 참고용으로 링크 저장

데이터시트 상으로는 ns 급으로 쉬어주어야 하지만
AVR ATmega128 16MHz라고 해도
명령어 처리에 10ns 급 정도의 딜레이는 가볍게 생기니까
그런건 무시하고 바로바로 포트에 값을 넣어 주는 듯 하다.

[링크 : http://blog.daum.net/irobotavr/668278] 8bit 통신

4bit 통신예제. PORTB로 되어있음. 하지만.. 작동이 안되네?
// used pins on port B
#define LCD_DB4 0    // PORTB.0 
#define LCD_DB5 1    // PORTB.1
#define LCD_DB6 2    // PORTB.2 
#define LCD_DB7 3    // PORTB.3
#define LCD_E  6     // PORTB.6 Enable 
#define LCD_RS 7     // PORTB.7 Register Select
[링크 : http://www.avrprojects.net/.../avr-c-programming-tutorials/112-4-bit-lcd-interface] 4bit 통신


---
PORTC 에 
7654(DATA) 2(E) 1(RW) 0(RS) 로 회로가 구성된 경우로 포팅한 녀석.
이 소스는 문자가 무언가는 나오지만 제대로 나오지 않는 문제가 있다.
하지만 이 소스를 통해 CLCD를 초기화할 경우 제대로 되기에 초기화 부분을 분석해서 내 소스에 적용하게 됨.
// used pins on port B
#define LCD_DB4 4    // PORTB.0 
#define LCD_DB5 5    // PORTB.1
#define LCD_DB6 6    // PORTB.2 
#define LCD_DB7 7    // PORTB.3
#define LCD_E  2     // PORTB.6 Enable 
#define LCD_RS 0     // PORTB.7 Register Select


//LCD commands
#define LCD_CLR 		0x01    // clear display
#define LCD_HOME 		0x02    // return home

#define LCD_INC 		0x06    // Increment, display freeze
#define LCD_MOV 		0x10    // Cursor move, not shift

#define LCD_OFF         0x08    // lcd off
#define LCD_ON          0x0C    // lcd on             
#define LCD_BLINK_ON	0x0D    // blink on              
#define LCD_CURSOR_ON	0x0E    // cursor on               
#define LCD_ALL_ON	    0x0F    // cursor on /  blink on
#define LCD_LINE1  		0x80    // cursor Pos on line 1 (or with column)
#define LCD_LINE2  		0xC0    // cursor Pos on line 2 (or with column)

unsigned char chr,data,pos;

// writes a char to the LCD
void LCD_char(unsigned char data)

{
	PORTC = data & 0b11110000; //high nibble
	PORTC |= 1 << LCD_RS;
	PORTC |= 1 << LCD_E;
	_delay_ms(2);
	PORTC &= ~(1 << LCD_E);
	_delay_ms(2);

	PORTC = (data << 4) & 0b11110000; //low nibble
	PORTC |= 1 << LCD_RS;
	PORTC |= 1 << LCD_E;
	_delay_ms(2);
	PORTC &= ~(1 << LCD_E);
	_delay_ms(2);
}


// writes a instruction to the LCD
void LCD_inst(unsigned char inst)

{	
	PORTC = (inst & 0b11110000); //send high nibble
	PORTC &= ~(1 << LCD_RS); // set RS to instructions
	PORTC |= 1 << LCD_E;
	_delay_ms(2);
	PORTC &= ~(1 << LCD_E);
	_delay_ms(2);

	PORTC = (inst << 4) & 0b11110000; //send low nibble
	PORTC |= 1 << LCD_E;
	_delay_ms(2);
	PORTC &= ~(1 << LCD_E);
	_delay_ms(2);	
}

// clear display
void LCDclr(void)
{
	LCD_inst (LCD_CLR);
}

// return home
void LCDhome(void)
{
	LCD_inst (LCD_HOME);
}

// LCD off
void LCDoff(void)
{
	LCD_inst (LCD_OFF);
}

// LCD on
void LCDon(void)
{
	LCD_inst (LCD_ON);
}

// cursor on
void LCDcursor(void)
{
	LCD_inst (LCD_CURSOR_ON);
}

// blink on
void LCDblink(void)
{
	LCD_inst (LCD_BLINK_ON);
}

// cursor all on
void LCDall(void)
{
	LCD_inst (LCD_ALL_ON);
}

//go to first line
void LCDline1 (void)

{
	LCD_inst (0b10000000);
}

//go to second line
void LCDline2 (void)
{
	LCD_inst (0b11000000);
}


// goto position x,y
void LCDgoto (char x,char y)
{

	if (y == 0)			pos = 0b00000000 + x;
	else if (y == 1)	pos = 0b01000000 + x;

	LCD_inst (0b10000000 | pos);
}

//write text to the LCD
void LCDtext(char *data)
{
	while (*data)
	{
		LCD_char(*data);
		data++;
	}
}

// init LCD

void LCD_init(void)
{
	DDRC = 0xFF;  // PORTC as output
	_delay_ms(40);

	// set 4-bit mode
	PORTC = 1 << 2;
	PORTC |= 1 << LCD_E;
	_delay_ms(1);
	PORTC &= ~(1 << LCD_E);
	_delay_ms(1);

	PORTC = 1<< 2;
	PORTC |= 1 << LCD_E;
	_delay_ms(1);
	PORTC &= ~(1 << LCD_E);
	_delay_ms(1);

	PORTC = 1 << 2;
	PORTC |= 1 << LCD_E;
	_delay_ms(1);
	PORTC &= ~(1 << LCD_E);
	_delay_ms(1);

	//set 4-bit mode and 2-line
	//LCD_inst (0b00101000);
	LCD_inst (0b00101000);

	//turn on display and cursor
	LCD_inst (0b00001100);

	//clr display
	LCD_inst (LCD_CLR);
}

int main( void )
{
	LCD_init();
	LCDtext (">AVR LCD DEMO<");
	LCDgoto (2,1);
	LCDtext("Hello World!");
	LCDall();
	LCDhome();
}

'embeded > AVR (ATmega,ATtiny)' 카테고리의 다른 글

ATmega128 + LC1628 제어하기 2  (0) 2013.12.24
ATmega128 + LC1628 제어하기 1  (0) 2013.12.24
Atmega8 으앙 쥬금!!! ㅠㅠ  (0) 2013.12.20
avr pud(pull up disable)  (0) 2013.12.19
AVR-GCC Program space  (0) 2013.12.19
Posted by 구차니