안녕하세요..
저번에도 같은 내용으로 질문을 했었는데요.. 또 좋은 답변을 얻을수 있을꺼 같아서
다시 한번더 질문하겠습니다.
※ 프로그램 설명 Atmega128 사용합니다.
- ADC를 이용하여 센서를 스위치로 사용
- 센서값을 0 또는 1로 표현을 하여서 LCD와 터미널프로램에 출력
- 입출력 구조 : 입력-센서8, 출력-LCD와 터미널프로그램
- 출력의 예(8*2 LCD 사용)
* LCD의 1번 라인을 8개로 분할하여 1번의 센서값이 기준값 500에서 600이 되었을때 → [0][0][0][0][0][0][0][1]→ PC전송
* LCD의 1번 라인을 8개로 분할하여 2번의 센서값이 기준값 500에서 600이 되었을때 → [0][0][0][0][0][0][1][0]→ PC전송
* LCD의 1번 라인을 8개로 분할하여 1,2번의 센서값이 기준값 500에서 600이 되었을때 → [0][0][0][0][0][0][1][1]→ PC전송
여기까지가 프로그램 설명입니다.
현재까지 코딩은 센서2개를 LCD의 라인1과 라인2와 터미널프로그램으로 출력합니다.
- 1번라인의 1번 센서 : [5][0][0][ ]][ ][ ][ ][ ]→ PC전송
- 2번라인의 2번 센서 : [5][0][0][ ]][ ][ ][ ][ ]→ PC전송
이것을 수정해서 LCD의 1번 라인에 스위치 형태로 8개 센서를 표현하고 싶은데 어떻게 해야 할지 모르겠네요
우선은 2개만이라도 1번 라인에 표현을 해보고 싶습니다. 실력이 부족해서요..
어디를 어떻게 수정하면 좋을지 조언을 해주시면 좋겠습니다.^^
고쳐주시면 더 좋고요..
- 소 스 -
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
// LCD 모듈로 접근하기 위한 외부 메모리 주소 선언
#define LCD_EN (*(volatile unsigned char *)0x8000)
#define LCD_WRITE (*(volatile unsigned char *)0x8002)
// LCD 모듈의 첫번째 라인, 두번째 라인 주소
#define LINE1 0x00 // LCD_Display_LINE1
#define LINE2 0x40 // LCD_Display_LINE2
// 함수 선언부 - 지연 함수
void delay_us(unsigned char);
void delay_ms(unsigned int);
// 함수 선언부 - LCD 초기화 관련 함수
void FunctionSet(); // FUNCTION SET
void DisplayOnOffControl(); //DISPLAY ON/OFF
void DisplayClear(); // DISPLAY CLEAR
void EntryModeSet(); // ENTRY MODE SET
// 함수 선언부 - LCD 글자표시 함수(문자 및 문자열)
void DisplayChar(unsigned char);
void DisplayString(unsigned char *);
void SetLCDAddress(unsigned char);
void TXD0(char data){ while(!(UCSR0A&0x20)); UDR0=data; }
//char RXD0(void){ while(!(UCSR0A&0x80)); return UDR0; }
// ADC 데이터를 표시하기 위한 데이터들
unsigned char ADC_L = 0x00; // ADC0의 하위바이트 결과 저장
unsigned char ADC_H = 0x00; // ADC0의 상위바이트 결과 저장
unsigned int ADC_RESULT = 0x00; // ADC0의 결과저장
unsigned char c1,c2,c3,c4; // 일,십,백,천 자리수 표현을 위한 임시변수
// 센서들의 변수 선언
unsigned int ADC_F0 = 0x00; // FLEX센서 1번
unsigned int ADC_F1 = 0x00; // FLEX센서 2번
unsigned int ADC_F2 = 0x00; // FLEX센서 3번
unsigned int ADC_F3 = 0x00; // FLEX센서 4번
unsigned int ADC_F4 = 0x00; // FLEX센서 5번
unsigned int ADC_F5 = 0x00; // FLEX센서 6번
unsigned int ADC_F6 = 0x00; // FLEX센서 7번
unsigned int ADC_F7 = 0x00; // FLEX센서 8번
unsigned char MAGNETIC_VALUE = 0x00; // 마그네틱 센서의 입력값 저장을 위해 쓰이는 변수
int main(void)
{
//========== SFR 초기화
SP = 0x10ff;
MCUCR = 0x80; // I/O 포트를 특수기능 모드로 설정
XMCRA = 0x40; // 외부 메모리 섹터 설정
XMCRB = 0x80; // 외부 메모리 섹터 설정
//========== I/O PORT로 입력받기(스위치 사용)
DDRD = 0xff; // PORTD를 출력모드로 설정(마그네틱 센서값의 출력에 사용)
PORTD = 0xff; // PORTD의 LED를 소등한다_LED미사용으로 사용 불필요 예상(마그네틱 센서에 사용)
DDRA = 0x00; // PORTA를 입력모드로 설정(마그네틱 센서값의 입력에 사용)
//========== 통신환경 설정
DDRE=2; //통신 입출력 설정
UCSR0A=0x00;
UCSR0B=0x18;
UCSR0C=6;
UBRR0H=0;
UBRR0L=103; // 통신 환경 설정 9600 bps
//========== LCD 초기화
FunctionSet();
DisplayOnOffControl();
DisplayClear();
EntryModeSet();
while(1)
{
//============================================ LINE1에 F0센서를 출력
ADCH = 0x00; // 변수 초기화
ADCL = 0x00; // 변수 초기화
ADMUX = 0x00; // ADC 설정
ADCSR = 0xc7; // ADC 설정 및 시작
while((ADCSR & 0x10)==0); // 변환완료까지 기다림
ADC_L = ADCL; // ADC0의 하위바이트결과
ADC_H = ADCH; // ADC0의 상위바이트결과
// ADC0의 상하위바이트 값을 이용하여 10비트값을 복원
ADC_RESULT = 0x00;
ADC_RESULT = ADC_RESULT | ADC_H;
ADC_RESULT = 0x300 & (ADC_RESULT<<8);
ADC_RESULT = ADC_RESULT | ADC_L;
ADC_F0 = ADC_RESULT; // ADC_RESULT값을 F0에 저장
// 값을 LCD에 표시
c4 = ADC_F0 / 1000;
c3 = (ADC_F0 % 1000) / 100;
c1 = ADC_F0 % 100;
c2 = c1/10;
c1 = c1 % 10;
SetLCDAddress(LINE1); // LINE1에 출력
DisplayChar(c4+0x30); // 천의 자리
DisplayChar(c3+0x30); // 백의 자리
DisplayChar(c2+0x30); // 십의 자리
DisplayChar(c1+0x30); // 일의 자리
TXD0(c4+0x30); // 자리수의 값을 컴으로 전송 0~9
TXD0(c3+0x30); // 자리수의 값을 컴으로 전송 0~9
TXD0(c2+0x30); // 자리수의 값을 컴으로 전송 0~9
TXD0(c1+0x30); // 자리수의 값을 컴으로 전송 0~9
//============================================ LINE2에 F1센서를 출력
ADCH = 0x00; // 변수 초기화
ADCL = 0x00; // 변수 초기화
ADMUX = 0x01; // ADC 설정
ADCSR = 0xc7; // ADC 설정 및 시작
while((ADCSR & 0x10)==0); // 변환완표까지 기다림
ADC_L = ADCL; // ADC0의 하위바이트결과
ADC_H = ADCH; // ADC0의 상위바이트결과
// ADC0의 상하위바이트 값을 이용하여 10비트값을 복원
ADC_RESULT = 0x00;
ADC_RESULT = ADC_RESULT | ADC_H;
ADC_RESULT = 0x300 & (ADC_RESULT<<8);
ADC_RESULT = ADC_RESULT | ADC_L;
ADC_F1 = ADC_RESULT; // ADC_RESULT값을 F1에 저장
// 값을 LCD에 표시
c4 = ADC_F1 / 1000;
c3 = (ADC_F1 % 1000) / 100;
c1 = ADC_F1 % 100;
c2 = c1/10;
c1 = c1 % 10;
SetLCDAddress(LINE2); // LINE2에 출력
DisplayChar(c4+0x30); // 천의 자리
DisplayChar(c3+0x30); // 백의 자리
DisplayChar(c2+0x30); // 십의 자리
DisplayChar(c1+0x30); // 일의 자리
TXD0(c4+0x30); // 자리수의 값을 컴으로 전송 0~9
TXD0(c3+0x30); // 자리수의 값을 컴으로 전송 0~9
TXD0(c2+0x30); // 자리수의 값을 컴으로 전송 0~9
TXD0(c1+0x30); // 자리수의 값을 컴으로 전송 0~9
//============================================
DisplayChar(0x20); // 마그네틱
DisplayChar(0x20); // 마그네틱
DisplayChar(0x20); // 마그네틱
TXD0(0x20); // 마그네틱
TXD0(0x20); // 마그네틱
TXD0(0x20); // 마그네틱
TXD0(0x20); // 마그네틱
//============================================ 마그네틱을 스위치로 사용
MAGNETIC_VALUE = PINA; // PORTA에서 입력을 받아서 저장(마그네틱 센서)
TXD0(0x20); // 컴으로 전송 0~9
TXD0(0x20); // 컴으로 전송 0~9
TXD0(0x20); // 컴으로 전송 0~9
TXD0(0x20); // 컴으로 전송 0~9
// 입력 값의 첫 번째 비트 값이 1인지 0인지 검사
if((MAGNETIC_VALUE & 0x01) == 0x01)
{
DisplayChar(0x31); // LDC에 1을 출력
TXD0(0x31); // 컴으로 전송 0~9
}
else
{
DisplayChar(0x30); // LDC에 0을 출력
TXD0(0x30); // 컴으로 전송 0~9
}
TXD0('\n'); // 컴으로 전송 0~9
TXD0('\a'); // 컴으로 전송 0~9
delay_ms(2000);
}
} // main 끝
//========== LCD 모듈에 글자를 출력하기 위한 함수
void DisplayChar(unsigned char c)
{
LCD_WRITE = c; // 매개변수 데이터를 LCD에 표시
delay_us(50);
}
//========== LCD 모듈에 문장을 출력하기 위한 함수
void DisplayString(unsigned char* s)
{
unsigned char i, j;
i = 0;
j = strlen (s)-1;
for(i=0; i<=j; i++)
{
DisplayChar(s[i]);
}
}
//========== 글자가 표시될 RAM 주소를 설정하기 위한 함수
void SetLCDAddress(unsigned char mode)
{
LCD_EN = (0x80 | mode);
delay_us(50);
}
//========== LCD 모듈 초기화 관련 함수
void FunctionSet()
{
delay_ms(50);
LCD_EN = 0x38;
}
void DisplayOnOffControl()
{
delay_us(40);
LCD_EN = 0x0c;
}
void DisplayClear()
{
delay_us(40);
LCD_EN = 0x01;
}
void EntryModeSet()
{
delay_ms(2);
LCD_EN = 0x06;
delay_us(40);
}
//========== 아래부터 지연함수 구현부분
void delay_us(unsigned char time_us)
{
register unsigned char i;
for(i=0; i<time_us; i++) // 4 cycle
{
asm volatile("PUSH R0"); // 2 cycle
asm volatile("POP R0"); // 2 cycle
asm volatile("PUSH R0"); // 2 cycle
asm volatile("POP R0"); // 2 cycle
asm volatile("PUSH R0"); // 2 cycle
asm volatile("POP R0"); // 2 cycle
// Sum = 16, cycle = 1 us for 16MHz
}
}
void delay_ms(unsigned int time_ms)
{
register unsigned int i;
for(i=0; i<time_ms; i++) // 4 cycle
{
delay_us(50);
delay_us(50);
delay_us(50);
delay_us(50);
}
}
[5][0][0][ ]][ ][ ][ ][ ]
이런 형태로 8 개를 표시하려면 한줄에 24칸이 필요합니다.^^
5, 0,0, 이런 형태로 하셔야 할듯 합니다.^^
LCD 출력은 DisplayChar 이나, DisplayString 함수를 사용하시면 됩니다.^^
sprintf 함수를 사용하시면 간단하게 표현하실수 있을 겁니다.^^
그리고, 지금 다시 보니, while(1) 안에
DisplayChar를 사용해서 출력하고 있네요.^^