전자회로실험

LED 속도 변화
어제 실험에서는 주기적인 시간에 따라 LED를 On/Off시키는 코드를 작성해 보았다. 오늘은 이 LED On/Off를 시간을 동적으로 바꾸어 보는 코드를 작성했다.

port.h파일

#define PINA  (*(volatile unsigned int *)0x39)
#define DDRA  (*(volatile unsigned int *)0x3A)
#define PORTA  (*(volatile unsigned int *)0x3B)

#define PINB  (*(volatile unsigned int *)0x36)
#define DDRB  (*(volatile unsigned int *)0x37)
#define PORTB  (*(volatile unsigned int *)0x38)

#define PINC  (*(volatile unsigned int *)0x33)
#define DDRC  (*(volatile unsigned int *)0x34)
#define PORTC  (*(volatile unsigned int *)0x35)

#define PIND  (*(volatile unsigned int *)0x30)
#define DDRD  (*(volatile unsigned int *)0x31)
#define PORTD  (*(volatile unsigned int *)0x32)

#define PINE  (*(volatile unsigned int *)0x21)
#define DDRE  (*(volatile unsigned int *)0x22)
#define PORTE  (*(volatile unsigned int *)0x23)

#define PINF  (*(volatile unsigned int *)0x20)
#define DDRF  (*(volatile unsigned int *)0x61)
#define PORTF  (*(volatile unsigned int *)0x62)

main.c파일

#include "port.h"

int main(void)
{
  unsigned int us = 0;    // 10^-6
  unsigned int ms = 0;  // 10^-3
  int flag = 0;
  int t = 2000;  // 
시간 변화를 주기 위한 변수

  DDRC = 0xFF;

  while(1)
  {
    us++;
    if(us >= 1000)
    {
      ms++;
      us = 0;
    }
    if(ms >= t)
    {
      if(flag)
      {
        PORTC = 0x00;
        flag = 0;
      }
      else
      {
        PORTC = 0xFF;
        flag = 1;
      }
      ms = 0;
      t -= 100;
      if(t == 0)
      {
        t = 2000;
      }
    }
  }

  return 0;
}
//
변수 t 이용하여 LED on/off 마다 t값을 줄여줌으로써 on/off 주기가 점점 짧아진다. 변수 t 0 되면 다시 2000으로 초기화하고 다시 반복한다.

PINx
PINx 레지스터는 I/O핀이 입력으로 사용될 경우 핀에 입력된 데이터를 읽어 오는 레지스터이다. 이 PINx를 직접 사용해보았다.

main.c 파일

#include "port.h"

int main(void)
{
  DDRC = 0x01;  // C
 01번을 출력으로 설정
  PORTC = 0x01;  // C
 01번에 High 출력

  DDRD = 0x00;  // D
핀을 입력으로 설정
  PORTD = 0x00;  // D
 초기화

  PORTF = 0x00;  // F
 초기화

  while(1)
  {
    if(PIND & 0x01)  // D
 01번에 High신호가 들어오면
    {
      DDRF = 0xff;  // F
핀에 High 신호 출력
    }
    else
    {
      DDRF = 0x00;  // F
핀에 Low 신호 출력
    }

  }
  return 0;
}
// F
핀에는 LED 연결시켜놓고, C 01번을 D 01번으로 연결시키면 F에서 출력이 나오므로 LED 불이 들어오는 것을 있다.

switch누름에 따라 LED on개수변화
#include
 "port.h"

int main(void)
{
  DDRC = 0x00;  //switch input
  PORTC = 0x00;

  DDRF = 0xFF;  //LED output
  PORTF = 0xFF;

  while(1)
  {
    if((~PINC) & 0x01)    // 1
 스위치가 눌러 졌을 
    {
      PORTF = ~(0x01);
    }
    else if((~PINC) & 0x02)  // 2
 스위치가 눌러 졌을 
    {
      PORTF = ~(0x03);
    }
    else if((~PINC) & 0x04)  // 3
 스위치가 눌러 졌을 
    {
      PORTF = ~(0x07);
    }
    else if((~PINC) & 0x08)  // 4
 스위치가 눌러 졌을 
    {
      PORTF = ~(0x0F);
    }
    else if((~PINC) & 0x10)  // 5
 스위치가 눌러 졌을 
    {
      PORTF = ~(0x1F);
    }
    else if((~PINC) & 0x20)  // 6
 스위치가 눌러 졌을 
    {
      PORTF = ~(0x3F);
    }
    else if((~PINC) & 0x40)  // 7
 스위치가 눌러 졌을 
    {
      PORTF = ~(0x7F);
    }
    else if((~PINC) & 0x80)  // 8
 스위치가 눌러 졌을 
    {
      PORTF = ~(0xFF);
    }
    else
    {
      PORTF = 0xFF;
    }
  }
  return 0;
}
// switch
입력 받은핀 : PORTC // LED 출력핀 : PORTF
// switch
회로도를 보면 스위치가 눌려 졌을 Low 신호가 입력 된다. 그러므로 C 입력을 보수 연산을해서 어느 핀이 눌러 졌는가 확인하고, 이에 따라 LED On 개수를 정하고 F핀으로 출력 하였다.

 

C언어

Big Endian & Little Endian


정수 0x12345678가 실제 메모리에 저장 되는 방식에는 Big-Endian과 Little-Endian방식이 있다. Big-Endian의 의미는 정수의 끝부분 메모리 주소가 크다는 의미이고, Little-Endian은 정수의 끝부분의 메모리 주소가 작다는 의미다.

일반적인 인텔x86계열 cpu들은 Little-Endian방식을 채택하고 있는데, Little-Endian 방식은 메모리 첫 부분에 바로 정수의 끝자리가 오기 때문에 산술연산이 간단해지는 장점이 있다. 반면 끝부분이 앞에 오기 때문에 대수비교에 약점이 있다.

main.c파일

#include <stdio.h>

int main()
{
  int iNum = 0x12345678;
  int *iP = &iNum;

  printf("iNum address: %08x\n"&iNum);
  printf("iP   address: %08x\n"&iP);
  printf("iNum   value: %08x\n", iNum);

  *iP = 0x77777777;
  printf("iNum   value: %08x\n", iNum);

  *((int *)0x12ff7c) = 0x99;
  printf("iNum   value: %08x\n", iNum);
  
  /* little endian
 확인하는 코드 */
  *((char *)0x12ff7c) = 0x01;
  *((char *)0x12ff7d) = 0x02;
  *((char *)0x12ff7e) = 0x03;
  *((char *)0x12ff7f) = 0x04;
  printf("iNum   value: %08x\n", iNum);

  return 0;
}


//
인텔 x86계열 Little-Endian 확인하는 코드로 결과 제일 밑을 보면 확인할 있다

Volatile 키워드

c컴파일러는 불필요한 코드를 자동적으로 최적화 시켜준다. 하지만 특수 역할을 하는 레지스터를 엑세스 해야 되는 경우 최적화가 문제를 일으킨다. 이를 방지하기 위해서 volatile키워드를 사용한다.

+ Recent posts