728x90

ATmega128 포트가 범용 디지털 I/O로 사용될 경우, Read-Modify-Write 기능을 수행할 수 있음

:     I/O포트 입출력 변경하지않고도 동시에 입력과 출력의 기능을 수행할 수 있다.

입출력 방향의 변경없이 포트의 동작 방향이 달라질 수 있음


DDRx 레지스터 : 입출력의 방향을 설정, 각 비트를 1로 설정하면 출력, 0으로 설정하면 입력으로 결정

0 : PORTxn = 입력 -> 입력된 데이터가 PINxn에 저장.

1 : PORTxn = 출력 -> PORTxn의 데이터가 출력됨.


PORTx 레지스터 : 데이터 출력

PINx 레지스터 : 포트 입력 핀, 읽기만 가능하고 쓰기 불가



ATmega128에서 PORTG는 5개의 비트만 사용 (다른 PORT는 0-7까지 8개의 비트 사용)



Atmel/avr tools/avr toolchain/avr/include/avr/iom128.h

 /io.h

에서 SFR 등 비트 정의를 볼 수 있다.




PORT초기화 예)


DDRB = 0xFF;    // 포트 B 출력 설정

PORTB = 0x00;    // 출력 0 설정

DDRD = 0x00;    // 포트 D 입력 설정

PORTD = 0x00;    // 포트 D 내부 풀업 저항을 사용하기 위해 0으로 설정

SFIOR |= 1<<2;    // PUD 비트 1로 설정(풀업 저항 사용안함)



SFIOR의 PUD(Pull-up Disable) 비트를 1로 설정하면 ATmega128 내부에 있는 풀업저항을 사용하지 않는것이고 

PUD를 0으로 설정하면 내부 풀업저항을 사용하는 것이다. 


SFIOR의 PUD 비트의 초기값은 0으로 되어 있기 때문에 이 레지스터를 설정하지 않으면 내부 풀업저항을 사용하도록 설정되는 것과 같다. 





WIn32 API 수업


// 그림판

#include <Windows.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass = TEXT("Text Out 124");  // Title 명


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)

{

HWND hWnd;

MSG Message;

WNDCLASS WndClass;

g_hInst = hInstance;


WndClass.cbClsExtra = 0;

WndClass.cbWndExtra = 0;

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

WndClass.hInstance = hInstance;

WndClass.lpfnWndProc = WndProc;

WndClass.lpszClassName = lpszClass;

WndClass.lpszMenuName = NULL;

WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

RegisterClass(&WndClass);


hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);


while (GetMessage(&Message, NULL, 0, 0))

{

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return (int)Message.wParam;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT pa;

static int x = 100;

static int y = 100;

static int a = 0;


static BOOL bNowDraw = FALSE;


switch (iMessage)

{

case WM_DESTROY:

PostQuitMessage(0);    // 종료

return 0;


case WM_PAINT:

hdc = BeginPaint(hWnd, &pa);

TextOut(hdc, x, y, TEXT("A"), 1);

EndPaint(hWnd, &pa);

return 0;


case WM_KEYDOWN:

switch (wParam)

{

case VK_LEFT:

x -= 8;

break;

case VK_RIGHT:

x += 8;

break;

case VK_UP:

y -= 8;

break;

case VK_DOWN:

y += 8;

break;

case VK_SPACE:

a++;

a %= 2;

break;

}

InvalidateRect(hWnd, NULL, FALSE);

return 0;


case WM_LBUTTONDOWN:

x = LOWORD(lParam);

y = HIWORD(lParam);

bNowDraw = true;

return 0;

case WM_MOUSEMOVE:

if (bNowDraw == TRUE)

{

hdc = GetDC(hWnd);

MoveToEx(hdc, x, y, NULL);

x = LOWORD(lParam);

y = HIWORD(lParam);

LineTo(hdc, x, y);

ReleaseDC(hWnd, hdc);

}

return 0;

case WM_LBUTTONUP:

bNowDraw = FALSE;

return 0;

case WM_LBUTTONDBLCLK:

MessageBox(hWnd, TEXT("더블클릭"), TEXT("메세지박스"), MB_YESNO);

return 0;

}

return(DefWindowProc(hWnd, iMessage, wParam, lParam));

}





// 타이머

#include <Windows.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass = TEXT("Timer");  // Title 명


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)

{

HWND hWnd;

MSG Message;

WNDCLASS WndClass;

g_hInst = hInstance;


WndClass.cbClsExtra = 0;

WndClass.cbWndExtra = 0;

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

WndClass.hInstance = hInstance;

WndClass.lpfnWndProc = WndProc;

WndClass.lpszClassName = lpszClass;

WndClass.lpszMenuName = NULL;

WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

RegisterClass(&WndClass);


hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, 300, 400, 400, 300, NULL, (HMENU)NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);


while (GetMessage(&Message, NULL, 0, 0))

{

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return (int)Message.wParam;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT pa;

SYSTEMTIME st;

static TCHAR sTime[128];


switch (iMessage)

{

case WM_CREATE:

SetTimer(hWnd, 1, 1000, NULL);

return 0;

case WM_TIMER:

GetLocalTime(&st);

wsprintf(sTime, TEXT("지금 시간은 %d:%d:%d입니다."), st.wHour, st.wMinute, st.wSecond);

InvalidateRect(hWnd, NULL, TRUE);

return 0;


case WM_DESTROY:

PostQuitMessage(0);    // 종료

return 0;


case WM_PAINT:

hdc = BeginPaint(hWnd, &pa);

TextOut(hdc, 100, 100, sTime, lstrlen(sTime));

EndPaint(hWnd, &pa);

return 0;

}

return(DefWindowProc(hWnd, iMessage, wParam, lParam));

}



// 3초에 한번 덧셈문제 출제


#include <Windows.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass = TEXT("Timer");  // Title 명


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)

{

HWND hWnd;

MSG Message;

WNDCLASS WndClass;

g_hInst = hInstance;


WndClass.cbClsExtra = 0;

WndClass.cbWndExtra = 0;

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

WndClass.hInstance = hInstance;

WndClass.lpfnWndProc = WndProc;

WndClass.lpszClassName = lpszClass;

WndClass.lpszMenuName = NULL;

WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

RegisterClass(&WndClass);


hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, 300, 400, 400, 300, NULL, (HMENU)NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);


while (GetMessage(&Message, NULL, 0, 0))

{

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return (int)Message.wParam;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT pa;

SYSTEMTIME st;

static TCHAR sTime[128];


int a = rand() % 30;

int b = rand() % 30;


switch (iMessage)

{

case WM_CREATE:

SetTimer(hWnd, 1, 3000, NULL);

return 0;

case WM_TIMER:

GetLocalTime(&st);

wsprintf(sTime, TEXT("%d+%d=?"), a, b);

InvalidateRect(hWnd, NULL, TRUE);

return 0;


case WM_DESTROY:

KillTimer(hWnd, 1);

PostQuitMessage(0); // 종료

return 0;


case WM_PAINT:

hdc = BeginPaint(hWnd, &pa);

TextOut(hdc, 100, 100, sTime, lstrlen(sTime));

EndPaint(hWnd, &pa);

return 0;

}

return(DefWindowProc(hWnd, iMessage, wParam, lParam));

}




'Study > Embedded' 카테고리의 다른 글

아두이노 기초  (0) 2017.05.25
ATMEGA USART-C# App 연동  (0) 2016.12.12
7/8 LCD제어2  (0) 2016.07.08
7/5 LCD 제어  (0) 2016.07.05
5/26 업무일지 PC PWM을 이용한 LED 밝기 조절  (0) 2016.05.26
728x90

LCD 모듈 제어에 기본적으로 수행되야하는 기능


- IR에 명령 쓰기

- DR에 데이터 쓰기

- 명령 처리 시간을 고려한 시간 지연



LCD 컨트롤러 명령어 표


신호 제어선 정의 예


#define  CLR   0x01      //Clear Display 명령
#define  HOME  0x02      //Return Home 명령 
#define  FNC   0x38      //Function Set 명령
                		 //Data Length = 8bit. 행수 2행


void LCD_PortSetting(void)
{
  DDRC = 0xFF;        //데이터 라인
  DDRD = 0xFF;        //0~2 제어핀 사용
  //D0: RS ,D1: R/W ,D2: EN
}


명령 레지스터에 명령어 쓰기 함수


위의 명령어 표와 같은 명령을 수행할 함수이다. 수행결과는 함수를 호출하는 함수에 반환될 필요가 없다.


void IR_Write(unsigned char Data) { PORTD &= 0xFC; // RS = 0, RW = 0 (Write Enable), 0xFC = 1111 1100) _delay_us(1); // Enable 까지 최소 대기 시간 40ns PORTD |= 0x04; // En _delay_us(1); PORTC = Data; _delay_us(1); PORTD = 0b00000010; // Disable. Read Mode }

PORTD &= 0XFC // PORTD= PORTD & 0XFC



데이터 레지스터에 데이터 쓰기 함수


DDRAM 또는 CGRAM에 데이터를 쓰는 함수로서 사용되는 여러가지 명령어가 제시되어 있다.

void DR_Write(unsigned char Data)
{
  PORTD = 0x01;    //RS = 1, Write Enable
  _delay_us(1);    //Enable 까지 최소 대기 시간 40ns
  PORTD |= 0x04;    //Enable 활성화
  _delay_us(1);    //
  PORTC = Data;    //Data
  _delay_us(1);
  PORTD = 0b00000010;  //Disable, Read Mode  
}













'Study > Embedded' 카테고리의 다른 글

ATMEGA USART-C# App 연동  (0) 2016.12.12
7/21 Atmega128 포트/ win32 api  (0) 2016.07.21
7/5 LCD 제어  (0) 2016.07.05
5/26 업무일지 PC PWM을 이용한 LED 밝기 조절  (0) 2016.05.26
2016-05-19 업무일지-Atmega2560_LCD출력  (0) 2016.05.19
728x90

IR (명령 레지스터) : LCD 모듈 환경 설정

DR (데이터 레지스터) : LCD 모듈에 글자를 나타내기 위한 데이터 값 기록



LCD 컨트롤러 내부는 IR,DR과 문자를 표시하기 위해 사용되는 DDRAM, CGRAM, CGROM으로 구성



LCD 모듈은 보통 총 14핀 또는 16핀 구성 (16핀은 백라이트 구동을 위한 전원단자 2핀 추가)


1,2번 : LCD 모듈 구동전원 인가

3번 : LCD 표시장치 밝기 조절 (밝기 조절시 가변저항 연결, 필요없으면 GND 연결)


4-6 : LCD 제어 (RS, R/W, E) 

RS (4번) - 입력단자로서 LCD 모듈의 명령 또는 데이터 레지스터 선택

0이면 IR, 1이면 DR 선택


R/W (5번) - 데이터 또는 명령을 읽고, 쓰기할때 사용

0이면 쓰기 (CPU에서 LCD 모듈로 데이터 씀)

1이면 읽기 (LCD모듈에서 CPU로 데이터 읽음)


E (6번) - 활성화되어있으면 데이터 교환이 이루어짐

HIGH (1 입력) 일때 데이터 교환 가능, 0일때는 데이터 교환 불가능


7-14 : Data Bus (4비트 방식 제어시 11-14번만 이용됨)

마이크로 컨트롤러와 인터페이스를 할 경우에는 읽기 쓰기 타이밍을 고려해야 함(데이터 시트 타이밍도 참고)




IR (명령 레지스터)

: LCD의 제어에 필요한 명령 저장, 표시 데이터 DDRAM 위치주소와 문자발생기 CGRAM 위치 지정하기 위한 주소정보 저장


DR (데이터 레지스터)

: 화면에 표시할 데이터 또는 새로운 글꼴에 대한 데이터 임시 저장

데이터를 쓸 때는 IR에 의해 지정된 DDRAM 또는 CGRAM 주소로 데이터 전달

읽을때는, IR에 의해 지정된 DDRAM 또는 CGRAM 주소의 데이터가 마이크로 컨트롤러로 전달



제어 명령어는 데이터 시트를 참고

HY-1602W-204-LCD.pdf

케릭터 LCD 명령어 설명.pdf




비지 플래그 

: 연속적으로 LCD 모듈에 제어명령이 입력될 때, LCD 모듈이 이 명령을 처리할 수 있는가를 나타내는 상태 표시 플래그 

RS가 0 (IR), R/W가 1(읽기)일때 출력된다.


BF = 0 : LCD 모듈로 다음 명령을 쓸 수 있다.

BF = 1 : LCD 컨트롤러가 현재 IR로 입력된 명령어 처리하는 상태, 다음 제어 명령을 쓸수 없는 상태를 나타냄.








DDRAM (Display Data RAM)

화면에 표시할 8비트 문자를 저장 (표시되지 않는 영역의 RAM은 일반적 데이터 저장용 메모리로 사용가능)


CGROM (Character Generator ROM)

문자 패턴을 저장




 HY-1602W-204-LCD.pdf (CGROM에 저장된 내용은 데이터 시트 11p 참고)




CGRAM (Character Generator RAM)

사용자가 원하는 문자 패턴을 만들때 사용



화면 클리어

#define CLR    0x01 // 화면 전체 클리어 후, Return Home 명령


커서 홈

#define HOME  0x02 // 커서만 홈 위치로 보내는 명령


엔트리 모드 셋

: LCD 모듈에 데이터를 쓰기/읽기 수행할 경우 DDRAM주소 즉, 커서 위치를 오른쪽으로 증가 또는 왼쪽으로 감소시킬것인가를 결정하는 기능 수행

또한, 커서 위치는 변하지 않고 화면을 이동시킬지(shift) 결정



DB2 bit를 1로 설정 


1비트=I/D

I/D = 1일때 커서 또는 깜박임 위치가 우측 이동 (주소 +1)

I/D = 0일때 커서 또는 깜박임 위치가 좌측 이동 (주소 -1)


0비트=S    

S = 1, I/D=1일 때, 좌로 쉬프트

S = 1, I/D=0일 때, 우로 쉬프트

S = 0, 화면 쉬프트 되지 않음


* CGRAM도 같은 방법으로 적용



Display ON/OFF Control

: 화면의 ON/OFF, 커서의 ON/OFF, 커서위치에 있는 문자 점멸 등의 기능 설정

예) IR_Write(0x0E); // Display on/off DDRAM, 커서를 화면에 표시


* 더 자세한 명령어 설정은 데이터 시트 참고


커서 표시 시프트

: 커서의 위치 또는 표시할 데이터의 읽기 또는 쓰기없이 (DDRAM 내용 변경없이)

오른쪽/왼쪽으로 이동.


2줄을 표시할 경우 첫번째줄의 끝을 넘을 경우 두번째 줄 이동


* 첫번째줄과 두번째 줄이 동시 이동

데이터 쉬프트해도 두번째 줄 데이터는 첫번째 줄에 표시안됨

쉬프트 해도 AC는 변하지 않음



Function Set

: Function Set은 LCD를 사용하기 앞서 선행되어야 한다.

(busy flag와 어드레스 명령을 제외한 다른 명령이 실행되기전에 프로그램 앞 부분에 실행되어야 함)



DL : 인터페이스 길이

1이면 데이터 길이 8비트 설정

0이면 데이터 길이 4비트 설정 (DB7-DB4사용), 이 경우 두번에 나누어 먼저 상위 4비트 전송하고, 하위 4비트 전송해야 함


N : 표시줄의 숫자 (0이면 1줄, 1이면 2줄)


F : 문자 폰트 설정 (0이면 5x8, 1이면 5x10)




CGRAM, DDRAM 주소 설정



CGRAM에 새로운 문자를 만들고자 할 경우 IR레지스터의 DB6 비트를 1로 설정(AC는 주소로서 전달)


DDRAM에 주소를 설정한 후에 데이터를 송수신하려면 DB7 비트를 1로 설정

N=0이면 한개의 라인을 가지며, 7비트 (AC0-AC6)는 0x00~0x4F로 설정


N=1이면, 두개의 줄을 가지며

첫번째 줄의 주소는 0x00~0x27

두번째 줄의 주소는 0x40~0x67까지로 설정

'Study > Embedded' 카테고리의 다른 글

7/21 Atmega128 포트/ win32 api  (0) 2016.07.21
7/8 LCD제어2  (0) 2016.07.08
5/26 업무일지 PC PWM을 이용한 LED 밝기 조절  (0) 2016.05.26
2016-05-19 업무일지-Atmega2560_LCD출력  (0) 2016.05.19
2016-05-17 업무일지-7 segment  (0) 2016.05.17
728x90

PC PWM을 이용한 LED 밝기 조절




WGMn2~0 비트에 의한 동작모드

모드1 : Phase Correct PWM / TOP(0xFF)


/************************************************
* PC PWM을 이용한 LED 밝기 조절 프로그램
* 2016년 5월 26일
************************************************/

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  unsigned char i, duty;

  //PWM 출력을 뽑을 GPIO설정(OC0A(PB7))
  DDRB=0xFF; // PB7 PWM 출력, PB 0~6 사용안함
  //Time / Counter0의 설정 (PC PWM 모드)
  TCCR0A = 0b10000001; // 0x81, 상향카운터 compare match 0, 하향 1로 set
  TCCR0B = 0x01; // 1분주

  while(1)
  {
    for(i=0, duty=0; i<6; i++, duty +=51)
    {
      OCR0A = duty;
      _delay_ms(500);
    }

  }
  return 0;
}




/************************************************
* PC PWM을 이용한 LED 밝기 조절 프로그램
* 2016년 5월 26일
************************************************/

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  unsigned char i, duty;

  //PWM 출력을 뽑을 GPIO설정(OC0A(PB7))
  DDRB=0xFF; // PB7 PWM 출력, PB 0~6 사용안함
  //Time / Counter0의 설정 (PC PWM 모드)
  TCCR0A = 0b10000001; // 0x81, 상향카운터 compare match 0, 하향 1로 set
  TCCR0B = 0x01; // 1분주

  while(1)
  {
    for(i=0, duty=0; i<6; i++, duty +=51)
    {
      OCR0A = duty;
      _delay_ms(500);
    }

  }
  return 0;
}




switch문으로 변경

/************************************************
* PC PWM을 사용한 DC 모터 속도 제어용 프로그램

* 속도 조절 단계 15단계, 출력 0C0A 또는 OC0B
* 입력 스위치 입력 2개(UP, Down)
* 최대 속도 도달시 UP키 동작 안함, 회전하지 않을 때 DN키 동작 안함.
************************************************/
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  unsigned char duty = 0;
  
  
  DDRB  =  0xFF;            

  DDRA  =  0xFC;    //0,1번 포트를 스위치 입력으로                      
  
  TCCR0A  =  0x81;    //OC0A를 출력으로 사용                
  TCCR0B  =  0x01;          

   while(1)
  {
    key = (PINA & 0x03)
    switch(key)
    {
      case 1:
        while(PINA & 0x01 );
        if(i < 15)
          i++;
        break;
      case 2:
        while(PINA & 0x02);
        if(i > 0)
          i--;
        break;
    }
    OCR0A = 17*i;
  }
  return 0;
}


'Study > Embedded' 카테고리의 다른 글

7/8 LCD제어2  (0) 2016.07.08
7/5 LCD 제어  (0) 2016.07.05
2016-05-19 업무일지-Atmega2560_LCD출력  (0) 2016.05.19
2016-05-17 업무일지-7 segment  (0) 2016.05.17
7 Segment 출력(proteus시뮬)  (0) 2016.05.16
728x90
#include <avr/io.h>
#include <util/delay.h>

#define  CLR   0x01      //Clear Display 명령
#define  HOME  0x02      //Return Home 명령 
#define  FNC   0x38      //Function Set 명령
                		 //Data Length = 8bit. 행수 2행


void LCD_PortSetting(void)
{
  DDRC = 0xFF;        //데이터 라인
  DDRD = 0xFF;        //0~2 제어핀 사용
  //D0: RS ,D1: R/W ,D2: EN
}

void IR_Write(unsigned char Data)  
{
  PORTD &= 0xFC;    //RS = 0, Write Enable
  _delay_us(1);    //Enable 까지 최소 대기 시간 40ns
  PORTD |= 0x04;    //Enable 활성화
  _delay_us(1);    //
  PORTC = Data;    //Data
  _delay_us(1);
  PORTD = 0b00000010;  //Disable, Read Mode  

}

void DR_Write(unsigned char Data)
{
  PORTD = 0x01;    //RS = 1, Write Enable
  _delay_us(1);    //Enable 까지 최소 대기 시간 40ns
  PORTD |= 0x04;    //Enable 활성화
  _delay_us(1);    //
  PORTC = Data;    //Data
  _delay_us(1);
  PORTD = 0b00000010;  //Disable, Read Mode  
}

void LCD_drive()
{
  _delay_ms(50);
  IR_Write(FNC);
  _delay_ms(5);
  IR_Write(FNC);
  _delay_us(100);
  IR_Write(FNC);
  _delay_ms(2);
  IR_Write(0x0E);	// Display On / Off, 	DDRAM, 커서 ON
  _delay_ms(2);  
  IR_Write(CLR);	// Display Clear
  _delay_ms(30);
  IR_Write(0x06);	// Entry Mode Set, 커서위치를 오른쪽으로 증가
  _delay_ms(2);
}

int main(void)
{
  LCD_PortSetting();
  LCD_drive();
  DR_Write(65);
  _delay_ms(2);
  DR_Write('D');

  while(1)
  {     
  }
  return 0;
}

Output :

LCD에 D 출력




#include <avr/io.h>
#include <util/delay.h>

#define CLR    0x01 // Return Home 명령
#define HOME  0x02 // Function Set 명령
#define FNC    0x38 // Data Length 8 bit 

void LCD_PortSetting(void)
{
  DDRC = 0xFF; // 데이터 라인
  DDRD = 0xFF; // 0 ~ 2 제어 핀 사용
  // 00: RS, 01: R/W, 02: En
}

void IR_Write(unsigned char Data)
{
  PORTD &= 0xFC; // RS = 0, Write Enable

  _delay_us(1); // Enable 까지 최소 대기 시간 40ns
  PORTD |= 0x04; // En

  _delay_us(1);
  PORTC = Data;

  _delay_us(1);
  PORTD = 0b00000010; // Disable. Read Mode
}

void DR_Write(unsigned char Data)
{
  PORTD = 0x01; // RS = 1, Write Enable

  _delay_us(1); // Enable 까지 최소 대기 시간 40ns
  PORTD |= 0x04; // En

  _delay_us(1);
  PORTC = Data;

  _delay_us(1);
  PORTD = 0b00000010; // Disable. Read Mode
}

void LCD_drive()
{
  _delay_ms(50); // 
  IR_Write(FNC);

  _delay_ms(5);
  IR_Write(FNC);
  
  _delay_us(100);
  IR_Write(FNC);
  _delay_ms(2);

  IR_Write(0x0E); // Display on/off DDRAM, 커서를 화면에 표시
  _delay_ms(2);


  IR_Write(CLR); // Display Clear
  _delay_ms(30);

  IR_Write(0x06); // Entry module set 명령. 오른쪽으로 커서 이동.
  _delay_ms(2);
}

void LCD_CHAR(unsigned char a)
{
  _delay_ms(1); // 명령어 쓰기 전 일정 시간 지연
  DR_Write(a); // 사유: Busy Flage 확인 대용
}

void cursor_HOME(void)
{
  IR_Write(0x02);
  _delay_ms(2);
}

void Display_Shift(unsigned char p)
{
  if(p == 1) // 표시화면 전체를 오른쪽으로 이동.
  {
    IR_Write(0x1C); // 화면 표시 내용을 오른쪽으로 이동.
    _delay_us(50);
  }

  else if(p == 0)
  {
    IR_Write(0x18); // 화면 표시 내용을 오른쪽으로 이동.
    _delay_us(50);    
  }
}

void LCD_STR(unsigned char *str)
{
  while(*str != 0)	// 0은 null, 값이 들어오면 
  {
    LCD_CHAR(*str);
    str++;
  }
}

void Position(unsigned char col, unsigned char row)	// 열과 행 
{
	IR_Write(0x80 | row+col*(0x40));
}

int main(void)
{
  LCD_PortSetting();
  LCD_drive();
  /*
  DR_Write(65);
  DR_Write('B');
  */
  Position(1,1);
  LCD_STR("Hello");
  //Display_Shift(1);

  while(1)
  {

  }

  return 0;
}

Output :

LCD에 Hello 출력







'Study > Embedded' 카테고리의 다른 글

7/5 LCD 제어  (0) 2016.07.05
5/26 업무일지 PC PWM을 이용한 LED 밝기 조절  (0) 2016.05.26
2016-05-17 업무일지-7 segment  (0) 2016.05.17
7 Segment 출력(proteus시뮬)  (0) 2016.05.16
5/12 avr 업무일지  (0) 2016.05.12
728x90

 

7 segment 숫자와 알파벳 출력 


캐소드 구동방식은 FND의 세그먼트중 켜길 원하는 비트가 0, 끄길 원하는 비트가 1이 된다.




 

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
	unsigned char fnd[16] = 
				{0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xd8, 
		 		 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};
	volatile unsigned char i;

	DDRF=0xFF;
	while(1)
	{	
		for(i=0; i<16; i++)
		{		
			_delay_ms(20);
			PORTF = fnd[i];
		}
	}
}



  //  PORTF = 0b1000000;  //0

  //  PORTF = 0b1111001;  //1

  //  PORTF = 0b0100100;  //2

  //  PORTF = 0b0110000;  //3  B0

  //  PORTF = 0b0011001;  //4  99

  //  PORTF = 0b0010010;  //5  92

  //  PORTF = 0b0000010;  //6  82

  //  PORTF = 0b1011000;  //7  E8

  //  PORTF = 0b0000000;  //8  80

  //  PORTF = 0b0010000;  //9  90

  //  PORTF = 0b0001000;  //A  88

  //  PORTF = 0b0000011;  //b  83

  //  PORTF = 0b1000110;  //c  c6

  //  PORTF = 0b0100001;  //d  a1

  //  PORTF = 0b0000110;  //e  86

  //  PORTF = 0b0001110;  //f  8e








애노드 구동방식은 FND의 세그먼트중 켜길 원하는 비트가 1, 끄길 원하는 비트가 0이 된다.


#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
	unsigned char fnd[10] = // 0~9
							{0xC0, 0xF9, 0xA4, 0xB0, 0x99, 
							 0x92, 0x82, 0xd8, 0x80, 0x90};
		
	unsigned char n10;
	unsigned char n1;

	unsigned char num=0;

	DDRH=0xFF;	// 7 Segment의 Data Line
	DDRJ=0xFF;	// 7 Segment의 자릿수 ON/OFF
	while(1)
	{	
		n10 = num / 10;	// 십의 자리
		n1 = num % 10;	// 일의 자리
		
		PORTJ = 0x00;	// ON
		PORTH = fnd[n10];	// Data
		PORTJ = 0x01;	// OFF
		_delay_ms(2);
				
		PORTJ = 0x00;
		PORTH = fnd[n1];
		PORTJ = 0x02;
		_delay_ms(2);
		PORTJ = 0x00;		

		num++;
		num = num % 100;
	}
	return 0;
}








728x90

bcd.DSN


proteus에서 회로도 그리고 아래 소스를 시뮬레이션



hex파일을 프로그램으로 올려줌




7 Segment - up & down 카운트



#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
	unsigned char in, out =0;
	
	DDRA = 0b11111100;		// A0, A1만 입력 (0xFC) / 사용하지 않는 포트는 출력 
	DDRB = 0xFF;
	while(1)
	{
			in = PINA;
			switch (in)
			{
					case 0x01 :		// Up count
							while(PINA=0x01);	// 스위치 때는 순간 while문 탈출(high->low)
							out++;
							break;
					case 0x02 :
							while(PINA=0x02);
							out--;
							break;
			}
			PORTB = out;
			//_delay_ms(50);
	}
		return 0;
}





7 Segment - 입출력



#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
	unsigned char a;

	DDRA = 0x00;	// A 포트는 입력으로 사용, 생략 가능
	DDRB = 0xFF;	// B 포트는 출력으로 사용
	DDRC = 0xFF;	// 미사용 포트는 출력으로 설정
	DDRD = 0xFF;	// 미사용 포트는 출력으로 설정
	DDRE = 0xFF;	// 미사용 포트는 출력으로 설정
	DDRF = 0xFF;	// 미사용 포트는 출력으로 설정
	DDRG = 0xFF;	// 미사용 포트는 출력으로 설정
	DDRH = 0xFF;	// 미사용 포트는 출력으로 설정
	DDRJ = 0xFF;	// 미사용 포트는 출력으로 설정
	DDRK = 0xFF 	// 미사용 포트는 출력으로 설정

	while(1)
	{
		a = PINA;
		switch(a)
		{
			case 0x01;
					PORTB = 0x01;
					break;
			case 0x02;
					PORTB = 0x02;
					break;
			case 0x04;
					PORTB = 0x04;
					break;
			case 0x08;
					PORTB = 0x08;
					break;

			case 0x10;
					PORTB = 0x10;
					break;
			case 0x20;
					PORTB = 0x20;
					break;
			case 0x40;
					PORTB = 0x40;
					break;
			case 0x80;
					PORTB = 0x80;
					break;
			default :
				PORTB = 0;
				break;
		}
		PORTB = a;
	}
	return 0;
}




'Study > Embedded' 카테고리의 다른 글

2016-05-19 업무일지-Atmega2560_LCD출력  (0) 2016.05.19
2016-05-17 업무일지-7 segment  (0) 2016.05.17
5/12 avr 업무일지  (0) 2016.05.12
5/2 디지털이란? / 저항, 인덕터, 캐패시터  (0) 2016.05.02
2016 04 28 디코더  (0) 2016.04.28
728x90

#include <avr/io.h>

#include <util/delay.h>


int main(void)

{

DDRA=0xFF;

while(1)

{

// PORTA ^=0XFF; // DDRA = (*(volatile unsigned char *)0x21)

PORTA = PORTA ^ 0XFF;

_delay_ms(3000);

}

return 0;

}



PORTA = PORTA ^ 0xFF; //xor =  모든값을 반전


0x02에 offset값(0x20) 더해서 0x22

오프셋이란, 두 번째 주소를 만들기 위해 기준이 되는 주소에 더해진 값을 의미한다. 


오프셋을 이용하여 주소를 나타내는 것을 상대주소 지정방식이라고 부르는데, 그 이유는 결과 주소가 다른 지점의 상대적인 위치가 되기 때문이다. 오프셋을 다른 말로 "변위"라고도 부른다.



안넣으면 계속 켜진거처럼 보임, 오실로스코프를 통해 클럭이 움직이는걸 볼 수 있음


'Study > Embedded' 카테고리의 다른 글

2016-05-17 업무일지-7 segment  (0) 2016.05.17
7 Segment 출력(proteus시뮬)  (0) 2016.05.16
5/2 디지털이란? / 저항, 인덕터, 캐패시터  (0) 2016.05.02
2016 04 28 디코더  (0) 2016.04.28
2016 04 27 논리회로  (0) 2016.04.27
728x90

1. 디지털이란?

digit - 손가락


analog->표본화(sampling)->양자화->부호화



불확정성의 원리



임베디드 레시피 p.28

저항, 인덕터, 캐패시터



R (저항)

전류의 흐름을 방해. 저항의 크기가 크면 작은 전류, 저항의 크기가 작으면 큰 전류가 흐를 수 있음



L(인덕터) 또는 코얼

저주파수는 통과

고주파수는 걸러진다.

주로 회로에 직렬연결


C(캐패시터) 또는 콘덴서

고주파 통과

저주파 걸러냄

주로 회로에 병렬연결




'Study > Embedded' 카테고리의 다른 글

7 Segment 출력(proteus시뮬)  (0) 2016.05.16
5/12 avr 업무일지  (0) 2016.05.12
2016 04 28 디코더  (0) 2016.04.28
2016 04 27 논리회로  (0) 2016.04.27
2016-04-25_디지털제어-회로 기초  (0) 2016.04.25
728x90


디코더


입력선에 나타나는 n비트의 2진 코드를 최대 2n개의 서로 다른 정보로 바꿔주는 조합논리회로


 

2x4 디코더 진리표





AND 게이트로 구현한 2x4 디코더                                        실제 회로는 NAND 게이트로 구현


: NAND 게이트를 사용하는것이 AND 게이트를 사용한 디코더에 비해 게이트를 더 적게 쓰기 때문에 경제적.

성능 측면에서도 NOT 게이트의 신호전달 지연시간 만큼을 줄일 수 있기 때문






'Study > Embedded' 카테고리의 다른 글

5/12 avr 업무일지  (0) 2016.05.12
5/2 디지털이란? / 저항, 인덕터, 캐패시터  (0) 2016.05.02
2016 04 27 논리회로  (0) 2016.04.27
2016-04-25_디지털제어-회로 기초  (0) 2016.04.25
20160324_펌웨어(써미스터,PWM)  (0) 2016.03.24

+ Recent posts