SW 개발

[AVR펌웨어] GPIO 로 spi 컨트롤하기 / DS1302 컨트롤 (예제소스)

. . . 2011. 12. 2. 14:51
반응형

출처 : 이전에 정리했던 소스...

  • avr의 spi기능을 이용하지 않고 일반 gpio로 spi를 구현
  • 칩드라이브의 예는 ds1302를 이용하도록 한다.

DS1302 컨트롤

일단... 위의 그림은 ds1302의 데이터 시트이이다.

  • 다들 알고 있듯이 칩에 데이터를 읽고 쓰기 위해서는 미리 데이터 버스에 데이터를 날려주고 컨트롤 신호를 쏴주면 된다.

이사항을 위의 그림과 연결해보자.

미리 해당핀(io핀)을 hi/low 로 만들어 놓고 sclk핀의 신호를 hi/low 를 만들어주면 해당 io선으로 데이터가 들어가게 된다. 

sclk의 신호를 만들때 avr의 gpio를 이용할수있다. 단순히 출력핀을 hi => low => hi 로 변환시키면 한개의 클럭이 만들어진다. 이때 hi => low 로 변화시에 딜레이를 주면 원하는 클럭을 만들수있다.

(즉 주파수를 변화시킬수있는것 같다;;)

여기서 중요한것은 첫번째 그림에서 나온 타이밍도이다. spi 로 칩을 컨트롤 할때 다들 해당되는 얘기인데.. 데이터시트를 보면 첫번째 그림같은것은 꼭 있던것 같다. 즉.. 클럭으로 인식하는 hi유지시간 low유지시간등등... 이 기록되어있다.

gpio spi 통신하기

그럼 spi통신을 하기위한 코딩순서를 함 보자.

1. 쓰려고 하는 i/o 핀들의 입출력설정

#define DS1302_DDR_SET() (sbi(DDRE, 4), sbi(DDRE, 3), sbi(DDRE, 2))

일단, DS1302를 사용하기 위해 위와같이 기본적인 설정을 한다.

참고로 sbi 와 cbi의 기본적인메크로는 다음과 같다.

#define sbi(ADDRESS,BIT)    (ADDRESS |= (1<<BIT))
#define cbi(ADDRESS,BIT)    (ADDRESS &= ~(1<<BIT))
#define bit(ADDRESS, BIT)    (ADDRESS&(1<<BIT))

이때.. 컴파일러에서 해당 메크로들을 지원할지 모르니 ifdef로 빼주면서 코딩하면될듯..

2. ds1302 쪽으로 cs(chip select)신호를 보낸다.

위의 첫번째 그림을 보면 알겠지만... 모든 신호들 전에 먼저 cs신호가 hi로 변하는걸 볼수있다

#define DS1302_CS_ENABLE()  (sbi(DDRE, 4), sbi(PORTE, 4) )  // active low 
#define DS1302_CS_DISABLE() (sbi(DDRE, 4), cbi(PORTE, 4) )  

3. 데이터를 보낸다. / 클럭을 보낸다.

해당 칩으로 데이터를 보낼때는 비트를 한개씩 보내게 된다.

for(i=0;i<=7;++i) 
{
   if(cmd&msk)
       DS1302_MOSI_HI(); //sbi(PORTC, 5); //output_bit(RTC_IO, shift_right(&cmd,1,0) );
   else
       DS1302_MOSI_LO(); //cbi(PORTC, 5);
   DS1302_SCK_HI(); //sbi(PORTA, 0); // PB1==SCK //output_high(RTC_SCLK);
   delay_us(2); // if need delay
   DS1302_SCK_LO(); //cbi(PORTA, 0); // output_low(RTC_SCLK);
   delay_us(2); // if need delay
   msk<<=1;
}

코딩스타일은 간단하다.

  • 한개씩 보내야 하므로,, 8개의 비트중에 한개 비트를 msk 씌워서...
  • 해당 데이터가있을때 해당 핀을 hi로 해놓고 클럭인가..
  • 해당 데이터없을때 해당 핀을 low로 해놓고 클럭인가..

위의 소스를 보면 충분히 이해가 갈것이다. 위의 내용들을 총 종합하여.. ds1302에 데이터를 날려주는 코드를 짜보면.. 아래와 같다.

#define DS1302_DDR_SET()    (sbi(DDRE, 4), sbi(DDRE, 3), sbi(DDRE, 2) )  
#define DS1302_CS_ENABLE()  (sbi(DDRE, 4), sbi(PORTE, 4) )  // active low 
#define DS1302_CS_DISABLE() (sbi(DDRE, 4), cbi(PORTE, 4) )  
#define DS1302_MOSI_HI()    (sbi(DDRE, 3), sbi(PORTE, 3) )
#define DS1302_MOSI_LO()    (sbi(DDRE, 3), cbi(PORTE, 3) )
#define DS1302_IO_AS_INPUT()   (cbi(DDRE, 3),cbi(PORTE,3))
#define DS1302_IO_AS_OUTPUT()  (sbi(DDRE, 3),sbi(PORTE,3))


void write_ds1302_byte(u08 cmd) 
{
   u08 i;
   u08 msk = (u08)0x01; // ds1302는 LSB부터 보낸다? 
   DS1302_DDR_SET();
   DS1302_CS_ENABLE();
   DS1302_IO_AS_OUTPUT();  

   for(i=0;i<=7;++i) 
   {
      if(cmd&msk)
          DS1302_MOSI_HI(); //sbi(PORTC, 5); 

      else
          DS1302_MOSI_LO(); //cbi(PORTC, 5);
      DS1302_SCK_HI(); //sbi(PORTA, 0); // PB1==SCK //output_high(RTC_SCLK);
      delay_us(2); // if need delay
      DS1302_SCK_LO(); //cbi(PORTA, 0); // output_low(RTC_SCLK);
      delay_us(2); // if need delay
      msk<<=1;
   }
}

일단 ds1302는.. 맨처음에 커맨드 8비트를 날려주고 그다음에.. 데이터를 날려주는 형식으로 통신을 한다.

반응형