AVR

ADC와 char LCD

작성자 임베디드코리아 작성일17-11-13 19:32 조회2,641회 댓글0건
/*
 * ADC_lcd.c
 *
 * Created: 2017-11-13 오후 6:13:47
 * Author : GLORY
 */

#include <avr/io.h>
#include <util/delay.h> //_delay_us(), _delay_ms() 함수를 사용하기 위해

//DDRAM 설정 : 0x80+DDRAM address 값
#define LINE1 0x80  //첫번째 라인의 DDRAM address : 0x00 -> 0x80+0x00
#define LINE2 0xC0  //두번째 라인의 DDRAM address : 0x40 -> 0x80+0x40

//PG2=LCD_EN, PG1=RW, PG0=RS 에 연결
#define CMD_WRITE  0xFC  //명령어쓰기 E=1, RW=0, RS=0
#define CMD_READ    0xFE  //명령어읽기 E=1, RW=1, RS=0
#define DATA_WRITE  0xFD  //데이터쓰기 E=1, RW=0, RS=1
#define DATA_READ  0xFF  //데이터읽기 E=1, RW=1, RS=1
#define LCD_EN      0x04    //PG2에 연결되어 있기 때문에 bit2를 1로 했다.

//LCD에 명령을 쓰기 위한 함수
void LCD_cmd_write(char cmd)
{
PORTG = CMD_WRITE;    //PORTG에 RS, RW, E 가 연결되어 있다.
PORTB = cmd;                //PORTB에 데이터버스가 연결되어 있다.
PORTG = PORTG^LCD_EN;  //E 신호를 H->L로 하기 위해
_delay_ms(2);                //LCD 내부 동작시간
}
void LCD_pos(unsigned char col, unsigned char row)  //LCD 포지션 설정
{
LCD_cmd_write(0x80 | (row+col*0x40));  // row=행 / col=열 ,DDRAM주소설정

}
// LCD 초기화, 초기화 강좌의 순서도 참조
void init_LCD(void)
{
_delay_ms(15);        //15msec 이상 시간지연
LCD_cmd_write(0x38); //기능셋(데이터버스 8비트, 라인수:2줄)

_delay_ms(5);        //4.1msec 이상 시간지연, 생략가능
LCD_cmd_write(0x38); //기능셋, 생략 가능
_delay_us(100);      //100usec 이상 시간지연, 생략가능
LCD_cmd_write(0x38); //기능셋, 생략 가능

LCD_cmd_write(0x08);  //표시 Off , 생략 가능
LCD_cmd_write(0x01);  //화면 지우기
LCD_cmd_write(0x06);  //엔트리모드셋
LCD_cmd_write(0x0C);  //표시 on
}

//LCD에 데이터를 쓰기 위한 함수
void LCD_data_write(char data)
{
PORTG = DATA_WRITE;    //PORTG에 RS, RW, E 가 연결되어 있다.
PORTB = data;                //PORTB에 데이터버스가 연결되어 있다.
PORTG = PORTG^LCD_EN;  //E 신호를 H->L로 하기 위해
_delay_ms(2);                      //LCD 내부 동작시간
}

// LCD에 문자열을 표시하기 위한 함수
void LCD_wr_string(char d_line, char *lcd_str)
{
LCD_cmd_write(d_line);      //문자열을 표시하기 위한 라인 설정
while(*lcd_str != '\0')
{
LCD_data_write(*lcd_str);  //한개의 문자씩 LCD에 표시한다.
lcd_str++;
}
}

void lcdPrintData(char *str)    //↑문자열을 한문자씩 출력함수로 전달
{ while(*str !=0)
{
LCD_data_write(*str);
str++;

}

}

void LCD_numerals (uint16_t _temp) {
uint8_t s100,s10;
LCD_pos(1,0); // 커서위치를 첫번째 줄, 첫번째 칸으로 이동
lcdPrintData(" Vres: "); // " Vres: " 출력
s100 = _temp/100; // 100의 자리 추출
if(s100> 0) LCD_data_write(s100+'0'); // 100의 자리 값이 있으면 출력
else lcdPrintData(" "); // 100의 자리 값이 없으면 빈칸 출력
s10 = _temp%100; // 100의 자리를 제외한 나머지 추출
LCD_data_write((s10/10)+'0'); // 10의 자리 추출하여 출력
LCD_data_write('.'); // 소숫점 출력
LCD_data_write((s10%10)+'0'); // 1의 자리 추출하여 출력
LCD_data_write('V'); // 전압 단위 출력
}

// ATmega128의 포트 초기화
void init_PORT(void){
DDRB = 0xFF;  //LCD 데이터 버스
PORTB = 0xFF;
DDRG = 0xFF;  //LCD 컨트롤 신호(PG2=LCD_EN, PG1=RW, PG0=RS)
PORTG = 0xFF;
}

int main(void)
{
unsigned int AdData = 0; // 10bit ADC값 저장 변수
float v_temp;  // 전압값을 계산할 변수
ADMUX = 0x01;  // 00000
ADCSRA = 0x87;

init_PORT();  //초기화
init_LCD();

while(1){
        ADCSRA |= 0x40; // ADSC AD 개시(Start)
        while((ADCSRA & 0x10) == 0x00); // ADIF AD 다 될 때까지 기다림
        AdData = ADC; // 전압이 디지털로 변환된 값 읽어오기
        v_temp = (float)AdData*33/1023;
        LCD_numerals(v_temp);
}

return 1;
}