BASIC4MCU | 질문게시판 | atmega128 블루투스를 이용한 LCD !! 도와주세요ㅠ
페이지 정보
작성자 이이잉 작성일2021-11-22 21:36 조회15,026회 댓글4건본문
#define F_CPU 16000000UL
#include <avr/io.h> // I/O 레지스터정의
#include <util/delay.h> // 시간지연함수
#include <stdio.h>
#include <avr/interrupt.h>
#include "LCD.h" // LCD 제어프로그램 헤더파일
int pump_speed;
volatile char* BT_Pump_Speed[10];
volatile unsigned char flag, data;
unsigned char get_data(void)
{
while(!(UCSR1A&0x80)); // 수신완료될때까지 대기
return UDR1;
}
ISR(USART1_RX_vect)
{
while(!(UCSR1A&0x20)); // 송신데이터를 받을 준비가 될때까지 대기
data = UDR1;
if(data == 'A')
flag = 'A';
if(data == 'B')
flag = 'B';
if(data == 'C')
flag = 'C';
if(data == 'S')
flag = 'S';
}
void tx_flag(char flag2) // data 수신
{
while((UCSR1A&0x20) == 0); // UDR 레지스터가 새로운 데이터 수신할 준비 X 이면 ↓ 실행 X
//while((UCSR1A&(1<<RXC1)));
UDR1 = flag2; // flag 변수에 저장된 값을 UDR1 레지스터에 저장
}
void str_in(char *pStr)
{
while(*pStr) tx_flag(*pStr++);
}
int main()
{
DDRE=0x08; // OC3A OUTPUT
TCCR3A=0x83;
TCCR3B=0x0B; // Fast PWM Freq.=250Hz(T=4ms)
LCDInit(); // LCD 초기화
//LCD 시작 화면
LCDMove(0,0);
LCDPuts(" BLUETOOTH AMBU ");
LCDMove(1,0);
LCDPuts(" START! ");
Delay_ms(3000);
LCDInit(); // LCD 초기화
//LCD 초기화면
LCDMove(0,0);
LCDPuts("SPEED : ");
LCDMove(1,0);
LCDPuts("PRESSURE : ");
Delay_ms(2000);
UCSR1A=0x00;
UCSR1B=0x98;
UCSR1C=0x06;
UBRR1H=0;
UBRR1L=103; // 16MHz = 103
SREG=0x80;
while(1)
{
if(flag =='A')
{
//동작
OCR3A=1023;
Delay_ms(1000);
pump_speed = OCR3A;
//BT출력
sprintf(BT_Pump_Speed, "%d", pump_speed); // 모터속도값->문자열
str_in("Air Pump Speed : ");
str_in(BT_Pump_Speed); //에어펌프 속도 출력
str_in("\n");
//LCD
LCDInit();//초기화
sprintf(BT_Pump_Speed, "%4d",pump_speed );
LCDMove(0,8);
LCDPuts(BT_Pump_Speed);
Delay_ms(1000);
//중지
OCR3A=0;
Delay_ms(500);
}
if(flag =='B')
{
//동작
OCR3A=800;
Delay_ms(1000);
pump_speed = OCR3A;
//BT출력
sprintf(BT_Pump_Speed, "%d", pump_speed); // 모터속도값->문자열
str_in("Air Pump Speed : ");
str_in(BT_Pump_Speed); //에어펌프 속도 출력
str_in("\n");
//LCD
LCDInit();//초기화
sprintf(BT_Pump_Speed, "%4d",pump_speed );
LCDMove(0,8);
LCDPuts(BT_Pump_Speed);
Delay_ms(1000);
//중지
OCR3A=0;
Delay_ms(500);
}
if(flag =='C')
{
//동작
OCR3A=600;
Delay_ms(500);
pump_speed = OCR3A;
//BT출력
sprintf(BT_Pump_Speed, "%d", pump_speed); // 모터속도값->문자열
str_in("Air Pump Speed : ");
str_in(BT_Pump_Speed); //에어펌프 속도 출력
str_in("\n");
//LCD
LCDInit();//초기화
sprintf(BT_Pump_Speed, "%4d",pump_speed );
LCDMove(0,8);
LCDPuts(BT_Pump_Speed);
Delay_ms(1000);
//중지
OCR3A=0;
Delay_ms(500);
}
if(flag =='S')
{
//중지
OCR3A=0;
Delay_ms(500);
//BT출력
str_in("STOP"); //에어펌프 속도 출력
str_in("\n");
//LCD
LCDInit();//초기화
LCDMove(0,0);
LCDPuts("!!!!!!STOP!!!!!!");
Delay_ms(1000);
}
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------------
위의 코드를 실행하면 while(1)문 이전에
LCD 시작 화면(BLUETOOTH AMBU+START!)가 3초 떠있는 뒤 이후 (SPEED : + PRESSURE : ) 가 출력된 뒤
이후 블루투스 값을 넣어줘도 LCD의 화면이 (SPEED : + PRESSURE : )으로 그대로 유지됩니다....
제 생각에는 블루투스와 관련되 함수인
UCSR1A=0x00;
UCSR1B=0x98;
UCSR1C=0x06;
UBRR1H=0;
UBRR1L=103;
SREG=0x80;
이후에 LCD의 동작이 안되는 것 같은데.. 도와주세요ㅠㅠㅠㅠㅠㅠㅠ
댓글 4
조회수 15,026master님의 댓글
master 작성일
LCD.h LCD.c
빠진 파일이 있으면 체크할 수가 없습니다.
이이잉님의 댓글
이이잉
<LCD.c>
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include "LCD.h"
// LCD 포트 주소
#define LCD_PORT PORTD
#define LCD_DDR DDRD
// 내부 함수
static void checkbusy(void);
static void write_command(char command);
static void write_data(char ch);
void LCDInit(void)
{
LCD_DDR = 0xFF; // LCD 포트를 출력으로 설정
Delay_ms(15);
write_command(0x30);
Delay_ms(5);
write_command(0x30);
Delay_ms(1);
write_command(0x32);
LCDCommand(FUNSET);
LCDCommand(DISP_OFF);
LCDCommand(ALLCLR);
LCDCommand(ENTMOD);
//Initialization ends
LCDCommand(DISP_ON); // 화면 ON
}
void LCDCommand(char command)
{
checkbusy();
write_command(command);
if(command == ALLCLR || command == HOME)
Delay_ms(2);
}
void LCDPutchar(char ch)
{
checkbusy();
write_data(ch);
}
void LCDPuts(char* str)
{
while(*str) // *str이 NULL 문자가 아니면 루프를 돈다.
{ //while(*str != 0)
LCDPutchar(*str); // 문자 *str을 화면에 출력
str++; // str이 다음 문자를 가리킴
}
}
void LCDMove(char line, char pos)
{
pos = (line << 6) + pos;
pos |= 0x80; // 비트 7를 세트한다.
LCDCommand(pos);
}
static void write_command(char command)
{
char temp;
// 상위 nibble 출력
temp = (command & 0xF0) | 0x04; //0x04: RS, RW=0, E=1
LCD_PORT = temp;
LCD_PORT = temp & ~0x04; //E=0, LCD Disable
// 하위 nibble 출력
temp = (command << 4) | 0x04; //0x04: RS, RW=0, E=1
LCD_PORT = temp;
LCD_PORT = temp & ~0x04; //E=0, LCD Disable
Delay_ms(1);
}
static void write_data(char ch)
{
unsigned char temp;
// 상위 nibble 출력
temp = (ch & 0xF0) | 0x05; //0x05: RS=1, RW=0, E=1
LCD_PORT = temp;
LCD_PORT = temp & ~0x04; //E=0, LCD Disable
// 하위 nibble 출력
temp = (ch << 4) | 0x05; //0x05: RS=1, RW=0, E=1
LCD_PORT = temp;
LCD_PORT = temp & ~0x04; //E=0, LCD Disable
}
void LCDNewchar(char ch, char font[]) // 글자 등록함수
{
int i;
ch <<= 3; // ch = ch << 3;과 같음
ch |= 0x40; // 비트6을 세트 => CGRAM 주소설정
LCDCommand(ch); // CGRAM 주소설정 =>LCDPutchar()로
// 쓰는 문자는 CGRAM에 저장
for(i=0; i<8; i++) // 글꼴을 CGRAM에 저장한다.
LCDPutchar(font[i]);
}
static void checkbusy()
{
_delay_us(100);
return;
}
void MCU_initialize(void) /* initialize ATmege128 MCU */
{
MCUCR = 0x80; // Enable external memory and I/O, Disable SLEEP mode
XMCRA = 0x44; // 0x1100 - 0x7FFF (1 wait), 0x8000 - 0xFFFF (0 wait)
XMCRB = 0x80; // Enable bus keeper. Use PC0-PC7 as high byte of address bus
DDRB = 0xF0; // PORTB7..4 = output, PORTB3..0 = Input
PORTB = 0x00;
// DDRD = 0x00; // PORTD = Input
DDRD = 0xFF; // PORTD7..2 =Output, PORTD1..0 = Input
PORTD = 0x00;
// DDRE = 0x02; // PORTE1 = output, All other PORTs are Input
//DDRE = 0x0A; // PORTE1, 3 = output, All other PORTs are Input
// PORTE = 0x00;
PORTE = 0xE0; // Pull up the PORTE7..5
DDRF = 0x00; // PORTF = Input
PORTF = 0x00;
DDRG = 0x1F;
LCD_CONTROL = 0x00;
LCD_DATABUS = 0x00;
}
void Delay_ms(unsigned int time_ms) /* time delay for ms */
{
register unsigned int i;
for(i = 0; i < time_ms; i++) {
Delay_us(250);
Delay_us(250);
Delay_us(250);
Delay_us(250);
}
}
void Delay_us(unsigned char time_us) /* time delay for us */
{
register unsigned char i;
for(i = 0; i < time_us; i++) { // 4 cycle +
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle +
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle +
asm (" PUSH R0 "); // 2 cycle +
asm (" POP R0 "); // 2 cycle = 16 cycle = 1 us for 16MHz
}
}
void LCD_command(unsigned char command) /* write a command(instruction) to text LCD */
{
LCD_CONTROL = 0x00; // E = 0, Rs = 0
LCD_CONTROL = 0x01; // E = 1
LCD_DATABUS = command; // output command
asm (" PUSH R0 "); // delay for about 250 ns
asm (" POP R0 ");
LCD_CONTROL = 0x00; // E = 0
Delay_us(50);
}
void LCD_data(unsigned char data) /* display a character on text LCD */
{
LCD_CONTROL = 0x02; // E = 0, Rs = 1
LCD_CONTROL = 0x03; // E = 1
LCD_DATABUS = data; // output data
asm (" PUSH R0 "); // delay for about 250 ns
asm (" POP R0 ");
LCD_CONTROL = 0x02; // E = 0
Delay_us(50);
}
void LCD_string(char command, char *string) /* display a string on LCD */
{
LCD_command(command); // start position of string
while(*string != '\0') { // display string
LCD_data(*string);
string++;
}
}
void LCD_initialize(void) /* initialize text LCD module */
{
LCD_CONTROL = 0x03; // E = 1, Rs = 1 (dummy write)
LCD_CONTROL = 0x02; // E = 0, Rs = 1
Delay_ms(2);
LCD_command(0x38); // function set(8 bit, 2 line, 5x7 dot)
LCD_command(0x0C); // display control(display ON, cursor OFF)
LCD_command(0x06); // entry mode set(increment, not shift)
LCD_command(0x01); // clear display
Delay_ms(2);
}
이이잉님의 댓글
이이잉 작성일
<LCD.h>
//#ifndef __LCD_H__
#define __LCD_H__
#define LCD_DATABUS *((volatile unsigned char *)0x2000) // LCD data output address
#define LCD_CONTROL *((volatile unsigned char *)0x2100) // LCD control signal output address
#define ALLCLR 0x01 // 화면을 지운다.
#define HOME 0x02 // 커서를 홈으로 보낸다.
#define LN21 0xc0 // 커서를 2번째 라인의 첫번째에 위치시킴
#define ENTMOD 0x06 // entry mode
#define FUNSET 0x28 // function se
#define DISP_ON 0x0c // 디스플레이를 켠다.
#define DISP_OFF 0x08 // 디스플레이를 끈다
#define CURSOR_ON 0x0e // 커서를 켠다.
#define CURSOR_OFF 0x0c // 커서를 끈다.
#define CURSOR_LSHIFT 0x10 // 커서를 왼쪽을 이동시킨다
#define CURSOR_RSHIFT 0x14 // 커서를 오른쪽으로 이동시킨다.
#define DISP_LSHIFT 0x18 // 디스플레이를 왼쪽으로 이동시킨다.
#define DISP_RSHIFT 0x1c // 디스플레이를 오른쪽으로 이동시킨다.
void LCDInit(void);
void LCDCommand(char command);
void LCDMove(char line, char pos);
void LCDPutchar(char ch);
void LCDPuts(char* str);
//endif // __LCD_H__
master님의 댓글
master 작성일
UCSR1B=0x98; UBRR1L=103;
블루투스는 UART1을 사용하고 있는데요
UART1은 포트D에 있습니다.
UART1이 아닌 UART0으로 블루투스를 변경하든지
LCD를 포트D가 아닌 다른 비어있는 포트로 변경하세요
LCD를