임베디드 개발(before)/IoT 임베디드 SW 개발자 양성과정

[32일차] ARM 프로세서 이해 및 활용 (switch 실습)

주운녕 2020. 8. 25. 16:01

오늘은 스위치의 입력에 따라 값을 출력하는 실습을 진행했다.

먼저 스위치를 사용하기 위해서는 보드의 스위치가 연결되어있는 레지스터의 설정을 초기화 해야한다.

초기화는 UserManual을 참고하자.

 

1. 회로도 보기.

 

 

먼저, 회로도를 보자.

왼쪽부터 스위치 SW4~13, SW14, SW15 이렇게 있는데 편의상 왼쪽부터 1번 스위치라 한다.

보면 아무런 신호를 주지 않을 때, 값이 1를 유지하게 되는 풀업 회로도인 것을 알 수 있다.

즉, 스위치가 열려있을 때는 Vdd에서 나오는 3.3v가 저항을 거쳐 GPF2~6, GPF0~1 로 가기 때문에 High를 유지한다.

스위치를 누르게 되면 Vdd에서 저항을 거쳐 그라운드로 떨어지기 때문에 해당 스위치에 연결된 GPF의 값이 '0'으로 LOW 상태가 된다.

 

우리는 스위치를 1번부터 12번까지 사용할 것이기 때문에 GPF[0:6]번 레지스터를 초기화 해주어야 한다.

또한 1~10번 스위치는 GPF7과 GPG0을 활용하여 5개의 레지스터(PF[2:6])로 10개의 스위치를 조작하게끔 되어있다.

따라서 우리가 초기화 해줄 레지스터는

스위치로 입력을 받는 PF[0:6]레지스터와

풀업 상태를 변경해주는 GPF7, GPG0 레지스터 이다.

 

 

 

 

 

 

 

 

PF[0:6]

▷ GPFCON (모드를 설정)

: input(00) 모드로 해준다.

 

▷ GPFDAT (데이터)

: 스위치 입력시 해당 해당 스위치 비트가 0으로 된다.

 

▷ GPFUDT (풀업 풀다운 선택)

: 풀업 enable (10)으로 해준다.

 

 

 

 

 

 

 

 

★ 코딩해보기

▷ key.c

//SW 1~12 번 초기화
void Key_Port_Init(void)
{
	
	/* GPFCON -Input Mode GPF[0:6] */
	/* YOUR CODE HERE */
	rGPFCON &= ~(0x3fff<<4); //GPF[0:6]을 input mode로 초기화
	rGPFUDP &= ~(0x3fff<<4); //GPF[0:6]을 풀업 enable 하기전에 bit clr
	rGPFUDP |= (0x2aaa<<4);	//GPF[0:6] pull-up enable
	
	/* GPFCON, GPGCON - outputmode GPF7, GPG0 */
	/* YOUR CODE HERE */	
    rGPGCON &= ~(0x01);		//GPG0 bit clr
	rGPGCON |= (0x01);	//GPG0 output 설정
	rGPFCON &= ~(0x01<<14);	//GPF7 bit clr 
	rGPFCON |= (0x01<<14);	//GPF7 output 설정
    
	rGPGDAT |= (0x01<<7); 	//GPG0 HIGH /* 풀업 회로이기에 이따가 */
	rGPFDAT	|= (0x01);	//GPF7 HIGH /* 스위치 활성화시  LOW (회로도 참고)*/
}

int Key_Get_Pressed(void)
{
	int i, keyval;
	
	/* YOUR CODE HERE */
	for(i=0; i<2; i++)
	{	
		rGPFDAT |= (0x1<<7); 	//GPG0 HIGH /* 풀업 회로이기에 이따가 */
		rGPGDAT |= (0x1);	//GPF7 HIGH /* 스위치 활성화시 LOW (회로도 참고)*/
        
      	  //i=0이면 GPG0 LOW => SW1~5번
      	  //i=1이면 GPF7 LOW => SW5~10번 사용
		(i==1)?(rGPGDAT &= ~0x1):(rGPFDAT &= ~(0x1<<7));
        
		keyval = ((~rGPFDAT) & 0x7F); //스위치가 눌려 LOW 된 비트 검출
		switch(keyval)
		{
        	//해당 비트에 따라 스위치 숫자로 반환
			case 1 : return 11;
			case 2 : return	12;		
			case 4 : return (1+(5*i));
			case 8 : return (2+(5*i));
			case 16 : return (3+(5*i));
			case 32 : return (4+(5*i));
			case 64 : return (5+(5*i));
		}	
	}

	return 0;
}

int Key_Wait_Get_Pressed(void)
{
	/* YOUR CODE HERE */
	int a; 
	while (! (a=Key_Get_Pressed()));
	return a; 
}

void Key_Wait_Get_Released(void)
{
	/* YOUR CODE HERE */
	while (Key_Get_Pressed());
	Uart_Send_String("released\n");
}

 

▷ libc.c

void Led_Display(int data)
{
	/* 
 	 * LED On : Active high 
     * LED Off: Active low
	 * GPGDAT[7:4]
	 */
	
	rGPGDAT |= (0xf<<4);

	/* EXERCISE TODO: complete the code below */	
	
	if(data & 0x01)  rGPGDAT &= ~(0x1<<7);  /* turn ON LED1 */
	if(data & 0x02)  rGPGDAT &= ~(0x1<<6);	/* turn ON LED2 */
	if(data & 0x04)  rGPGDAT &= ~(0x1<<5);	/* turn ON LED3 */
	if(data & 0x08)  rGPGDAT &= ~(0x1<<4);  /* turn ON LED4 */

}

 

▷ main.c

/*=========================*/
#include "my_lib.h"
#include "option.h"
#include "2450addr.h"
#include ".\images\bicycle.h"

void Main(void)
{

#if 1 /* KEY TEST */
	int temp;
	Led_Port_Init();
	Uart_Send_String("Press any key : waiting .....\n");
	Key_Port_Init();
	
	for(;;)
	{
		temp = Key_Wait_Get_Pressed();
		Led_Display(temp);
		Uart_Printf("Key Value =%d\n",  temp); 
		Key_Wait_Get_Released();
	}
}

 

 

▷ 작동 영상

- 해당 스위치 번호(1~12)에 맞춰 LED가 2진수값으로 점등되고, key value가 출력된다.

 

 


* 개인적인 학습 목적으로 작성한 글이기에 내용에 잘못된 정보가 있을 수 있습니다.