HW 기초

FirmWare / AVR / 간단소스 / 시리얼 통신관련..(쉘만들기 기초)

. . . 2013. 12. 19. 16:24
반응형

이전에 프로젝트 했던걸 정리하는 차원에서 포스팅...

펌웨어 시리얼 통신

쉬운 예제가 이해하기 제일좋다.

통신초기화 관련 예제코드

void uart0_init(u32 baud)
{    
  /*================================
    BAUD = F_CPU / (16 * (UBRR + 1) )
    UBRR = (F_CPU / (16L*baud)) - 1
  ==================================*/

   baud = (F_CPU / (16L*baud)) - 1;    
// buad 로 인자로 받아온 buad로 초기화..

  //uart1 register baud setting
   UBRR0H = (u08)(baud>>8);            // 클경우 상위 8bit만 잘리기에..
   UBRR0L = (u08)(baud);

   DDRE=0xFE;     // PE1(TXD) 출력(1), PE0(RXD) 입력(0)

   UCSR0A=0x00;
  // UCSR0B=0x18;   // Receive enable, Transmitte enable
  // UCSR0C=0x06;   // 비동기 방식, No parity bit, 1 stop bit   

//   UBRR0H=0x00;
//   UBRR0L=0x67;   // 16MHz에서 9600 bps  (10진수 103)

    // UCSR0B 설정
    // bit7:수신완료 인터럽허용 , 
    // bit6:송신완료 인터럽허용, 
    // bit4:uart rx enable, 
    // bit3: uart tx enable
    // bit2 : sendding size setting UCSR0C 같이 설정 => 0 : 8bit
    // 11011000 

    UCSR0B = (1<<7) | (1<<6) | (1<<4) | (1<<3) | (0<<2) ; // 00011000 

    // UCSR0C 설정
    // bit6 : synchro setting => 0: dissynchro mode
    // bit5,bit4 : parity bit setting => 00 : not used
    // bit3 : stop bit setting => 0 : stop bit 2 use
    // bit2,bit1 : data sendding size => 11 : 8bit
    // 00001010

    UCSR0C = (0<<3) | (1<<2) | (1<<1) | (0<<5) | (0<<4);

}
  • iar 컴파일러 기준이다.
  • 해당 시리얼을 위와 같이 코딩하면 될듯하다.
  • 자세힌 모르겠는데.. 보우레이트 계산에서 틀리게 들어갈수도있으니.. 안되면 직접 공학용계산기 뚜드려서 상수로 넣을것! 한번 위의 수식이 안되서... 직접때러넣으니 통신 성공한적도있음

간단한 printf 대용으로 구현

int getchar(void)
{
  // UCSRnA 
  // bit7 : 버퍼에 수신문자 있으면 1

   while (!(UCSR0A & 0x80))        // 
         ;   //wait for character
   return ((int) UDR0 & 0xFF);  //grab character 
}

int putchar(int ch)
{
  // UCSRnA 
  // bit5 : 송신 버퍼가 비어서 데이터를 받을 준비되면 1

   while (!(UCSR0A & 0x20))
      ;    //wait xmit ready
   UDR0 = (unsigned char) ch;
   return (ch);                 //send the character
}

void SendString(char *buf)
{
  int i;
  for(i=0; i<strlen(buf); i++)
  {
      if(buf[i]==0)
       break;
      putchar(buf[i]);
  }
}
  • iar 기준이다.
  • printf 를 사용하기전에 간단히 위와같이 해서 사용하면 될듯

avr에서 쉘만들기

#pragma vector = USART0_RXC_vect 
// 비동기 uart 통신위해서 송신측 인터럽 사용
__interrupt void usart0_rxc(void)
{
    __disable_interrupt();
    u16 i;
    u08 dummy;

 //  UCSR1A &= ~(1<<7);  // 인터럽트 플래그 해제 
    //while(!(UCSR1A&(1<<7))); // 데이터 기다린다. 

    dummy = UDR0; // 인터럽트 발생시에 일단 i/o 레지스터의 값을 읽어온다.
                  // usart0 !!!!

    buf_rx0[rx0_head] = dummy;    
    // 그리고 버퍼에 저장시키고

    rx0_head = (rx0_head+1)%BUF_SZ;     
    // 다음 저장을 위해.. 하개 증가시킨다. 단 버퍼의 최대 사이즈는 판별할것

    // 엔터를 쳤을때 커맨드로 인식, cmd1 측으로 명령어 string 보낸다.
    // 0x0d : carriage return , 0x0a = newline
    if(dummy==0x0d || dummy==0x0a) 
    {
        for(i=0; i<CMD0_SZ && rx0_tail!=rx0_head; rx0_tail=(rx0_tail+1)%BUF_SZ, i++)
            cmd0[i] = buf_rx0[rx0_tail];    
        // 차례대로 다시 커맨드배열로 정렬

        cmd0[i-1] = 0; // 마지막에 리턴 문자 제거후 완전한 str만듬

        cmd0len = i-1;
        //for(; i<CMD0_SZ; i++)
        //      cmd0[i] = 0;

        if(i>0)
            cmd0f = 1; // 여기서만 set 
            // setting cmd string input flag --> ParseCmd check 
    }
//    putchar(dummy); // receive echo   
    __enable_interrupt();
}
  • iar 기준이다.
  • uart 인터럽 핸들러를 이용한다.
  • isr에서 전역으로 선언된 배열에 하나의 캐릭터가 들어올때마다 때려넣는다..
  • 엔터 / 탭 등이 들어오면.. 하나의 명령어로 인식을 한다. => 플래그 세팅
  • 명령어로 인식하자마자.. 커멘드를 새로 정렬해서 strcmp 하기 쉽게 한다. (전역으로 선언된 배열에 캐릭터를 하나씩 때려넣을때 반대로 들어가있기때문..ㅋㅋ)
  • main 코드에서는 명령어들어왔을때의 플래그를 매번 검사
  • 플래그 세팅시에 커맨드가 저장된 배열을 비교하면서 해당루틴으로 분기

참고. 고급 printf 구현..

출처 : http://kldp.org/node/23207

임베디드 환경에서의 printf 구현이 쉽지는 않다. 아래와 같은 코딩으로 불편하나마 printf()를 대체하여 쓸수가 있다.

C 함수의 호출 원리를 이용한 sprintf() 의 약식 구현 이다. va_start() 나 va_end() 함수를 사용하여 구현할 수도 있지만, 이것도 stack의 동작을 숨기고 있어서 좀더 low level 로 구현하고자 한다.

스텍이나 메모리 상황이 안좋거나.. 타겟쪽에 라이브러리를 올리지 못하는 상황이라면 아래와같이 코딩하여 사용할수있을것이다.(컴파일이 된다면..) 소스원작자는 32bit ARM에서 target에 printf()관련 라이브러리를 통째로 올릴수없어서 코딩하였다고 한다.

/*+-------------------------------------------------------------------------+
  |  FILE: sprintf.c                                                        |
  |  Version: 0.1                                                           |
  |                                                                         |
  |  Copyright (c) 2003 Chun Joon Sung                                      |
  |  Email: chunjoonsung@hanmail.net / 
  +-------------------------------------------------------------------------+*/

char *itoa( char *a, int i)
{
    int sign=0;
    int temp=0;
    char buf[16];
    char *ptr;

    ptr = buf;

    /* zero then return */
    if( i )
    {
        /* make string in reverse form */
        if( i < 0 ){ 
                    i = ~i + 1; 
                    sign++; }

        while( i ){ 
                    *ptr++ = (i % 10) + '0'; 
                    i = i / 10; }

        if(sign)
            *ptr++ = '-';

        *ptr = '';

        /* copy reverse order */
        for( i=0; i < strlen(buf); i++ )
            *a++ = buf[strlen(buf)-i-1];
    }    
    else
        *a++ = '0';

    return a;
}

char *xtoa( char *a, unsigned int x, int opt)
{
    int i;
    int sign=0;
    int temp=0;
    char buf[16];
    char *ptr;

    ptr = buf;

    /* zero then return */
    if( x )
    {
        /* make string in reverse form */
        while( x )
            { *ptr++ = (x&0x0f)<10 ? (x&0x0f)+'0' : (x&0x0f)-10+opt; x>>= 4; }

        *ptr = '';

        /* copy reverse order */
        for( i=0; i < strlen(buf); i++ )
            *a++ = buf[strlen(buf)-i-1];
    }
    else    
        *a++ = '0';

    return a;
}

long _sprintf(buf, format, arg)
char *buf;
char *format;
long  arg;
{
    int cont_flag;
    int value;
    int quit;
    char *start=buf;
    long *argp=(long *)&arg;
    char *p;

    while( *format )
    {
        if( *format != '%' )    /* 일반적인문자*/
        {
            *buf++ = *format++;
            continue;
        }

        format++;                /* skip '%' */

        if( *format == '%' )    /* '%' 문자가연속두번있는경우*/
        {
            *buf++ = *format++;
            continue;
        }

        switch( *format )
        {
            case 'c' :
                *buf++ = *(char *)argp++;
                break;

            case 'd' :
                buf = itoa(buf,*(int *)argp++);
                break;

            case 'x' : 
                buf = xtoa(buf,*(unsigned int *)argp++,'a');
                break;

            case 'X' : 
                buf = xtoa(buf,*(unsigned int *)argp++,'A');
                break;

            case 's' :
                p=*(char **)argp++;
                while(*p) 
                        *buf++ = *p++;
                break;

            default :
                *buf++ = *format; /* % 뒤에엉뚱한문자인경우*/
                break;
        }

        format++;
    }
    *buf = '';

    return(buf-start);
}

main()
{
    char buf[80];

    _sprintf( buf, "%d, %x, %X, %sn", 1234, 0xabcd, 0xabcd, "abcd"); 
    puts(buf);
}

반응형