BASIC4MCU | 질문게시판 | atmega128 CLCD
페이지 정보
작성자 릴를 작성일2023-12-03 17:18 조회3,636회 댓글2건본문
전체 코드입니다.
displayMessage(Smart_fan, Press_Switch); 처음 여기서 출력한 문자열에서 LCD가 바뀌질 않습니다.
블루투스 코드를 넣기 전에 스위치 버튼을 이용해 인터럽트로 선풍기 속도 조절, led 출력, LCD 출력까지 다 되었는데
블루투스 코드를 넣으면 버튼을 눌러도 LCD가 처음 문자열에서 바뀌지 않습니다.
또한 블루투스를 이용해서 속도 조절, led 출력은 되는데 마찬가지로 LCD가 문제입니다
//////////////코드////////////////////////
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
// 초음파 부분
#define SOUND_VELOCITY 340UL // 소리 속도 (m/sec)
#define TRIG 6 // HC-SR04 Trigger 신호 (출력)
#define ECHO 7 // HC-SR04 Echo 신호 (입력)
// CLCD Command & Data
#define BIT4_LINE2_DOT58 0x28 // 4 Bit Mode, 2 Lines, 5x8 Dot
#define DISPON_CUROFF_BLKOFF 0x0C // Display On,Cursor Off, Blink Off
#define DISPOFF_CUROFF_BLKOFF 0x08 // Display Off,Cursor Off, Blink Off
#define INC_NOSHIFT 0x06 // Entry Mode, Cursor Increment
#define NULL 0x00
// Display No Shift
#define DISPCLEAR 0x01 // Display Clear, Address 0
// Position, Cursor 0
#define CUR1LINE 0x80 // Cursor Position Line 1 First
#define CUR2LINE 0xC0 // Cursor Position Line 2 First
#define CURHOME 0x02 // Cursor Home
#define E_BIT 0x04 // Enable Bit #
#define RW_BIT 0x03 // Read Write Bit #
#define RS_BIT 0x02 // Register Select Bit #
void initMotor();
void initInterrupt();
void CLCD_cmd(char); // 명령어 전송 함수
void CLCD_data(char); // 데이터 Write 함수
void CLCD_puts(char *); // 문자열 처리 함수
void display_fnd(unsigned int value); // FND Display 함수
void init_CLCD(); // 초기화
void putchar1(char c); //문자를 송신(Transmit)하는 함수
char available(); // 문자 입력을 확인하는 함수
char getchar1(); // 문자를 수신(receive)하는 함수
void init_uart1(); // UART1 초기화 함수
char Smart_fan[] = "Smart fan"; // 시작 메시지(1열)
char Press_Switch[] = "Press Switch!"; // 시작 메시지(2열)
char Sw4_press[] = "SW4"; // Sw4 선풍기
char High_fan[] = "HIGH FAN";
char Sw3_press[] = "SW3"; // Sw3 선풍기
char Middle_fan[] = "MIDDLE FAN";
char Sw2_press[] = "SW2";; // Sw2 선풍기
char Low_fan[] = "LOW FAN";
char Sw1_press[] = "SW1"; // Sw1 선풍기
char Stop_fan[] = "STOP";
char blueth1[] = "BLUETOOTH1";
char blueth2[] = "BLUETOOTH2";
char blueth3[] = "BLUETOOTH3";
char blueth4[] = "BLUETOOTH4";
// Motor Speed
#define STOP_SPEED 0
#define LOW_SPEED 77
#define MID_SPEED 153
#define HIGH_SPEED 230
// 모터 제어
#define MOTOR_CW 0xb0
#define MOTOR_CCW 0x70
#define MOTOR_BRAKE 0xd0
#define MOTOR_STOP 0x30
#define MOTOR_STANDBY 0x00
volatile int motorSpeed = STOP_SPEED;
volatile int ledState = 0; // LED 상태를 저장
volatile uint8_t interruptFlag = 0; // 인터럽트 플래그
void setMotorSpeed(int speed) {
OCR2 = speed;
}
void initMotor() {
DDRB = 0xf0;
PORTB = MOTOR_STANDBY;
TCCR2 = 0x6b;
}
void initInterrupt() {
EICRA = 0x0f; //INT0, INT1
EICRB = 0x0f;
EIMSK = 0x33;
sei(); // 전역 인터럽트 활성화
}
void putchar1(char c) // 1 문자를 송신(Transmit)하는 함수
{
while(!(UCSR1A & (1<<UDRE1))); // 즉,1을 5번 왼쪽으로 shift한 값이므로 0x20과 &
UDR1 = c; // 1 문자 전송, 송신 데이터를 UDR1에 넣음
}
char available() // 문자 입력을 확인하는 함수
{
if (UCSR1A & (1<<RXC1)) // 입력된 문자가 있는지 확인
return(1); // 입력된 문자가 있으면 "1"의 값으로 return
else return(0); // 입력된 문자가 없으면 "0"의 값으로 return
}
char getchar1() // 1 문자를 수신(receive)하는 함수
{
return(UDR1); // 1 문자 수신, UDR1에서 수신 데이터를 가져옴
}
void init_uart1() // UART1 초기화 함수
{
UCSR1B = 0x18; // 송신 Transmit(TX), Receive(RX) Enable
UCSR1C = 0x06; // UART Mode, 8Bit Data, No Parity, 1 Stop Bit
UBRR1H = 0; // Baudrate 세팅
UBRR1L = 8; // 16Mhz, 115200 baud (주의 :초기 셋팅 값 확인)
}
void displayMessage(char* line1, char* line2) {
CLCD_cmd(CUR1LINE);
CLCD_puts(line1);
CLCD_cmd(CUR2LINE);
CLCD_puts(line2);
}
ISR(INT0_vect) {
// INT0 핀 (PD0) 인터럽트 처리
motorSpeed = HIGH_SPEED;
ledState = 0x01;
}
ISR(INT1_vect) {
// INT1 핀 (PD1) 인터럽트 처리
motorSpeed = MID_SPEED;
ledState = 0x02;
}
ISR(INT4_vect) {
// INT4 핀 (PE4) 인터럽트 처리
motorSpeed = LOW_SPEED;
ledState = 0x04;
}
ISR(INT5_vect) {
// INT5 핀 (PE5) 인터럽트 처리
motorSpeed = STOP_SPEED;
ledState = 0x08;
}
int main(void)
{
char c; DDRA = 0xff;
DDRD = 0xfc;
DDRC = 0xff; // CLCD PORT(data & command)
DDRE = 0x00; // SW1, sw2, sw3, sw4가 연결된 포트 E는 입력으로 선언
initMotor();
initInterrupt();
init_CLCD(); // CLCD 초기화
PORTB = MOTOR_CW;
displayMessage(Smart_fan, Press_Switch);
init_uart1(); // UART1 초기화
while (1) {
if (available()) // 만약 입력된 문자가 있으면
{
c = getchar1(); // 입력된 문자를 스마트폰으로부터 받아서
switch(c) // 명령의 종류에 따라 아래를 실행
{
case '1' : motorSpeed = STOP_SPEED;
ledState = 0x08; break; // 선풍기 STOP
case '2' : motorSpeed = LOW_SPEED;
ledState = 0x04; break; // 선풍기 STOPbreak; // 선풍기 LOW
case '3' : motorSpeed = MID_SPEED;;
ledState = 0x02; break; // 선풍기 MIDDLE
case '4' : motorSpeed = HIGH_SPEED;
ledState = 0x01; break; // 선풍기 HIGH
case '5' :
switch(motorSpeed)
{
case STOP_SPEED: putchar1('1'); break;
case LOW_SPEED: putchar1('2'); break;
case MID_SPEED: putchar1('3'); break;
case HIGH_SPEED: putchar1('4'); break;
}
}
}
setMotorSpeed(motorSpeed);
// LED 디스플레이 (선택된 속도에 따른 LED 표시)
if(motorSpeed == STOP_SPEED)
displayMessage(Sw1_press, Stop_fan);
else if(motorSpeed == LOW_SPEED)
displayMessage(Sw2_press, Low_fan);
else if(motorSpeed == MID_SPEED)
displayMessage(Sw3_press, Middle_fan);
else if(motorSpeed == HIGH_SPEED)
displayMessage(Sw4_press, High_fan);
PORTA = ledState;
// 딜레이 추가 (필요에 따라 조절)
_delay_ms(100);
}
}
void init_CLCD() // LCD 초기화
{
_delay_ms(50); // 전원 인가후 CLCD 셋업 시간
PORTC = 0x00; // 데이타 clear
CLCD_cmd(BIT4_LINE2_DOT58); // 4 Bit Mode, 2 Lines, 5x8 Dot
CLCD_cmd(DISPON_CUROFF_BLKOFF); // Display On, Cursor Off, Blink Off
CLCD_cmd(INC_NOSHIFT); // Entry Mode, Cursor Increment,
// Display No Shift
CLCD_cmd(DISPCLEAR); // Display Clear, Address 0
_delay_ms(2); // 디스플레이 클리어 실행 시간 동안 대기
}
int read_distance() // 거리가 0이 아니면 선풍기 온으로 변경(아직 x)
{
unsigned int distance = 0;
while(1)
{
TCCR1B = 0x03; // Counter/Timer 1 클록 4us
PORTA &= ~(1<<TRIG); // Trig = LOW
_delay_us(10);
PORTA |= (1<<TRIG); // Trig = HIGH
_delay_us(10);
PORTA &= ~(1<<TRIG); // Trig = LOW
while(!(PINA & (1<<ECHO))) // wait until Echo = HIGH
;
TCNT1 = 0x0000; // Counter/Timer 1 값 초기화(=0)
while (PINA & (1<<ECHO))
;
TCCR1B = 0x00; // Counter/Timer 1 클록 정지
distance = (unsigned int)(SOUND_VELOCITY * (TCNT1 * 4 / 2) / 1000);
// 거리 = 속도 * 시간
if (distance < 300) // 30cm 이내 접근?
{
//set_MotorSpeed(HIGH_SPEED);
}
else if (distance < 600)// 60cm 이내 접근?
{
// set_MotorSpeed(MID_SPEED);
}
else if (distance < 1000) // 1m 이내 접근?
{
// set_MotorSpeed(LOW_SPEED);
}
else if (distance > 1000)
{
// set_MotorSpeed(STOP_SPEED);
}
}
}
void CLCD_puts(char *ptr)
{
while(*ptr != NULL) // 문자열이 마지막(NULL)인지 검사
CLCD_data(*ptr++); // 마지막이 아니면 1문자 디스플레이
}
void CLCD_data(char data)
{
PORTD = 0x04; // 0b0000100, E(bit4)=0, R/W(bit3)=0,
// RS(bit2)=1, Write 사이클, 데이터 모드
_delay_us(1); // Setup Time
PORTD = 0x14; // 0b00010100, E(bit4)=1, R/W(bit3)=0,
// RS(bit2)=1 Enable
PORTC = data & 0xf0; // upper 4bit
PORTD = 0x04; // 0b0000100, E(bit4)=0, R/W(bit3)=0,
// RS(bit2)=1, Write 사이클, 데이터 모드
_delay_us(2); // Hold & Set Time
PORTD = 0x14; // 0b00010100, E(bit4)=1, R/W(bit3)=0,
// RS(bit2)=1 Enable
PORTC = (data << 4) & 0xf0; // lower 4bit
PORTD = 0x04; // 0b00000100, E(bit4)=0, R/W(bit3)=0,
// RS(bit2)=1 사이클 종료
_delay_ms(1); // Hold Time & Execution Time
}
void CLCD_cmd(char cmd)
{
PORTD = 0x00; // 0b0000000, E(bit4)=0, R/W(bit3)=0,
// RS(bit2)=0, Write 사이클, 명령어 모드
_delay_us(1); // Setup Time
PORTD = 0x10; // 0b00010000, E(bit4)=1, R/W(bit3)=0,
// RS(bit2)=0 Enable
PORTC = cmd & 0xf0; // upper 4bit 전송
PORTD = 0x00; // 0b0000000, E(bit4)=0, R/W(bit3)=0,
// RS(bit2)=0, Write 사이클, 명령어 모드
_delay_us(2); // Hold & Setup Time
PORTD = 0x10; // 0b00010000, E(bit4)=1, R/W(bit3)=0,
// RS(bit2)=0 Enable
PORTC = (cmd << 4) & 0xf0; // lower 4bit 전송
PORTD = 0x00; // 0b00000100, E(bit4)=0, R/W(bit3)=0,
// RS(bit2)=0 사이클 종료
_delay_ms(1); // Hold Time & Execution Time
}
댓글 2
조회수 3,636master님의 댓글
master 작성일
DDRC = 0xff; // CLCD PORT(data & command)
포트C에 데이터와 컴맨드를 사용한다고 주석이 달려있으나
lcd 관련 함수를 보니
포트c와 포트d 두개의 포트를 나누어서 사용하고 있습니다.
포트d를 사용하지말고 포트c만을 사용해서 lcd를 구동하도록 변경 해보세요
master님의 댓글
master 작성일
https://cafe.naver.com/circuitsmanual/5381
이 예제 참고해서 수정하면 될겁니다.