본문 바로가기
코스웨어/11년 내장형하드웨어

[내장형]윤민석-2011년 9월 2일 일일보고서

by 알 수 없는 사용자 2011. 9. 2.
728x90
반응형
USART
 
 - 0 , 1 두개 외 DBGU(개발의 용이를 위해 하나 더 지원)로 3개 지원
 - 시리얼 통신 -> PA9, PA10을 사용

 
 

AT91SAM7S256을 이용한 UART 통신설정

 

PIOA.h (진한부분이 새로 추가한 부분입니다.)

#ifndef __PIOA_H__
#define __PIOA_H__

#define PIOA_PER  (*(volatile unsigned int *)0xFFFFF400) // Pin enable
#define PIOA_OER  (*(volatile unsigned int *)0xFFFFF410) // output enable
#define PIOA_PPUDR  (*(volatile unsigned int *)0xFFFFF460) // pull-up resistance disable
#define PIOA_CODR  (*(volatile unsigned int *)0xFFFFF434) // 대입하면 0  - clear ouput data
#define PIOA_SODR  (*(volatile unsigned int *)0xFFFFF430) // 대입하면 1  - set output data
#define PIOA_ODR  (*(volatile unsigned int *)0xFFFFF414)  //PIO output Disable Register
#define PIOA_IFER  (*(volatile unsigned int *)0xFFFFF420)  //PIO Glitch Register
#define PIOA_IER    (*(volatile unsigned int *)0xFFFFF440)  //PIO Glitch Register
#define PIOA_ISR    (*(volatile unsigned int *)0xFFFFF44C)//몇번에 인터럽트가 발생하恙눼쩝� 알수 揚獵�.
#define PIOA_ODSR  (*(volatile unsigned int *)0xFFFFF438)//출력 데이터 상태 레지스터
#define PIOA_IDR    (*(volatile unsigned int *)0xFFFFF444)//인터럽트 금지 레지스터
#define PIOA_ASR  (*(volatile unsigned int *)0xFFFFF470)//주변장치 A 선택 레지스터
#define PIOA_BSR  (*(volatile unsigned int *)0xFFFFF474)//주변장치 B 선택 레지스터
#define PIOA_PDR  (*(volatile unsigned int *)0xFFFFF404)//병렬 입출력 금지 레지스터 

#endif



main.c

#include "PIOA.h"

#define DBGU_CR    (*(volatile unsigned int*)0xFFFFF200)    //DBGU 제어 레지스터 (송/수신부)
#define DBGU_IDR  (*(volatile unsigned int*)0xFFFFF20C)    //DBGU 금지 레지스터 (관련 인터럽터 비활성화)
#define DBGU_BRGR  (*(volatile unsigned int*)0xFFFFF220)    //DBGU 보레이트 발생 레지스터 (포트속도 설정)
#define DBGU_MR    (*(volatile unsigned int*)0xFFFFF204)    //DBGU 모드 레지스터 (포트모드 설정)
#define DBGU_SR    (*(volatile unsigned int*)0xFFFFF214)    //DBGU 상태 레지스터 
#define DBGU_THR  (*(volatile unsigned int*)0xFFFFF21C)    //DBGU 송신 홀딩 레지스터
#define DBGU_RHR  (*(volatile unsigned int*)0xFFFFF218)    //DBGU 수신 홀딩 레지스터

#define RSTRX  2
#define RSTTX  3
#define DRXD    9
#define DTXD    10
#define RXEN    4
#define TXEN    6
#define PAR    9
#define CHMODE  14
#define TXRDY  1
#define RXRDY  0

#define MCK    48000000
#define BORETE  115200
#define CD    (MCK/(16*BORETE))

void Usart_init()
{
  DBGU_CR = (1<<RSTRX| 1<<RSTTX);  //송수신부를 리셋, 동작중지
  DBGU_IDR = 0xFFFFFFFF;    //모든 레지스터 1로 설정
  PIOA_ASR = (1<<DRXD | 1<<DTXD);  //PA9, PA10 핀 Peripheral A활성화
  PIOA_BSR = 0x00000000;  //모든  Peripheral B 비활성화
  PIOA_PDR = (1<<DRXD | 1<<DTXD);  //PA9, PA10 핀 Peripheral A비활성화
  DBGU_BRGR = CD;  //cd값 26, MKC = 48MHz
  DBGU_MR = (0<<CHMODE | 4<<PAR);  //포트모드설정(로컬루프백, 패리티 X)
  DBGU_CR = (1<<RXEN | 1<< TXEN);  //송수신 활성화

  return;
}

void Send_Char(unsigned char usSData)    //Data 송신용 함수
{
  while (0 == ((DBGU_SR) & (1<<TXRDY)));  //(TXRDY 실시간 1확인)
  DBGU_THR = usSData;

  return;
}

unsigned char Recv_Char()    //Data 수신용 함수
{
  unsigned char usSData = 0;
  while (0 == ((DBGU_SR) & (1<<RXRDY)));
  usSData = DBGU_RHR;
  
  return usSData;
}

int main(void)
{
  unsigned char buff;
  Usart_init();
  Send_Char('A');
  Send_Char('K');
  Send_Char('I');
  Send_Char('H');
  Send_Char('O');

  while(1)
  {
    buff = Recv_Char();
    Send_Char(buff);
  }
 
  while(1);  
  return 0;
}



1. 송/수신부를 리셋 시키고 동작을 중지시킴
 

  DBGU_CR 레지스터의 AT91C_US_RSTRX, AT91C_US_RSTTX 비트를 1로 설정

  BGU_CR = (1<<RSTRX| 1<<RSTTX);



2. 관련 인터럽터의 비활성화  

  DBGU_IDR 레지스터의 모든 비트를 1로 설정

 DBGU_IDR = 0xFFFFFFFF;

 



3. DBGU의 외부 연결용 Pin 설정

    아래 그림은 AT91SAM7S의 스펙의 36Page에서 발췌한 부분입니다. 자세히 보면

    Peripheral A에 속해 있고 PA 9, 10번 핀에 대해서 설정해야 한다는 것을 알 수

    있음.

    정리해 보면 PA9, 10번 핀을 Peripheral A 모드 활성화, 그에따라 Peripheral B

    는 당연히 비활성화, 그리고 LED를 점둥할 때 쓰이는 병렬 I/O 포트 비활성화 등

    3가지 동작이 이루어 져야 함.

    3-1. PA9, 10번 핀의 Peripheral A 모드 활성화

             PIO_ASR 레지스터의 AT91C_PA9_DRXD, AT91C_PA10_DTXD 비트를

             1로 설정

  PIOA_ASR = (1<<DRXD | 1<<DTXD);

 



3-2. PA9, 10번 핀의 Peripheral B 모드 비활성화

            PIO_BSR 레지스터의 모든 비트를 0로 설정

  PIOA_BSR = 0x00000000;

 




3-4. PA9, 10번 핀의 병렬 I/O 포트 모드 비활성화

           PIO_PDR 레지스터의 AT91C_PA9_DRXD, AT91C_PA10_DTXD

PIOA_PDR = (1<<DRXD | 1<<DTXD);

 

 


4. 포트 속도 설정

     DBGU_BRGR 레지스터에 115200 bps로 설정


DBGU_BRGR = CD;



5. 포트 모드 설정(정상모드, 패리티 없음)

     DBGU_MR 레지스터에

     AT91C_US_CHMODE_LOCAL, AT91C_US_PAR_NONE 비트를 1로 설정


 DBGU_MR = (0<<CHMODE | 4<<PAR);


 



6. 송/수신 모드 활성화

   DBGU_CR 레지스터의 AT91C_US_TXEN, AT91C_US_RXEN 비트를 1로 설정


DBGU_CR = (1<<RXEN | 1<< TXEN);


 


7. Data 송신용 함수의 제작 : void Send_Char(unsigned char usSData)


    7-1. 폴링 방식으로 제작

    7-2. DBGU_SR 레지스터 폴링

            AT91SAM7S의 스펙 253Page 참조.

            실시간으로 TXRDY 비트가 1로 설정되었는지 확인.

            이 비트는 디버그 유닛이 전송 준비가 되면 1로 설정되므로

            확인 즉시 1byte를 전성하면 시리얼 통신 포트로 문자가 전송

            되게 됨. 여기서 주의 해야 할 것은 ATMEL사가 DBGU_SR

            레지스터를 제공한 헤더파일에서는 DBGU_CSR로 해 놓았다는

            것. 이유는 모르겠으나 이점을 유의해서 프로그램을 작성해야 함.

    7-3. DBGU 유닛에 문자 전송

            AT91SAM7S의 스펙 255Page를 참조.

            DBGU_THR 레지스터에 char Data를 직접 쓰면 1Byte 시리얼 전송이

            이루어 지게 됨.


void Send_Char(unsigned char usSData)  //Data 송신용 함수
{
     while (0 == ((DBGU_SR) & (1<<TXRDY))); //(TXRDY 실시간 1확인)
     DBGU_THR = usSData;

     return;
}


 



8. Data 수신용 함수의 제작 : unsigned char Recv_Char()

    8-1. 폴링 방식으로 제작

    8-2. DBGU_SR 레지스터 포링
            송신 함수 제작과 마찬가지로 AT91SAM7S의 스펙 253Page를

            참조하면서 작성.

            실시간으로 RXRDY 비트가 1로 설정되었으면 1byte를 수신하면

            시리얼 통신 포트로 1Byte가 수신된 것 임.

    8-3. DBGU 유닛으로부터의 Byte 수신

            AT91SAM7S의 스펙 255Page를 참조.

            DBGU_RHR 레지스터에서 읽어 들이면 쓰면 시리얼 통신을 통해

            1Byte를 실질적으로 수신 되게 됨.


unsigned char Recv_Char()  //Data 수신용 함수
{
     unsigned char usSData = 0;
     while (0 == ((DBGU_SR) & (1<<RXRDY)));
     usSData = DBGU_RHR;
 
     return usSData;
}



9. 하이퍼터미널로 값을 넣었을 때  반응

 
main함수부분

 

int main(void)
{
    unsigned char buff;    //임시저장 변수
    

     Usart_init();
     Send_Char('A');    //하이퍼터미널에 내가 원하는 문자를 전송
     Send_Char('K');
     Send_Char('I');
     Send_Char('H');
     Send_Char('O');

 

     while(1)
     {
          buff = Recv_Char();
          Send_Char(buff);
     }
 

 
 while(1); 

 return 0;
}

 

 

 

API 예제

 

//main.cpp

 

#include <windows.h>
#include "MsgProc.h"  //add

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE f_hInst;
LPCTSTR lpszClass = TEXT("First");

//add
typedef struct MESSAGEMAP
{
  UINT iMessage;
  LRESULT (*lpfnMsgProc)(HWND, WPARAM, LPARAM);
} MESSAGEMAP;
////////////////////////////////////

  
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
           LPSTR lpszCmdParam, int nCmdShow)
{
  HWND hWnd;
  MSG Message;  //MSG 구조체 사용
  WNDCLASS WndClass;  //WNDCLASS 구조체 사용
  g_hInst=hInstance;  //이 윈도클래스를 등록하는 프로그램의 번호

  /*WndClass 정의(윈도우의 기반이 되는 클래스를 정의한다. 즉, 만들고자 하는 윈도우의 속성을 정의)*/
  WndClass.cbClsExtra = 0;  //예약 영역, 사용하지 않을 경우 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;  //윈도우 스타일 정의
  
  /*윈도우 클래스 등록*/
  RegisterClass(&WndClass);

  /*메모리상에 윈도우 생성*/
  hWnd=CreateWindow(lpszClass, /*타이틀바문자열*/TEXT("My First Program"), /*윈도우스타일*/WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL,
    /*윈도창위치*/300/*윈도창위치*/400/*폭*/CW_USEDEFAULT, /*높이*/CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance,NULL);
  //(윈도클래스이름,타이틀바에나타날문자열,윈도우스타일,CW사용하면 운영체제가 화면크기에 맞게 알아서 조절, ....)
  
  ShowWindow(hWnd, nCmdShow);  //CreateWindow함수가 리턴한 핸들을 이용하여 출력(윈도우를 화면에 표시)

  /*사용자로부터의 메시지 처리(메시지 루프)*/
  while(GetMessage(&Message, NULL, 00))  //메시지 큐에서 읽어옴
  {              //GetMessage가 WM_QUIT면 False리턴
    TranslateMessage(&Message);  //키보드 입력 처리
    DispatchMessage(&Message);  //큐에서 꺼낸 메시지를 WndProc함수의 iMessage로 전달
  }
  return(int)Message.wParam;    //메시지 루프 종료후 이 프로그램을 실행시킨 OS로 리턴
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{  //운영체제가 호출하는 함수는 CALLBACK 표시, LRESULT = 4바이트 long
  
  //add
  int i;
  static MESSAGEMAP MessageMaps[] = {
    {WM_CREATE, OnCreate},
    {WM_COMMAND, OnCommand},
    {WM_LBUTTONDOWN, OnLButtonDown},
    {WM_PAINT, OnPaint},
    {WM_DESTORY, OnDestroy}
  };

  for(i=0; i<sizeof(MessageMaps)/sizeof(MessageMaps[0]); i++)
  {
    if(MessageMaps[i].iMessage == iMessage)
      return (*MessageMaps[i].lpfnMsgProc)(hWnd, wParam, lParam);
  }
  ////////////////////////////////////////

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

 

 

//MsgProc.cpp

 

#include "MsgProc.h"

LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  return 0;
}

LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  return 0;
}

LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  return 0;
}

LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  HDC hdc;
  PAINTSTRUCT ps;

  hdc = BeginPaint(hWnd, &ps);

  EndPaint(hWnd, &ps);
  return 0;
}

LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  PostQuitMessage(0);
  return 0;
}

 

 

//MsgProc.h

 

#ifndef __MSGPROC_H_
#define __MSGPROC_H_

#include <windows.h>

LRESULT OnCreate(HWND, WPARAM, LPARAM);
LRESULT OnCommand(HWND, WPARAM, LPARAM);
LRESULT OnLButtonDown(HWND, WPARAM, LPARAM);
LRESULT OnPaint(HWND, WPARAM, LPARAM);
LRESULT OnDestroy(HWND, WPARAM, LPARAM);

extern HINSTANCE g_hInst;

#endif


API는 일단 예제만.....

728x90