#include <iom128v.h>
#include <macros.h>
#define FUNCSET 0x28 // Function Set
#define ENTMODE 0x06 // Entry Mode Set
#define ALLCLR 0x01 // All Clear
#define LINE2 0xC0 // 2nd Line Move
#define HOME 0x02 // Cursor Home
#define DISPON 0x0c // Display On
#define DISPOFF 0x08 // Display Off
unsigned char value;
typedef unsigned char byte;
#pragma interrupt_handler adc_isr:22
void adc_isr(void)
{
value=ADCH;
Command(LINE2);
htoa(value);
delay_ms(5000);
}
void delay_us(unsigned char time_us) /* time delay for us 16MHz */
{
register unsigned char i;
for(i = 0; i < time_us; i++) // 4 cycle +
{
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle +
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle +
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle +
}
}
void delay_ms(unsigned int time_ms) /* time delay for ms */
{ register unsigned int i;
for(i = 0; i < time_ms; i++)
{
delay_us(250);
delay_us(250);
delay_us(250);
delay_us(250);
}
}
// LCD 초기화
void LCD_init(void)
{
DDRD = 0xFF; // 포트 D 출력 설정
PORTD &= 0xFB; // E = 0;
delay_ms(15);
Command(0x20);
delay_ms(5);
Command(0x20);
delay_us(100);
Command(0x20);
Command(FUNCSET);
Command(DISPON);
Command(ALLCLR);
Command(ENTMODE);
}
// 문자열 출력 함수
void LCD_String(char *str)
{
while(*str){
Data(*str++);
delay_ms(100);
}
}
// 인스트럭션 쓰기 함수
void Command(byte inst)
{
delay_ms(2);
// 인스트럭션 상위 바이트
PORTD = (inst & 0xF0); // 데이터
PORTD &= 0xFE; //RS = 0;
PORTD &= 0xFD; //RW = 0;
delay_ms(4);
PORTD |= 0x04; //E = 1;
delay_ms(4);
PORTD &= 0xFB; //E = 0;
// 인스트럭션 하위 바이트
PORTD = ((inst<<4) & 0xF0); // 데이터
PORTD &= 0xFE; //RS = 0;
PORTD &= 0xFD; //RW = 0;
delay_ms(4);
PORTD |= 0x04; //E = 1;
delay_ms(4);
PORTD &= 0xFB; //E = 0;
}
//데이터 쓰기 함수
void Data(byte dw)
{
delay_ms(2);
// 데이터 상위 바이트
PORTD = (dw & 0xF0); // 데이터
PORTD |= 0x01; //RS = 1;
PORTD &= 0xFD; //RW = 0;
delay_ms(4);
PORTD |= 0x04; //E = 1;
delay_ms(4);
PORTD &= 0xFB; //E = 0;
// 데이터 하위 바이트
PORTD = ((dw<<4) & 0xF0); // 데이터
PORTD |= 0x01; //RS = 1;
PORTD &= 0xFD; //RW = 0;
delay_ms(4);
PORTD |= 0x04; //E = 1;
delay_ms(4);
PORTD &= 0xFB; //E = 0;
}
void htoa(byte hh)
{
Data((hh%1000)/100+'0');
Data((hh%100)/10+'0');
Data(hh%10+'0');
}
void main(void)
{
DDRF=0X00; //수광포트
LCD_init();
Command(HOME);
LCD_String("ADC TEST"); // 첫 번째 라인에 출력
SEI();
ADCSRA = 0xaf;
ADMUX = 0x20;
delay_ms(100);
ADCSRA |= 0x40;
}
센서회로도는 아크마님 라인트레이서 회로도를 보고 만들었구요
컴파일러는 icc인데
adc한다음에 adc값을 lcd로 출력하는 프로그램입니다
그런데 adc완료인터럽트는 걸리는것 같은데
막상 값을 출력해보면 adc값이 000으로 나오더라구요
이게 어디가 잘못된건지를 못찾아서 질문올립니다..
제가 좋아하는 컴파일러 중에 하나가 icc입니다^^
전체 소스는 보지 못했구요 님이 말씀하신부분만 봤습니다.
value=ADCH;
Command(LINE2);
htoa(value);
delay_ms(5000);
이런 구문이 있는데요
adc로 값을 받을때는
10비트 모드로 작동시킬때에는 1바이트만으로는 표현할수 없어요
ADCH, ADCL 레지스터에 각각 값이 상위, 하위 바이트로 나뉘어져 저장됩니다.
사용법 예를 들자면
int value;
value = ADCH << 8;
value |= ADCL;
이런식으로 저장을 해야합니다.
그리고 단편적으로 보건데 ADC인터럽트에서 딜레이 함수를 쓰는건 좋지 않습니다..
해보시고 이외에 문제점 있으시면 말씀해주세요...
ADC레지스터 설정부분은 제가 안봤기때문에..
int value;
value = ADCW;
이런식으로 플밍하시면 되겠습니다.
제가 나가봐야 되서 길게 못적어요...수고하세욤
이렇게해서 8비트 ADC를 하려고한건데 잘못한건가요
그리고 INT로 선언해서 오른쪽정렬로 바꾼다음에 value = ADCH << 8; value |= ADCL;
으로 수정하여 실행해도 안되네요 ㅜㅜ
아 뭐가 잘못된건지 모르겠다는..
단계별로 테스트 해보세요.
1. 오실로 스코프로 센서의 출력값을 측정해보세요. 실제 물리적으로 출력값이 나와야 측정이 될테니까요
2. avcc, agnd, aref 단에 배선이 정확이 연결되었는지 확인해보세요.
3. adc인터럽트가 호출된후에 다시 adc 인터럽트를 enable시켜주는 명령어를 해줘야 합니다. 아래 소스에서는 이러한 구문이 없네요.
void adc_isr(void)
{
value=ADCH;
Command(LINE2);
htoa(value);
delay_ms(5000);
}
위 3가지 사항을 잘 확인해보시고
아래 소스는 제가 실제로 구현해서 쓰는 소스입니다.
void adc_isr(void)
{
int value=0;
//conversion complete, read value (int) using...
value=ADCL; //Read 8 low bits first (important)
value|= (int)ADCH << 8; //read 2 high bits and shift into top byte
ADMUX = 0; // adc cheannel select
ADCSRA|=0x40; // adc on
}
제가 icc로 adc할때 주로 쓰는 프로그램 코드입니다. avr128에서 테스트되었으며 잘 작동합니다.^^
ADMUX는 선택받고 싶은 ADC채널입니다(8개중에 선택하는거죠 데이터 쉬트 참조)
답글 달아주신대로 수정해보았지만 ADC값이 계속 000으로 나오네요
밑에는 수정된 소스입니다
#include <iom128v.h>
#include <macros.h>
#define FUNCSET 0x28 // Function Set
#define ENTMODE 0x06 // Entry Mode Set
#define ALLCLR 0x01 // All Clear
#define LINE2 0xC0 // 2nd Line Move
#define HOME 0x02 // Cursor Home
#define DISPON 0x0c // Display On
#define DISPOFF 0x08 // Display Off
unsigned int value;
typedef unsigned char byte;
#pragma interrupt_handler adc_isr:22
void adc_isr(void)
{
value = ADCH << 8;
value |= ADCL;
Command(LINE2);
htoa(value);
ADMUX=0X00;
ADCSRA|=0x40;
}
void delay_us(unsigned char time_us) /* time delay for us 16MHz */
{
register unsigned char i;
for(i = 0; i < time_us; i++) // 4 cycle +
{
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle +
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle +
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle +
}
}
void delay_ms(unsigned int time_ms) /* time delay for ms */
{ register unsigned int i;
for(i = 0; i < time_ms; i++)
{
delay_us(250);
delay_us(250);
delay_us(250);
delay_us(250);
}
}
// LCD 초기화
void LCD_init(void)
{
DDRD = 0xFF; // 포트 D 출력 설정
PORTD &= 0xFB; // E = 0;
delay_ms(15);
Command(0x20);
delay_ms(5);
Command(0x20);
delay_us(100);
Command(0x20);
Command(FUNCSET);
Command(DISPON);
Command(ALLCLR);
Command(ENTMODE);
}
// 문자열 출력 함수
void LCD_String(char *str)
{
while(*str){
Data(*str++);
delay_ms(100);
}
}
// 인스트럭션 쓰기 함수
void Command(byte inst)
{
delay_ms(2);
// 인스트럭션 상위 바이트
PORTD = (inst & 0xF0); // 데이터
PORTD &= 0xFE; //RS = 0;
PORTD &= 0xFD; //RW = 0;
delay_ms(4);
PORTD |= 0x04; //E = 1;
delay_ms(4);
PORTD &= 0xFB; //E = 0;
// 인스트럭션 하위 바이트
PORTD = ((inst<<4) & 0xF0); // 데이터
PORTD &= 0xFE; //RS = 0;
PORTD &= 0xFD; //RW = 0;
delay_ms(4);
PORTD |= 0x04; //E = 1;
delay_ms(4);
PORTD &= 0xFB; //E = 0;
}
//데이터 쓰기 함수
void Data(byte dw)
{
delay_ms(2);
// 데이터 상위 바이트
PORTD = (dw & 0xF0); // 데이터
PORTD |= 0x01; //RS = 1;
PORTD &= 0xFD; //RW = 0;
delay_ms(4);
PORTD |= 0x04; //E = 1;
delay_ms(4);
PORTD &= 0xFB; //E = 0;
// 데이터 하위 바이트
PORTD = ((dw<<4) & 0xF0); // 데이터
PORTD |= 0x01; //RS = 1;
PORTD &= 0xFD; //RW = 0;
delay_ms(4);
PORTD |= 0x04; //E = 1;
delay_ms(4);
PORTD &= 0xFB; //E = 0;
}
void htoa(byte hh)
{
Data((hh%1000)/100+'0');
Data((hh%100)/10+'0');
Data(hh%10+'0');
}
void main(void)
{
DDRF=0X00; //수광포트
LCD_init();
Command(HOME);
LCD_String("ADC TEST"); // 첫 번째 라인에 출력
SEI();
ADCSRA = 0xaf;
ADMUX = 0x00;
delay_ms(100);
ADCSRA |= 0x40;
while(1){};
}
그럴수도 있겠지요..그래서 제가 오실로 스코프로 일단 센서출력을 찍어보라고 위 답변에서 말씀드렸습니다.
기능을 한번에 테스트 하려 하지 마시고 나눠서 테스트를 해보세요
lcd는 잘 작동하나요?/
이 소스 의문되는 상당히 많이 있군요..;;
void htoa(byte hh)
{
Data((hh%1000)/100+'0');
Data((hh%100)/10+'0');
Data(hh%10+'0');
}
이 함수는 왜 byte로 받나요? 2바이트 데이터가 날라오는데요//
256 이상 값이 들어오지도 않는데 1000에 나머지값이라니요..ㅡㅡ;
// 제가 늘 말씀들이자면
하드웨어, 소프트웨어 두가지가 결합된 형태이기때문에
모든것이 생각되로 작동한다고 생각하고 의심되는 부분만을 고치시면 안됩니다.//
기능을 작게 작게 나두고 하드웨어와 소프트웨어로 나눈 후에 각각 확실한 검증을 한 후에
전체 기능을 테스트 해야합니다.
그리고 unsigned int value; 는 초기화를 해주셔야지요 쓰레기값이 들어갑니다..;;
안되는 부분만 질문하지마시고 각각 나눠서 하나하나씩 해보고 안되는 부분을 찾아서 질문을 해주시면 좋겠네요..
회로도도 첨부좀 해주시면 좋겠구요//
----------------------------------------------------------------------------------------------------------
마이크로 프로세서를 응용한 회로에서의 디버깅
마이크로 프로세서를 응용한 회로에서는 하드웨어, 소프트웨어 두가지가 결합된 형태이기때문에
모든 것이 개발자 생각되로 작동한다고 생각하고 의심되는 부분만을 고치시면 안됩니다
하드웨어와 소프트웨어로 나눈 후에 각 기능을 작게 나누고 기능별로 확실한 검증을 한 후에
전체 기능을 테스트 해야합니다.
전반적으로 문제가 있는것을 다른것은 다 잘동작하고 한 부분만 문제가 있다고 생각하시면 큰일납니다.
특히 전체 소스를 자신이 직접 코딩하여 테스트한 것이 아니라 타인의 소스를 응용해서 제작할때에는 더욱 그러합니다.
질문을 하시기전에 위와 같은 점을 한번쯤 점검해보시기 바랍니다.
- by 아크마 -