4월28일 ATMEGA(조도직렬통신) C++(cl /D 옵션 goto continue 등)

2010. 4. 28. 15:452010년/4월

-ATMEGA-
어제에 이어서 조도센서사용과 직렬통신에대해서  한다.
기본적으로  사용하는 내용은 어제와 같다.
#include<avr/io.h> // IO 제어  헤더 파일
#include<clock.h>  //오버플로우 인터럽터 사용
#define CPU_CLOCK 73728000  //MCU의 속도
#define BAUD_RATE 19200  //통신시 이용할 속도
#define BAUD_RATE_L (CPU_CLOCK/(16l*BAUD_RATE))-1 
#define BAUD_RATE_H ((CPU_CLOCK/(16l*BAUD_RATE))-1)>>8
//통신속도의 결과 값을 입력하기 위해   상하위 비트로 구분
//161은 16+L이며, 연산 시  값이  너무 커져 overflow가 발생하므로
//32비트 연산을  위해 16에 Long을 의미하는 l을 붙인다.

void uart_send_byte(unsigned char byte)//1byte 전송 함수
{
  while(!(UCSR0A&(1<<UDRE)));// 전송 버퍼가 빌 때 까지 기다린다.
  UDR0=byte ; //문자 1개를 전송한다.
}
void   LED_init(void)
{
  DDRA=0xFF;
  PORTA=0xFF;


}
void uart_send_string(unsigned char *buf)
{
  int iNum;
  for(iNum=0;iNum<strlen(buf);iNum++)
  {
    uart_send_byte(buf[iNum]);
  }
  uart_send_byte('\r');
  uart_send_byte('\n');
}
void ADC_init(void)
{
  ADMUX=((0<<REFS1)|(0<<REFS0)|(0<<ADLAR));   //전압초기화(REFS17번비트) 아날로그 디지털변환 활성화, 계산활성화(REFS0 6번비트),데이터정렬(ADLAR 5번비트)
  ADCSRA=((1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<ADPS0));  
//ADC허용(ADEN7번비트),프리스케일러 128사용(ADPS2 2번비트)(ADPS1 1번비트)(ADPS0 0번비트)
}
unsigned  int  ADConversion(int ch)
{
  ADMUX=ADMUX|(0<<MUX4|1<<MUX0);    
  //ADC0사용(MUX4~MUX0까지 0넣기 4비트~0비트)
  ADCSRA=(ADCSRA)|(1<<ADSC);  
  //AD변환 시작 ADSC (6번비트사용)
  while(1)
  {
    if(ADCSRA&(1<<ADIF))    
    //AD변환 완료확인 (ADIF 4번비트)
    {
      break;
    }
    
  }
  return ADC;      
//ADCL/H (ADC Data Register)안에있는값을 리턴


}
int main()
{
  
  setTCCR0();
  initTCNT0();
  setTIMSK();
  SREG=0x80;
  unsigned int ch_ADC;
  UBRR0L =(unsigned char)BAUD_RATE_L; //baud rate 설정
  UBRR0H =(unsigned  char)BAUD_RATE_H;
  LED_init();
  ADC_init();
  //parity설정 1stop bit설정,문자사이즈 8bit 설정
  UCSR0C=(0<<UPM1)|(0<<UPM0)|(0<<USBS)|
    (1<<UCSZ1)|(1<<UCSZ0);
  //송신수신 interrupt설정(PORTD27번28번사용), 문자사이즈 8bit설정
  UCSR0B=(1<<TXEN)|(1<<RXEN)|(0<<UCSZ2);
  
  while(1)
  {
    ch_ADC=ADConversion(1);
    uart_send_byte(ch_ADC);//문자 1개를직렬포트로 전송
    if(ch_ADC <100)
    {
      PORTA=((1<<2)|(1<<1)|(0<<0));  //yellow LED ON
    }        
    else if(ch_ADC >=100&& ch_ADC <102)
    {
      PORTA=((1<<2)|(0<<1)|(1<<0));  //green LED ON
    }
    else
    {
      PORTA=((0<<2)|(1<<1)|(1<<0));  //red LED ON
    }  
    sleep(1000);
    asm("NOP");
  }
  
  return 0;
}
DK-128같은경우..  zigbeX같은경우 통신을  위해서 USART가 필요한데  USART0부터 USART4까지 있다 우리가 전에  사용한경우는 USART1을 사용했다. 하지만 zigbeX같은경우 USART0을 사용하기때문에 
UDR1,UCSR1A,UCSR1B,UCSR1C,UBRR1을 전부 0으로 바꾸어야 사용할수 있다. 그리고 조도센서같은경우 우리가 ADC0을 사용하였지만 ADC1로 바꾸고 외부전압으로 REFS1과 REFS0을 값을 0을 넣어야 내부전압으로 변경해서 ADMUX에 넣어야한다.
그리고 직렬통신을 합쳐서 사용하면된다.

-C뿔뿔-
비트 반전 연산자가 있다 여기서 ~ <== tilde라고한다.
컴퓨터에서 연산할때 곱셈같은경우는 대충  14클럭정도 걸리고 덧셋은 1클럭정도 속도차이가 있다. 그래서  비트 시프트연산일경우 7클럭정도 걸린다.  그래서 시프트연산이 곱셈연산과 비슷한데 2진수같은경우는 시프트연산이 속도면에서 유리하다. 이것은 컴퓨터 속도의 최적화하기위해서 하면된다.
#include<stdio.h>
int
 main()
{
   int inum;
   scanf("%d",&inum);
   if(10<inum)
   {
    printf("10보다 크다\n");
   }
   else
   {
    printf("10보다  작다\n");
   }
  (10<inum)?
  printf("10보다 크다\n")
  :  
  printf("10보다  작다\n");
  
   
  return 0;
}
if문과 매우 흡사한 선택문같지만 우리가 보기에는  별로  좋지않다. 필요한경우가 아니라면  사용하지말자 단  이렇게  쓸수도 있다는것을 알아두자
continue의  사용
#include<stdio.h>
int
 main()
{
  int inum=100;
  while(100<=inum)
  {
    scanf("%d",&inum);
    continue;
    printf("나는  천재인가?\n");
  }
  return 0;
}
여기서  continue같은경우 scanf로   입력받을때 밑에 printf문을 생략하고 다시while()조건을 보기때문에 실질적으로 계속 inum에 입력만하고 출력은 없다.

-goto-
goto는  어디 어디로 점프하는것이다 그래서  이쪽저쪽으로  흐름제어지만 이게 많이 사용되면  난잡해지기 때문에 잘안쓴다.
#include<stdio.h>
int
 main()
{  int  inum=0;
  int  isum=0;
  START: //라벨
  if(10<=inum)
  {
    goto   END; //END라벨로 이동
  }
  
  isum=isum+inum;
  ++inum;
  goto  START; //START라벨로이동
  END: //라벨
  /*
  while(10<inum)
  {
    isum=isum+inum;
    ++inum;
  }
  */

  printf("%d\n",isum);


  return 0;
}
-----------------------------------------------
------------------도전문제----------------------
-----------------------------------------------
#include <stdio.h>
#include <string.h>

enum SCA    //열거형 SCA 생성
{
  MON,    //0
  TUE,    //1  
  WED,    //2
  THU,    //3
  FRI,    //4
  SAT,    //5
  SUN,    //6
  END    //7
};
char Day[END][4]=  //END*4크기의 문자배열생성
{
 "MON",
 "TUE",
 "WED",
 "THU",
 "FRI",
 "SAT",
 "SUN",
};
int main()
{
  int inum;  //대문자 소문자 변경을위해 변수횟수
  int inum2;  //문자 비교할 변수횟수 
  int count=0;  //아닐때값찍기
  char cNum[4];  //입력받을값
  scanf("%s",cNum);  //입력

  for(inum=0;inum<4;++inum)
  {  
    if(cNum[inum]>='a'&&cNum[inum]<='z')
    //입력받은값이 소문자일경우 대문자로변경
    {
      cNum[inum]=cNum[inum]-32;
    }
  }
  for(inum2=0;inum2<END;++inum2)  //끝까지  다비교
  {
    if(strcmp(cNum,Day[inum2])==0)  비교한값이 0으로 같으면
    {
      printf("%d\n",inum2+1);  //숫자출력
      count++;  //카운트하나출력
    }
  }
  if(count==0)
  {
    printf("0\n");  //맞는게 없으면 0출력
  }
  return 0;
}

cl  /DDEBUG /P main.c ==>> 실행했을경우
원래 소스는
#include<stdio.h>
//#define DEBUG 1
int main()
{
 #ifdef DEBUG //DEBUG라는 define이 되어있으면 뒤에 printf를 실행하라이다.
 {
  printf("Program start\n");
 }
 #endif
 return 0;
}
하지만 /D(define)DEBUG  <== 즉 /D에 DEBUG붙여서 define하는것이다.
이것이다 그래서  전처리를 문장을 열어봤을때  #include<stdio.h> 빼고  남은 부분인 딱 저부분이다.
int main()
{
 
 {
  printf("Program start\n");
 }
 #line 10 "main.c"
 return 0;
}
cl /D 옵션은 말그래도 define을 하는것이고 뒤에  define 명을 적어주면된다.
gcc --save-temps -o  main.i main.c (gcc 중간파일 생성)


 


ATMEGA에서는  MakeFile을 사용하여 Make할때 일단 기본적으로 make clean을 해야한다. 하지만  MakeFile을 이용해서  define하는데 저 빨간부분이 아까 바꾼  클럭수인데 -D 옵션으로 사용해서 먼저define한다는것을 알수있었다.
MakeFile을  자세히 보면  된다.