■LCD

1.     회로도를 본다.

 

RS는 Instruction mode OR Data mode, E는 Enable 등.. 인걸 알 수 있다.

2.     DataSheet를 본다 - 타이밍

1. R/W : High, E : Low
2. RS : High or Low
3. R/W : High -> Low
 ------- 40nSec이상 delay
4. E : Low -> High
 ------- 150nSec이상 delay
 5. Data Bus
 ------- 80nSec이상 delay
 6. E : High -> Low
 ------- 10nSec이상 delay

데이터시트를 보면 Max가 없기에 Critical하게 꼭 맞춰줄 필요는 없어 보인다.

이러한 최소한의 딜레이가 필요하다. 그렇지 않으면 원하는 값으로 이루어지지 않음. Read mode에서는 RW쪽만 다르다.

 

3.     Instructions 해석

Note : Fiunction Set 5x11 dots는 4BIT일 경우만 사용 가능하다. 현재는 8bit,2-line,5x8로 set

그리고 실제 LCD는 5x7처럼 보이는데 커서가 1을 차지하여 5x8이다.

또한 Instruction후 딜레이 필요.

AND DDRAM은 DB7은 항상 set이여서 시작주소가 0x80이다. 1-Line과 2-Line이 bit수와 주소가 다르다.

#include "avr/io.h"
#include "avr/iom128.h"
#include "util/delay.h"
/*
	RS : Instruction mode VS Data mode?
	(LCD_controller VS LCD_data)
	E : Enable
*/
void LCD_controller(unsigned char control)
{
	_delay_ms(40);
	PORTG = 0x00; // clear.
	_delay_us(0.04); //RW & RS Setup time is 40ns min.
	PORTG |= 0x01; // G set.			Enable
	_delay_us(0.15); //Data Setup time is 80ns min.
	PORTA = control; // Data input.
	_delay_us(0.08); // valid data is 130ns min.
	PORTG = 0x0;// RS set. RW set. G clear.
	_delay_us(0.01);
}

void LCD_data(unsigned char Data)
{
	_delay_ms(1);
	PORTG = 0x04; //RS set. RW clear. G clear.
	_delay_us(0.04); //RW & RS Setup time is 40ns min.
	PORTG = 0x05; // E set.
	_delay_us(0.15); //Data Setup time is 80ns min.
	PORTA = Data; // Data input.
	_delay_us(0.08); // valid data min is 130ns.
	PORTG = 0x0; // RS clear. RW set. G clear.
	_delay_us(0.01);
}

void LCD_string(unsigned char address, unsigned char *ptr)
{
	int i=0;
	LCD_controller(address); // LCD display start position
	while(*ptr)
	{
		if(address+i == 0x90)
		LCD_controller(0xc0); // second line display
		
		LCD_data(*ptr);
		i++;
		ptr++;
	}
}

void LCD_initialize(void)
{

	/* 8bit interface mode */
	LCD_controller(0x38); // Function set. Use 2-line, display on.
	_delay_us(40); // wait for more than 39us.
	LCD_controller(0x0f); // Display ON/OFF Control. display,cursor,blink on
	_delay_us(40); // wait for more than 39us.
	LCD_controller(0x01); // Display Clear.
	_delay_ms(1.53); // wait for more than 1.53ms.
	LCD_controller(0x06); // Entry Mode Set. I/D increment mode, entire shift off
}

int main()
{
	DDRG = 0x07; // Control_bit
	DDRA = 0xff; // Data_bit

	LCD_initialize(); 
	LCD_string(0x80, "Hello World!!!! LCD TEST..12345678987654321"); // Start address is 0x80(0,0)

	
	while(1)
	{
	/*
	LCD_controller(0x1c);//화면 그대로 right
	LCD_controller(0x18);//화면 그대로 left
	_delay_ms(5000);
	*/
	}
	return 0;
}

'kernel Driver' 카테고리의 다른 글

[Atmega128]PWM(Buzzer)  (0) 2019.04.30
GPIO를 이용한 I2C구현  (0) 2019.04.24

■PWM

 Timer기능 안에 PWM mode가 있다. 주로 쓰는 것이 Fast Pwm mode.

PWM(Pulse Width Modulation) 신호는 디지털 소스를 사용하여 아날로그 신호를 생성하는 방법입니다. PWM 신호는 듀티 사이클과 주파수라는 가지 주요 구성 요소로 구성됩니다.

 듀티 사이클은 신호가 하이(또는 켜짐) 상태에 있는 시간을 1 사이클을 완료하는 걸리는 시간의 백분율로 나타냅니다.

 

, Buzzer에서 PWM 높은 것은 음향이 높은 , 듀티 사이클이 짧을수록 높은 음이 나옵니다.

PWM 신호는 다양한 제어 어플리케이션에 사용됩니다. 용도는 DC 모터 제어이지만 밸브, 펌프, 유압 장치 기타 기계 부품을 제어하는 ​​곳에도 사용할 있습니다.

 

 

TCCR0 prescale TCNT0,OCR0 값으로 클럭이 조정된다

TCNT0 주파수(Frequency) 조절할 있다.

OCR0 듀티 사이클 조절할 있다.

 

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#include <util/delay.h>


volatile int state, tone;
char f_table[8] = {17, 43, 66, 77, 97, 114, 117, 137};


ISR(TIMER0_OVF_vect)                               
{
	 PORTB ^= 1 << 4;

     TCNT0 = f_table[tone];
}

int main()
{
	DDRD = (0x00 << 7);
             int i=0;
             DDRB = 0x10;                    
             TCCR0 = 0x03;                  
             TIMSK = 0x01;                 
        
             sei();                               
             while(1) {
				  if (!(PIND & ( 1<<PIND7 )) )//버튼이 눌러졌다면
				  {
					   tone = f_table[rand()%8]; 
					   OCR0 = rand()%255;          
				  }
                         
             };                  
}

'kernel Driver' 카테고리의 다른 글

[Atmega128]Character LCD  (0) 2019.04.30
GPIO를 이용한 I2C구현  (0) 2019.04.24

TODO : GPIO 이용하여 RTC 디바이스를 사용하기 위해 RTC I2C통신을 한다.(, 실제 I2C통신을 사용할 주어진 함수를 이용한다.)

 

*SDA: data, SCL : 디바이스 신호 동기화에 사용되는 클럭.

*SCL high data 읽고 Low SDA 바뀐다. 이런식으로 통신

(i2c 데이터 통신 중에는 클럭이 high 시그널일 때에는 데이터(SDA) 시그널이 변경되면 안된다. 이러한 규칙으로 인해 클럭이 high 상태에서는 데이터를 안정적으로 읽는 것을 보장한다.)

 

*Master cpu, slave 디바이스들

 

*Ack 응답 Ack : 0, 무응답 Ack :1(? – Need to check)

 

1. 회로도 분석

 

 

2. Data Sheet 보고 set configuration

 

DDKIomuxSetPinMux DDKGpioSetConfig 등등

3.RTC chip DataSheet 분석

 

=> Slave address를 알 수 있다.

=> data를 보낼 때 여러개의 data를 연달아 보낼 수 있다. 단 1 < 1s 조건 ->1s이상 해본 결과 처음Write 할때 만 이상하게 들어가고 다시 Write하면 제대로잘 들어감

=> R/W mode 방식

=>  data 보낼 여러개의 data 연달아 보낼 있다. 1 < 1s 조건

=>  Lasty data byte 지금은 쓰지 않았지만 레지스터에 여러 데이터를 넣는 경우도 있는 같다.

그리고 Read mode에서 set register read data 사이에 Start, Stop 존재 해야하며 10초정도의

시간이 지나도 읽을 있더라.(자세히 모르겟다)

 

 

 

 

 **주요 이슈

1. DataPin Read 없었음

-> DDK_GPIO_DIR_IN 설정하지 않았음, R/W 마다 신경 써야한다

2. Data Read하는 부분 여러 Read하는데 방법을 잘모르겠으며 처음 한번만 잘나오고 뒤에는 쓰래기값이 나온다.

 - 문제점 1 : 

      int bin[8]={0,};

           =>bin 배열이 clear 되지 않아서 전에 쓰던 값이 들어가는 문제, 전역변수에서 지역변수로 바꿔줌

 - 문제점 2 : Write와 Read의 Data를 읽을 때 Regiter의 주소는 시작하는 주소 하나만 넣어서 8bit씩 읽으면 순차적으로 읽거나 쓸 수 있다.

 

#define myd_speed (10)



void Start()

{

        DDKGpioWriteDataPin(DDK_GPIO_PORT4, 13, 0);

        Sleep(myd_speed);

        DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 0);

        Sleep(myd_speed);

        //Start 신호-> SCL이High 상태일때, SDA이Low로변하면Start

}

void Stop()

{

        DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 1);

        Sleep(myd_speed);

        DDKGpioWriteDataPin(DDK_GPIO_PORT4, 13, 1);

        Sleep(myd_speed);

        //Stop 신호-> SCL이High 상태일때, SDA이High로변하면Stop

}

void SCL_Clock()

{

        DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 1);

        Sleep(myd_speed);

        DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 0);

        Sleep(myd_speed);

}





//SDA 8bit Data

void Clock_data(int data)

{

    int bin[8]={0,};    //주소를역순으로보내기위한배열



    int position = 7;

    while(data != 0){//bin 배열Clear후저장

        bin[position] = data %2;

        data /= 2;

        position--;

    }

            

    for(int i=0;i<8;i++){

        DDKGpioWriteDataPin(DDK_GPIO_PORT4, 13, bin[i]);

        SCL_Clock();

    }

}



void Read_data(int reg_addr)

{

        UINT32 pinVal;

        RETAILMSG(1, (L"[ I2C Read !!! ] "));

        Start();



        Clock_data(0xD0);//1101000 (Slave address + Write bit)(7bit + 1bit)

        SCL_Clock();//Ack



        Clock_data(reg_addr);//input data(data address)

        SCL_Clock();//Ack



        Stop();





        for(int i=0;i<3;i++){//03h ~ 05h만읽는다.

            Start();



            Clock_data(0xD1);//1101001 (Slave address + Read bit)

            SCL_Clock();//Ack





            /*            print            */

            RETAILMSG(1, (L"Read Data : ["));

            for(int i=0;i<8;i++){

                DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 1);

                Sleep(myd_speed);

                DDKGpioSetConfig(DDK_GPIO_PORT4, 13, DDK_GPIO_DIR_IN, DDK_GPIO_INTR_NONE);

                //Set DDK_GPIO_DIR_IN For Read mode enable



                DDKGpioReadDataPin(DDK_GPIO_PORT4, 13, &pinVal);

                RETAILMSG(1, (L"%d",pinVal));



                DDKGpioSetConfig(DDK_GPIO_PORT4, 13, DDK_GPIO_DIR_OUT, DDK_GPIO_INTR_NONE);

                DDKGpioWriteDataPin(DDK_GPIO_PORT4, 12, 0);

                Sleep(myd_speed);

            }

            RETAILMSG(1, (L"]"));

            SCL_Clock();//Ack



            Stop();

        }

}



BOOL MYD_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, 

                   DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,

                   PDWORD pdwActualOut)

{

    BOOL bRet = FALSE;



    switch(dwCode){

        case 1:

            /*                Init            */

            DDKIomuxSetPinMux(DDK_IOMUX_PIN_KEY_COL3, DDK_IOMUX_PIN_MUXMODE_ALT5, DDK_IOMUX_PIN_SION_REGULAR);

            //datasheet -> IOMUXC_SW_MUX_CTL_PAD_KEY_COL3 의gpio4_12(SCL)( ALT5) 설정(enable)

            DDKIomuxSetPinMux(DDK_IOMUX_PIN_KEY_ROW3, DDK_IOMUX_PIN_MUXMODE_ALT5, DDK_IOMUX_PIN_SION_REGULAR);

            //datasheet -> IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3 의gpio4_13(SDA)( ALT5) 설정(enable)



            DDKGpioSetConfig(DDK_GPIO_PORT4, 12, DDK_GPIO_DIR_OUT, DDK_GPIO_INTR_NONE);

            DDKGpioSetConfig(DDK_GPIO_PORT4, 13, DDK_GPIO_DIR_OUT, DDK_GPIO_INTR_NONE);

            //12, 13 bit Write mode enable

            



            RETAILMSG(1, (L"[ I2C Write !!! ] "));//Slave address : 1101000(RTC -> Chip : PCF8523TS/1 ) , Read : 1 Write : 0

            Start();

            

            Clock_data(0xD0);//1101000 (Slave address + Write bit)(7bit + 1bit)

            SCL_Clock();//Ack



            /*

            03h : Seconds(data address)

            04h : Minutes(data address)

            05h : Hours(data address)

            */

            Clock_data(0x03);

            SCL_Clock();//Ack





            Clock_data(0x00);//0초[7]:clock integrity is guaranteed, [6-0] 

            SCL_Clock();//Ack

            Clock_data(0x10);//10분[7]: unused, [6-4]: ten's place, [3-0]: unit place

            SCL_Clock();//Ack

            Clock_data(0x13);//13시[7-6]: unused, 12mode [5] : 0-AM,1-PM, [4]: ten's place,[3-0]: unit place

            SCL_Clock();//Ack                       24mode [5-4]: ten's place,[3-0]: unit place



            Stop();

            

            break;

        case 2:

            Read_data(0x03);



            break;

        case 3:



            break;



    }

      return bRet;

}

'kernel Driver' 카테고리의 다른 글

[Atmega128]Character LCD  (0) 2019.04.30
[Atmega128]PWM(Buzzer)  (0) 2019.04.30

+ Recent posts