반응형

74HC573 는 TTL 시리즈 중에서 8bits Latch IC 로 원하는 출력값을 다음 변경전까지 유지시키기 위한 용도로 사용합니다. 

제 경우에는 주로 릴레이 On, Off 에 많이 사용했습니다. 

 

그런데 주로 아두이노나노 보드를 사용하다 보니 출력 핀수가 적어서 시리얼로 제어가 가능한 74hc595 를 많이 사용했습니다. 

아두이노 메가 처럼 IO 핀이 많은 경우나 HC245 와 같은 입출력 포트를 같은 라인으로 사용할 경우 적용하면 좋을듯 하여 

코드를 만들어 보았습니다.

 

class HC573Latch 
{
public :
	
	void HC573Latch(uint8_t le, uint8_t enable,							// OE 단자를 사용할 경우 
		       uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
		       uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
			   
	void HC573Latch(uint8_t le, 											// OE 단자를 GND로 묶었을 경우 
		       uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
		       uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);			   
			   
	void latch8bits(uint8_t value) ;

private :
	bool _oe_used ;				// OE 단자의 사용 여부 
	
	uint8_t _output_enable ;  // activated by a LOW 
	uint8_t _latch_pin;       // activated by a HIGH pulse.
	uint8_t _data_pins[8];
  
    void pulseEnable();
} ;
//-----------------------------------------------------------------------	
void HC573Latch(uint8_t le, uint8_t enable,							// OE 단자를 사용할 경우 
		        uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
		        uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
	_output_enable = enable ;
	_latch_pin = le ;
	_oe_used = true ;
	
	_data_pins[0] = d0 ;
	_data_pins[1] = d1 ;
	_data_pins[2] = d2 ;
	_data_pins[3] = d3 ;
	_data_pins[4] = d4 ;
	_data_pins[5] = d5 ;
	_data_pins[6] = d6 ;
	_data_pins[7] = d7 ;
	
	digitalWrite(_output_enable, HIGH) ;
}			   
//-----------------------------------------------------------------------			
void HC573Latch(uint8_t le, 							// OE 단자를 GND로 묶었을 경우 
		        uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
		        uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
	_latch_pin = le ;
	_oe_used = false ;
	
	_data_pins[0] = d0 ;
	_data_pins[1] = d1 ;
	_data_pins[2] = d2 ;
	_data_pins[3] = d3 ;
	_data_pins[4] = d4 ;
	_data_pins[5] = d5 ;
	_data_pins[6] = d6 ;
	_data_pins[7] = d7 ;
}			   
//-----------------------------------------------------------------------	   
void HC573Latch::latch8bits(uint8_t value) 
{
	if(_oe_used == true) digitalWrite(_output_enable, LOW) ;
	
	for (int i = 0; i < 8; i++) 
	{
		digitalWrite(_data_pins[i], (value >> i) & 0x01);	// 데이타 핀에 데이타를 출력한다. 
	}
  
	pulseEnable();  	// Latch 단자를 on->off 하여 출력을 변경한다.
	
	if(_oe_used == true) digitalWrite(_output_enable, HIGH) ;
}	
//-----------------------------------------------------------------------
void HC573Latch::pulseEnable(void) 
{
	digitalWrite(_latch_pin, HIGH);
	delayMicroseconds(1);   
	digitalWrite(_latch_pin, LOW);	
}
//-----------------------------------------------------------------------
반응형
반응형

아두이노에서 내부 Timer를 이용하여 LED를 제어하는 코드 입니다. 

토글 스위치를 이용하여 타이머 동작을 제어하고 타이머가 구동되면 1초간격으로 LED 가 점멸하도록 했습니다.

#include "MsTimer2.h"    // Timer를 사용하기위한 헤더 선언 

#define     LED_ON          0
#define     LED_OFF         1

const int LED_CONT   = 1 ;
const int Timer_CONT = 2 ;      

boolean LED_Status = false ;     // LED 의 현재 상태 Flag 
boolean timerStatus = false ;    // 타이머 동작 여부 상태 Flag
//--------------------------------------------------------------------------------
void setup() 
{
    MsTimer2::set(1000, Timer_Event);      // 타이머 설정 : 1000msec, 구동 함수 선언  
	
	pinMode(LED_CONT, OUTPUT) ;
	pinMode(Timer_CONT, INPUT) ;           // toggle switch를 사용한 입력 
	
	digitalWrite(LED_CONT, LED_OFF);  
}
//--------------------------------------------------------------------------------
void loop() 
{
	int input = digitalRead(Timer_CONT) ;
	
	if(input == 1)
	{
		if(timerStatus == false)
		{		
			MsTimer2::start();  			// 타이머 동작 시작 
			timerStatus = true ;
		}
	}
	else
	{
		if(timerStatus == true)
		{		
			MsTimer2::stop();                // 타이머 동작 멈출
			timerStatus = false ;
		}
	}
}
//--------------------------------------------------------------------------------
void Timer_Event()  
{
    /* Timer Event : 1초에 한번씩 동작 */
    
	if(LED_Status)
	{
		digitalWrite(LED_CONT, LED_OFF);  
	}
	else
	{
		digitalWrite(LED_CONT, LED_ON);  
	}
	
	LED_Status = !LED_Status ;
}
//--------------------------------------------------------------------------------

아두이노 타이머 테스트
타이머 테스트 회로

반응형
반응형

아두이노 MPU에 내장되어 있는 EEP Rom 메모리에 데이타를 읽고 쓸수 있는 함수입니다.

정수형 데이타를 저장하거나 읽을 수 있도록 만들었습니다. 

하드웨어의 간단한 파라메터 값이나 보드의 어드레스 정보등을 저장하는 용도로 사용할 수 있습니다.

#include <EEPROM.h>

#define   FIRST_ADDRESS     0
#define   SECOND_ADDRESS    2

int EEPROM_Read(int Address)
{
	int result = 0  ;
	int temp ;

	result = EEPROM.read(Address+1) ;
	result <<= 8 ;
	temp = EEPROM.read(Address) ;

	result = result | temp ;  

	return result ;
}

void EEPROM_Write(int Address, int Value)
{
	char temp ;
	
	temp = 0x00ff & Value ;
	EEPROM.update(Address, temp) ;

	Value >>= 8 ;

	temp = 0x00ff & Value ;
	EEPROM.update(Address+1, temp) ; 
}


위의 함수들은 정수형 데이타를 저장하거나 읽어내는 용도이기 때문에 어드레스 설정을 할 경우 주의가 필요합니다. 

EEPROM의 번지는 바이트 단위이기 때문에 정수형 데이타는 2개의 번지를 점유하게 됨으로 그레 맞추어 번지를 설정 하여야 합니다.

 

 

반응형
반응형

아두이노에 버튼이 여러개 있을 경우 각각의 버튼에 대한 입력을 체크하여 각각의 버튼에 대한 입력 처리만 하게됩니다. 

예를 들어 버튼이 3개가 있다면 3가지 경우의 입력만 처리하게 됩니다.  

 

하지만 적은 수의 버튼으로 좀더 많은 경우의 처리를 하는 방법이 있습니다. 바로 bit field 기능을 이용하면 됩니다. 

비트 필드를 구성하게 되면 두개 이상의 키가 동시에 눌리는 경우도 하나의 입력값으로 인식하여 처리 루틴을 만드는 것이 가능합니다.

만일 버튼이 3개 있다면 최대 7가지의 경우로 조합하여 입력 처리를 할 수 있습니다. 

 

#define U08  unsigned char 

union BUTTON_STATE   // 버튼입력 상태에 대한 비트필드 공용체
{
  U08 State ;
  struct
  {
    int UP_BUTTON    : 1 ;
    int DOWN_BUTTON  : 1 ;
    int LEFT_BUTTON  : 1 ;
    int RIGHT_BUTTON : 1 ;   
    int EMPTY        : 4 ;
  } ;
} ;

const int upButton    = 2;    
const int downButton  = 3;       
const int leftButton  = 4;
const int rightButton = 5;

BUTTON_STATE btn_state ;

void setup()
{
  // initialize the buttons' inputs:
  pinMode(upButton, INPUT);      
  pinMode(downButton, INPUT);      
  pinMode(leftButton, INPUT);      
  pinMode(rightButton, INPUT);     
}

U08 Read_Button()
{
   btn_state.UP_BUTTON    = digitalRead(upButton); 
   btn_state.DOWN_BUTTON  = digitalRead(downButton);
   btn_state.LEFT_BUTTON  = digitalRead(leftButton);
   btn_state.RIGHT_BUTTON = digitalRead(rightButton);

   return btn_state.State ;
}
 
void loop()
{
    U08 Key_State ;

    Key_State = Read_Button() ;

    switch(Key_State)
    {
        case 0x01 : function1() ; break ;  // UP_BUTTON
        case 0x02 : function2() ; break ;  // DOWN_BUTTON
        case 0x04 : function3() ; break ;  // LEFT_BUTTON
        case 0x08 : function4() ; break ;  // RIGHT_BUTTON
        case 0x03 : function5() ; break ;  // UP_BUTTON & DOWN_BUTTON
    }
}
반응형
반응형

아두이노와 외부 디바이스 또는 PC 와 RS232 통신을 하기위한 방법을 설명합니다.

제 블로그에서는 가급적 실사용 위주를 중심으로 코드를 올립니다. 큰 틀은 가져가시고 세부적인 부분만 수정하셔도 동작에 지장이 없으실 겁니다. 

하기의 코드는 실제 개발 제품에 사용했던 것으로 PC가 Master 이고 아두이노가 Slave 인 구성에서의 코드입니다. 

아두이노가 Master 가 되는 상황에서 다른 디바이스를 제어할 경우는 코드 구성이 좀 틀립니다. 

또한 하기 코드의 프로토콜에는 별도의 오류 체크를 포함하지 않았지만 통신 오류를 줄이기 위해 Check Sum 이나 CRC 등의 오류 체크를 포함할 수도 있습니다. 

#define     STX             0x02
#define     ETX             0x03
#define     BUFFER_MAX      20              // 수신버퍼 최대 용량 

const int COMM_CTRL        = 3 ;			// MAX485 RX/TX Control

volatile int Comm_Index = 0 ;					// Receive buffer Index Pointer 
volatile boolean stringComplete = false ;   	// 수신 데이타가 다 들어왔는지 확인한다.
volatile boolean serial_start = false ;

char Receive_Buffer[BUFFER_MAX] ;
char Send_Buffer[7] = {STX, 0x30, 0x31, 'I', 'O', 'K', ETX} ;	            // Serial 송신 버퍼

//--------------------------------------------------------------------------------
void setup() 
{
    Serial.begin(9600);         // set serial communication (9600 bps)

    pinMode(COMM_CTRL, OUTPUT) ;  // RS485 통신의 경우 송,수신 전환 단자제어 
    digitalWrite(COMM_CTRL, LOW);    
}
//--------------------------------------------------------------------------------
void loop() 
{
    if(stringComplete == true)      // 통신 패킷이 모두 들어왔다. 
    {
        if(Receive_Buffer[1] == 0x30 && Receive_Buffer[2] == 0x31)    // 자신의 데이타가 맞다. 
        {
            switch(Receive_Buffer[3])   // 수신된 명령어???
            {
                case 'I' : Initialize() ;       // initialize  
                           break ;                            
                case 'P' : function1() ;
                           break ;
                case 'R' : function2() ;
                           break ;
                case 'T' : function3() ;
                           break ;
                case 'S' : function4() ;
                           break ;                           
                default  : Error() ;
                           break ;
            }
            
            Send_Action_Result() ;   // 수신에 대한 응답 메시지 송신
        }
        memset(Receive_Buffer, 0x00, sizeof(Receive_Buffer)) ;  // 수신 버퍼 Clear 
        stringComplete = false ;   // 시리얼 입력에 대한 작업이 종료 되었다. 
    }
}
//--------------------------------------------------------------------------------
void Send_Action_Result(void)
{
  /****************************************
    function : 시리얼 포트로 수신결과에 대한 응답을 보낸다.
  ****************************************/
    int count ;

    digitalWrite(COMM_CTRL, HIGH)  ;    // RS485 통신칩의 송/수신 컨트롤 단자 제어용입니다. 
                                        // 경우에 따라 없을 수도 있습니다. 
    for (count = 0 ; count < 7 ; count++)
    {
        Serial.write(Send_Buffer[count]) ;    // 송신 버퍼의 내용을 시리얼로 전송합니다.
    }

    delay(10) ;		// RS485 통신의 경우 이걸 해 주어야만 컨트롤 단자가 LOW 로 떨어지지 않는다.

    digitalWrite(COMM_CTRL, LOW)  ;
}
//------------------------------------------------------------------------------------
void function1() {} 
void function2() {} 
void function3() {} 
void function4() {} 
//------------------------------------------------------------------------------------
void Error(void)
{
    Send_Buffer[3] = 'N' ;    // NAK 반송  
    Send_Buffer[4] = 'A' ;    
    Send_Buffer[5] = 'K' ;
}
//-------------------------------------------------------------------------------- 
void Initialize(void)
{
    /* 명령어 수행 루틴 작성 */

    Send_Buffer[3] = 'I' ;    // 반송 명령어 
    Send_Buffer[4] = 'O' ;    // OK : 명령을 정상적으로 수행했다. 
    Send_Buffer[5] = 'K' ;
}
//-------------------------------------------------------------------------------- 
void serialEvent()   // 시리얼 포트의 입력 인터럽트 
{
    if (stringComplete == false)
    {
        char inChar = (char)Serial.read() ;

        if (inChar == STX && serial_start == false)      // 시리얼 포트로 데이타가 들어오기 시작 
        {
            serial_start = true ;
            Comm_Index = 0 ;
        }

        Receive_Buffer[Comm_Index] = inChar ;

        if (Receive_Buffer[Comm_Index] == ETX)          // 시리얼 포트로 데이타가 모두 들어왔다.        
        {
            stringComplete = true ;
            serial_start = false ;
        }

        Comm_Index ++ ;

        if (Comm_Index >= BUFFER_MAX) Comm_Index = 0 ;
    }
}
//--------------------------------------------------------------------------------

 

반응형

+ Recent posts