03_ MCP23008
C_Atmega128

03_ MCP23008

728x90
더보기

MCP23008의 회로를 수정하여 상위 4비트에 LED 4개를 연결하여 다음 프로그램을 ㅈ가성하시오

 

GP0의 스위치가 눌리면 4LED를 좌로 시프트

GP1의 스위치가 눌리면 4LED를 우로 시프트

GP2의 스위치가 눌리면 2LED를 교대로 점멸

GP3의 스위치가 눌리면 4개 점멸

 

 

위가 해결해야하는 문제고, 첫번째 문제는 7segment를 사용하여

회로도

다음과 같이 만드는 예제였다. 

우선 위 예제코드는 다음과 같았다.

 

/*
 * twi_scp23008.c
 *
 * Created: 2021-10-29 오전 10:29:42
 * Author: 정민규
 */
#define _USE_SAFTY_TWI_
#include <mega128.h>
#include <delay.h>
#include "TWI.h"


#define MCP23008ADDR (unsigned char) 0x40
#define GPIO (unsigned char) 0x09
#define IODIR (unsigned char) 0x00  


/* 
enum MCP23008_REG_ADDRESS
     {
        IODIR =  0x00,
        IPOL =   0x01, 
        GPINTEN = 0x02,
        DEFVAL = 0x03,   
        INTCON = 0x04,    
        IOCON =  0x05,     
        GPPU = 0x06,        
        INTF = 0x07,         
        INTCAP = 0x08,        
        GPIO =  0x09,
        OLAT = 0x0A,
     }  
     
*/ 
unsigned char MCP23008_I2C_Read(char devAddr, char regAddr, unsigned char* data)
{
    unsigned char rec_data;
    unsigned char ret_err = 0;
    ret_err = TWI_Start();
    if(ret_err!=0) return ret_err; 
    ret_err = TWI_Write_SLAW(devAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Write_Data(regAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Restart();
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Write_SLAW(devAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Read_Data_NACK(&rec_data);
    if(ret_err!=0) return ret_err;
    TWI_Stop();
    *data = rec_data;
    return ret_err;
}

 

unsigned char MCP23008_I2C_Write(char devAddr,char regAddr, char data)
{
    unsigned char ret_err = 0;
    ret_err = TWI_Start();
    if(ret_err!=0) return ret_err;  
    ret_err = TWI_Write_SLAW(devAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Write_Data(regAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Write_Data(data);
    if(ret_err!=0) return ret_err;
    TWI_Stop();
    return ret_err;
    
}

void MCP23008_Init(void)
{
    MCP23008_I2C_Write(MCP23008ADDR,IODIR,0x0F);
    delay_ms(10);
}


void main(void)
{
    unsigned char keyInput;
    unsigned char keyOutput;
    unsigned char fnd;
    unsigned char ret_err = 0;
    
    Init_TWI();
    MCP23008_Init();
    
while (1)
    {
        
        ret_err = TWI_Master_Receive_ExDevice(MCP23008ADDR, GPIO, &keyInput);
        if(ret_err == 0)
        {
            fnd = keyInput;
            keyOutput = (0x0F)|(fnd << 4);
            
            delay_ms(1);
            ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, keyOutput);
            delay_ms(100);
        }
        

    }
}

 

이렇게 보니까 짧고 간단해보이는데 진짜 문제가 많았다. 공부했던 TWI 헤더를 정말 몇시간을 들여다본지 모르겠다. 결국 내가만든  MCP23008_I2C_Read함수는 사용해보지도 못했다. TWI헤더안의 내용이랑 똑같은데 왜 작동안되는지 모르겠다. 

 

여러 시간동안 에러모드없으면 동작할지 다 빼보고 동작해보는 기염(?)을 토했지만 결국 해결하긴 했다. 지금은 에러모드 있을때 없을때 모두 동작한다.

 

아무튼 위 내용이 원래 내용은 아니고, 이제 입력받은 GPIO의 하위포트를 상위포트에 입력받아 각 LED의 기능을 동작하게 해 보았다.

 

/*
 * twi_scp23008.c
 *
 * Created: 2021-10-29 오전 10:29:42
 * Author: 정민규
 */
#define _USE_SAFTY_TWI_
#include <mega128.h>
#include <delay.h>
#include "TWI.h"


#define MCP23008ADDR (unsigned char) 0x40
#define GPIO (unsigned char) 0x09  //enum사용시 자꾸 에러가 떠서 수정하였습니다.
#define IODIR (unsigned char) 0x00  

unsigned char MCP23008_I2C_Read(char devAddr, char regAddr, unsigned char* data)
{   //MCP23008 의 Read를 담당합니다. 하지만 저는 헤더파일의 함수를 사용하였습니다.
    unsigned char rec_data;
    unsigned char ret_err = 0;
    ret_err = TWI_Start();
    if(ret_err!=0) return ret_err; 
    ret_err = TWI_Write_SLAW(devAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Write_Data(regAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Restart();
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Write_SLAW(devAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Read_Data_NACK(&rec_data);
    if(ret_err!=0) return ret_err;
    TWI_Stop();
    *data = rec_data;
    return ret_err;
}

 

unsigned char MCP23008_I2C_Write(char devAddr,char regAddr, char data)
{  //date를 쓰는 함수
    unsigned char ret_err = 0;
    ret_err = TWI_Start();
    if(ret_err!=0) return ret_err;  
    ret_err = TWI_Write_SLAW(devAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Write_Data(regAddr);
    if(ret_err!=0) return ret_err;
    ret_err = TWI_Write_Data(data);
    if(ret_err!=0) return ret_err;
    TWI_Stop();
    return ret_err;
    
}

void MCP23008_Init(void)
{ //MCP23009 초기함수
    MCP23008_I2C_Write(MCP23008ADDR,IODIR,0x0F);
    delay_ms(10);
}


void main(void)
{
    unsigned char keyInput;
    unsigned char keyOutput;
    unsigned char fnd;
    unsigned char ret_err = 0;
    char i;
    
    Init_TWI();
    MCP23008_Init();
    
while (1)
    {
        //keyInput 값에 GPIO하위포트 값들을 받아옵니다.
        ret_err = TWI_Master_Receive_ExDevice(MCP23008ADDR, GPIO, &keyInput);
        if(ret_err == 0)
        {
            fnd = keyInput;
            keyOutput = (0x0F)|(fnd << 4);
            
            delay_ms(1);
            //ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, keyOutput); 
            switch(keyOutput)   //각 스위치문에 해당하는 동작을 실행합니다.
            {                
                case 0b11101111: 
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b01111111 << i);
                     delay_ms(100);
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b10111111 << i);
                     delay_ms(100);
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b11011111 << i);
                     delay_ms(100);
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b11101111 << i);
                     delay_ms(100);
                   

                break;  
                case 0b11011111: 
                     for(i = 0 ; i<4;i++)
                     {
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b11101111 << i);
                     delay_ms(100);
                     }

                break;
                case 0b10111111: 
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b01011111 << i);
                     delay_ms(100);
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b10101111 << i);
                     delay_ms(100);

                break;
                case 0b01111111: 
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b11111111 << i);
                     delay_ms(100);
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b00001111 << i);
                     delay_ms(100); 

                break;
                

default:
                     ret_err = MCP23008_I2C_Write(MCP23008ADDR, GPIO, 0b11111111 << i);
                     delay_ms(100);
                break;
            }   
            delay_ms(100);
        }
        

    }
}

 

 

확실히 C를 공부할때면 python이나 다른 언어를 공부할때보다 투박한 맛이 있는 거 같다. 이리저리 알고리즘 쓴다고 머리굴릴때보다 단순하게 하는것이 이로보나 저로보나 나을 때가 있는 것 같다.

728x90

'C_Atmega128' 카테고리의 다른 글

02_ TWI_SRF02의 이용  (0) 2021.10.30
01_TWI  (0) 2021.10.30