아래는 atmega led를 깜박이는 소스이다. 이 소스에서 완성.
이 방법은 timer counter를 이용하지 않고 시간을 지연하기 위한 것. 시간의 지연시키는 것을 모니터링
하기 위해 오실로스코프를 사용하였다.
#define DDRA (*((volatile unsigned char *)0x21))//DDRA define PORTA (*((volatile unsigned char *)0x22))//atmegat의 portA부분의 주소를 정의. 데이터시트 참고
void my_msdelay(unsigned int uiMs);//함수 원형.
int main(void) { volatile unsigned int iCnt2; volatile unsigned int iCnt1; DDRA= 0xFF;//8비트 모두 활성화. PORTA=0xFF;//8비트 모두 활성화.
while(1) { my_msdelay(1000);//delay 함수 인자를 m/s단위의 시간.
// for(iCnt1=0;iCnt1<790;iCnt1++);//0.001초지연. //for(iCnt2=0;iCnt2<10;iCnt2++); PORTA=0x00;//A의 0을 넣어 led를 끄게 하기 위한 코드. 위아래코드가 while문에 의해 반복되면서 led를 깜박인다. my_msdelay(1000); //for(iCnt1=0;iCnt1<790;iCnt1++); //for(iCnt2=0;iCnt2<10;iCnt2++); PORTA=0xFF;
} while(1); return 0; }
void my_msdelay(unsigned int uiMs)//인자 uiMs는 말그대로 m/s단위의 시간을 뜻함. { volatile unsigned int iCnt; while(uiMs>0) { --uiMs; for(iCnt=0;iCnt<792;++iCnt);//0.001초지연. 인자로 1000을 받는다면 1000번 실행한다. 이것이 1초가 된다. } } 원래 반복문에서 for문은 이중for문이 2개가 존재하였다. 하나는 LED꺼진 상태와 켜진 상태.
for(iCnt1=0;iCnt1<790;iCnt1++);//0.001초, 즉, 1ms로 맞추기 위하여 숫자를 최대한 낮추어가면 맞춘다. 파형의 high,low값을 맞추는 작업이다. 위아래 보이는 숫자는 790은 어느정도 맞춘 상태.
//for(iCnt1=0;iCnt1<790;iCnt1++);
그리고 함수 my_msdelay함수를 만들어 위에 셋팅한 for문을 비교한다. 그러면 아래와 같은 코드가 된다.
my_msdelay(1); //for(iCnt=0;iCnt<790;++iCnt);my_msdelay(1)함수와 맞추기 위해서 주석처리. //for(iCnt=0;iCnt<1000;++iCnt) 이 부분은 필요없으로 주석처리.
for(iCnt=0;iCnt<790;++iCnt); //for(iCnt=0;iCnt<100;++iCnt); 이 부분은 필요없으로 주석처리.
my_msdelay(unsigned int uims) { volatile unsigned int iCnt; while(uims>0) { --uims;//while문을 탈출하기 위하여 증감한다. 예를 들어 uims가 3인 경우 아래 for문이 3번 돌고 while문이 //탈출된다. for(iCnt=0;iCnt<790;++iCnt);//ATMEGA는 16비트이므로 최대 수치가 65535이다 그냥 단순히 for문만을 //돌리면 최대치가 넘어서 제대로 출력을 할 수 없으므로 while문을 썼다. } }
아니면 변수 iCnt를 long형으로 바꾸는 방법도 있다.
|