2015-02-15

LED로 꾸미는 연말연시 트리 [강의] 의문사항 및 질문사항

AVR  연습하면서 질문으로 작성했던 부분을 정리하였습니다. 

자료 출처: http://cafe.naver.com/lazydigital/



안녕하세요, 반갑습니다. 오늘 1.3 강의를 보게되어 rand()함수에 대해 알게 되었습니다.

아래는 제가 강의 보며 작성자님께서 이야기하신 조건을 토대로 작성하여 보았습니다.

#include <avr/io.h>       // atmel studio 에서 사용할 avr i/o 포트, 레지스터에 대한 정의 헤더 파일
#define F_CPU 16000000UL  // 16MHZ를 사용, delay라이브러리 함수 사용시 반드시 선언되야함. (default 1000000UL 헤더에 되                                         //  있음) UL:unsigned long (4byte :32bits) 양수(0~4,294,967,295)
#include <stdlib.h>       // 랜덤함수 rand() 사용시 선언하는 라이브러리 헤더파일
                                 // rand()함수의 RAND_MAX값은 헤더파일에 그값이 0x7FFF (32767) 값이며 MIN값은 0부터라고 주석됨                                  // extern int rand (void); 로 함수가 정의되어 있음
#include <util/delay.h>    // atmel studio 에서 기본적으로 제공하는 _delay_ms(), _delay_us() 함수 사용시 F_CPU를 꼭 정의.

void time_sec(unsigned int sec){   //사용자 정의 딜레이용 함수

 volatile int i;              // 최적화 하지마세요(?) int형i.j; atmega128은 int형을 보통 2byte 처리(?) (-32768~32767) 까지 i,j                                          //에 표현가능
 for (i=0;i<sec;i++)       // 함수 호출시 받아 오는 변수값 sec 형태는 unsgined 양수형 int 변수 (0~65535) 까지 표현가능
 {
  _delay_ms(1);      // 1/1000 sec 제공되는 라이브러리 함수를 헤더파일로 포함시켜 헤더파일의 함수를 사용 F_CPU                                          //  값을 사용하여 계산함
 }
}


int main(void)            // 메인 함수
{
   unsigned char i;       // 양수형 1byte (8bits) 로컬 변수 i; 표현수(0~255)
    int t;                      // 2byte (16bits) 로컬 변수 t; 표현수(-32,768~32,767)
   DDRA = 0xff;           // 사용할 PORTA의 입출력 상태를 선택 all bits set "1" 로 모든 비트를 출력으로 이용.
   PORTA = 0x00;          // PORTA의 초기 출력 상태를 "0"으로 clear.
    while(1){             // 무한 루프 ex)for(;1;);,for(;;);,do{}while(1)..등등.
       
        i= rand()%256;     // rand() 값은 0~32767 값이 랜덤하게 발생 이값을 8bits의 표현값 범위안으로 변형 0~255    
        PORTA = i;          // rand()/256값이 몫이아닌 나머지 값은 0~255까지 rand()값의 임의                    
                                 //변화하는 분포값에 (255~0 순환)
                          // 대응하여 0~255의 나머지값으로 대응됨.
                   // PORTA에 이값을 입력하여 출력시킴.

 t= ((rand()%50)+1)*100;   // 변수 t 의 입력범위값은 (100~5000) 이므로  int 변수t 로 따로 선언.            
        time_sec(t);             // 점등 지속시간또한 랜덤하게 설정. 시간의 범위가 0.1sec~ 5sec(0.1~1:10ea,1.1~2:10ea,                                                  // 2.1~3:10ea, 3.1~4:10ea 4.1~5:10ea)
                                      // time_sec() 함수 입력범위는 100,200,300,400 ~1100,1200~ 5000. 50단계.
                 // 변수범위가 0~49까지의 범위에서 수식을 더해 ((0~49)+1)*100 으로 표현가능
                                      // 0~49까지 만의 표현범위만을 표시하기 위해서는 rand()%50
          // 값을 입력하여 (최대값대응: 17~0), (49~0:순환) 까지의 범위만을 갖는 변수를 입력
 }                    

}

질문1)) rand()함수에 대한 부분인데요, rand()함수 코드에 보면 두번 등장합니다. 이 함수값에 랜덤하게 나오는 (0~32767)
           값은 코드가 진행되면서 순차적으로 호출될때마다 서로 다른값을 생성하여 전달하는지 궁금합니다.
           PORTA에 호출되서 전달되는 랜덤 값과 변수t에 계산전에 전달되는 랜덤값은 다른값인가요?

질문2)) 제가 작성한 코드에 대한 부분입니다. 강의 내용을 보면서 좀 의아한 부분이나 오타인 부분인가 싶어서
이렇게 질문드립니다.
         
1. 강의 내용중에 "즉, rand( )%256 의 결과는 rand( )의 결과인 0~0x3fff 값을 256으로 나눈 나머지가 되므로 항상 0~255의 랜덤한 값으로 한정되어 나타나는 것이지요. " 라는 부분이 있는데요 0x3fff 은오타가 아니신지 혼동됩니다.  
0x7fff 값을 256으로 나눈 나머지 값이 0~255 의 랜덤값에 대응 한다고 생각하고 있는데 제가 잘못이해하거나 이해하지못한 부분이 있는지 알려 주시면 감사하겠습니다.

2. 강의 내용중 100, 200, …, 50000의 값을 가져야 하므로 rand( )%50을 수행하여 0~49까지 정수값으로 한정하게 하고, 여기에 1을 더한 후(1~50값을 가져야 하므로) 여기에100을 곱하면 원하는 ? 값인 100, 200, …, 1000, 1100, …, 50000의 값만 얻게 되므로 결과적으로는 0.1초 ~ 5.0초까지의 50가지 값만 얻을 수가 있겠습니다.
요부분은 강의 내용에 알려주신 공식 값에서 시간 0.1~5초 사이의 범위값(1~50)에 대응 하는것으로 보이는데 100~50000은 1~500을 나타내고 있는것 같아서 지정한 시간 값과 맞는것 같지않아 보입니다.

질문3)) 마지막으로 제가 시간 0.1~5초 사이를 가정하고 랜덤하게 시간 delay를 거는 조건을 충족시키기 위해 위와 같이 작성햇는데 의도한 범위내에서 시간값이 만들어져 들어가는지 궁금합니다. 바로 딜레이 함수를 사용하려 했는데 라이브러리 딜레이 함수는 받는 인자값으로 상수값 이외에는 않받는 것 같아서 위처럼 사용자 함수를 만들어 안에 라이브러리 delay함수를 넣어 사용하였습니다. 사용자함수에 들어가서 시간 딜레이를 걸때 만든 딜레이1초가 실제 코드에서 바로 1초를 걸어서 쓰는것과 차이가 날거 같은데 이점도 다른 형태로 표현하거 염두해두고 있어야 할부분이 있다면 알려주시면 감사하게씁니다.

질문4)) 하드웨어 부분인데요 강의 내용중에 이런부분이 있었습니다 atmega128은 int 형 변수를 2byte처리한다는 내용을
본 기억이 나서 여쭈어봅니다. 보통 c언어를 시작하면서 가장 처음 접하는것이 데이터형식범위 변수의 형인데요.
많이 봐오던 int형이었는데 4byte라고 생각했었는데 2byte 처리한다는 내용은 atmega128 만 이렇게 처리하는건지 궁금합니다.

제가 질문한것 이외에도 강의 특성상 이런부분에선 이런점들을 꼭 생각하거나 염두해둬야 하는부분이 있다면 알려주시면 감사하겠습니다,  제가 알고있는부분이 많지않고 이해하는부분이 적어 물어볼 질문을 생각하지 못하고 가는부분이 더 많다고 항상 느끼고 있습니다.
항상 느끼는 부분이지만 알면 알수록 질문거리들이 눈에 보이고 늘어나는건 배우는 입장에서는 참 즐거운것 같습니다.


자료 출처: http://cafe.naver.com/lazydigital/ 작성자:임베디드홀릭


질문1)) rand()함수에 대한 부분인데요, rand()함수 코드에 보면 두번 등장합니다. 이 함수값에 랜덤하게 나오는 (0~32767)
값은 코드가 진행되면서 순차적으로 호출될때마다 서로 다른값을 생성하여 전달하는지 궁금합니다.
PORTA에 호출되서 전달되는 랜덤 값과 변수t에 계산전에 전달되는 랜덤값은 다른값인가요?

=> rand 함수는 호출마다 서로 다른 값이 리턴됩니다. 하지만 실제 random과는 다른걸 아셔야 합니다.
rand 함수는 각 숫자의 발생 확률이 고르게 분포되어서, 1다음에 1이 나올 수 없습니다
(좁은 범위를 한정하도록 % 로 범위를 줄이면 발생할 수도 있지만)..


1. 강의 내용중에 "즉, rand( )%256 의 결과는 rand( )의 결과인 0~0x3fff 값을 256으로 나눈 나머지가 되므로 항상 0~255의 랜덤한 값으로 한정되어 나타나는 것이지요. " 라는 부분이 있는데요 0x3fff 은오타가 아니신지 혼동됩니다.
0x7fff 값을 256으로 나눈 나머지 값이 0~255 의 랜덤값에 대응 한다고 생각하고 있는데 제가 잘못이해하거나 이해하지못한 부분이 있는지 알려 주시면 감사하겠습니다.
=> 만약 rand가 32767이 최대라면 0x7fff 가 최대 맞습니다.
winavr에서 rand 함수의 범위를 한번 찾아보겠습니다.
)

2.위를 보면 5000 까지라고 코멘트 되어 있는것 같은데요?

그리고 범위가 넓어서 큰 차이가 안나긴 하지만
0 ~ 0x7fff 까지 값을 %50 으로 하면 0~49 가 확률적으로 동일하지는 않겠죠.
rand가 범위가 크고 % 로 나머지 구하는 범위가 좁을때는 무시할 정도가 되겟지만
0 ~ 15 (2진 레지슽의 끝은 2^N - 1로 끝남)을 5로 나누는 연산을 한다면
나머지 0 : 4경우
나머지 1 : 3경우
나머지 2 : 3경우(2,7,12)
나머지 3 : 3가지
나머지 4 : 3가지

나머지 0인 경우가 4/16

이런것까지 고려해야 하는 경우도 있긴 합니다..

질문 3)
winavr을 새로운 버젼 winavr-20100110(?) 버젼을 따로 설치후
프로젝트 옵션으로 외부 컴파일러 사용하도록 지정하면 됩니다.
avrstudio와 같이 설치되는 toolchain은 말씀하신것처럼 _delay_ms/us 함수가 상수인자만 받습니다.

질문4)
예전에는 8비트 cpu에서 int 가 8비트인 경우도 경험한 적이 있습니다.

int 는 해당 칩(cpu)가 가장효율적으로 처리하는 수형이라고 하긴 하지만 8비트에서는 예외입니다.

winavr/codevision 등의 기본 int 수형은 2바이트 이고
32비트 processor 들은 기본 int 수형이 4바이트 입니다.

avr에서는 가장 효율적인 수형은 8비트입니다.
32비트 칩에서는 기본 수형이 작다고 유리하지 않습니다.

따라서
가능하면 avr에서는
unsigned char 수형을 사용하는게 유리합니다.


No comments:

Post a Comment

Total Pageviews