답변 : atmega128 초보입니다.
페이지 정보
작성자 master 작성일18-12-01 14:41 조회4,756회 댓글1건본문
// MCU BASIC: https://www.basic4mcu.com
// DateTime : 2018-12-01 오후 2:45:45
// by Ok-Hyun Park
//
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
//-RGB LCD 제어 PORT&PIN---------------------------------------------------------------
#define RGB_DATA_DDR DDRA //-Data Bus제어 Port
#define RGB_DATA_PORT PORTA
#define DATA_D4 PA0 //-Data Bus PIN
#define DATA_D5 PA1
#define DATA_D6 PA2
#define DATA_D7 PA3
#define RGB_LCD_DDR DDRF //-RGB LCD 제어 Port
#define RGB_LCD_PORT PORTF
#define RS_BIT PF2 //-Register Select: LOW-Command,HIGH-Data
#define RW_BIT PF3 //-Read/Wite: LOW-Wite HIGH-Read
#define EN_BIT PF4 //-Enable Pin: LOW-Disable HIGH-Enable
#define RED_BIT PF5 //-Red Backlight: LOW-Off HIGH-On
#define GREEN_BIT PF6 //-Green Backight: LOW-Off HIGH-On
#define BLUE_BIT PF7 //-Blue Backlight: LOW-Off HIGH-On
//-RBG LCD 제어관련 상수---------------------------------------------------------------
#define ALL_SET 0xff //-모든 Pin 1로 셋
#define ALL_CLEAR 0x00 //-모든 Pin 0으로 클리어
#define DDRAM_ADDR 0x80 //-DD(Display Data)RAM 주소
//-RBG LCD 제어관련 명령어--------------------------------------------------------------
#define CMD_CLEAR_DISPLAY 0x01 //-CLEAR_DISPLAY(0x01)
#define CMD_RETURN_HOME 0x02 //-RETURN_HOME(0x02)
#define CMD_ENTRYMODE_SET 0x06 //-ENTRYMODE_SET(0x04)|Left(0x02)|Shift Decrement(0x00)
#define CMD_DISPLAY_CONTROL 0x0C //-DISPLAY_CONTROL(0x08)|Display On(0x04)|Cursor Off(0x00)|Blink Off(0x00)
#define CMD_CURSOR_SHIFT_RIGHT 0x1C //-CURSOR_SHIFT(0x10)|Shift Move(0x08)|Move Right(0x04)
#define CMD_FUNCTION_SET 0x28 //-FUNCTION_SET(0x02)|4BIT(0x00)|2 Line(0x08)|5x8 Dots(0x00)
#define CMD_8BIT_MODE 0x03 //-FUNCTION_SET(0x02)|8BIT(0x01)
#define CMD_4BIT_MODE 0x03 //-FUNCTION_SET(0x02)|4BIT(0x00)
#define DDRAM_FS_ADDR 0x0
#define DDRAM_EF_ADDR 0x0F
#define DDRAM_SS_ADDR 0x40
#define DDRAM_SF_ADDR 0x4F
//
#define LX_LIMIT 100 //-LED Off 되는 한계 값 정의
//-LED 관련
#define DDR_LED DDRD
#define PORT_LED PORTD
#define LED_ON 0x00
#define LED_OFF 0xF0
/*-------------------------------------------------------------------------*/
//-Temp관련
#define TEMP_ADDR 72 //-온도센서의 Slave 주소
#define TEMP_ADDR_W TEMP_ADDR<<1 //-Write 주소
#define TEMP_ADDR_R (TEMP_ADDR<<1)+1 //_ Read 주소
#define TEMP_REG 0 //_ 온도 데이터 저장 Reg.주소
#define TEMP_LIMIT 25 //_ DC Motor ON 되는 한계 값
//-Clock 제어를 위한 선언
#define CPU_CLOCK 16000000 //_ 16MHz
#define SCL_FREQUENCY 400000 //_ 400KHz
//-DC 모터 제어를 위한 정의
#define DCM_DDR DDRB // B포트를 모두 출력으로
#define DCM_PORT PORTB // B포트를 모두 출력으로 8칸이 다 1이 출력된다는거임
#define FORWARD_BIT 0
#define BACKWARD_BIT 1
//-온도값 저장 전역 변수 선언
volatile unsigned int gTempValue; //_ 측정된 온도 값 저장
//-USART 제어를 위한 전역 변수 선언
volatile unsigned int gLightValue; //-측정된 조도값 저장
/*=====================================함수 선언=========================================================*/
void RGB_LCD_Init(void);
void RGB_LCD_Enable(void);
void RGB_LCD_Write(unsigned char nValue);
void Set4BitMode(void);
void SendText(unsigned char addrCommand,char*szText);
void SendCommandl(unsigned char command);
void SendData(unsigned char data);
void LCD_Display(void);
void ADC_LED_Init(void);
void ADC_Convert(void);
void LED_OnOff(unsigned char nNum);
//_ Temp&ADC
void TEMP_DC_Init(void);
void TEMP_Read(void);
//_ DC Motor
void Run_DCM(void);
void Stop_DCM(void);
//
void TEMP_DC_Init(void){
//-DC Motor 초기화
DCM_DDR|=(1<<FORWARD_BIT)|(1<<BACKWARD_BIT); //-PB0,PB1 비트 Output으로 설정
DCM_PORT&=~((1<<FORWARD_BIT)|(1<<BACKWARD_BIT)); //-DC모터 구동 정지로 설정
//-Temp TWI 초기화
TWSR&=~((1<<TWPS1)|(1<<TWPS0)); //-분주비 설정
TWBR=(CPU_CLOCK/SCL_FREQUENCY-16)/ 2; //-TWI 통신 속도 설정
}
//
void TEMP_Read(void){
unsigned char arrTemp[2]; //-읽어온 2byte 데이터 저장
unsigned int nTmp; //-12bit 온도 값 저장
float fCValue; //-섭씨로 변환한 값 저장
//-START condition
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//-Slave Addr+Read 전송
TWDR=TEMP_ADDR_R;
TWCR=(1<<TWINT)|(1<<TWEN);
while(!(TWCR&(1<<TWINT)));
//-측정된 온도값 읽기
for(int i=0; i<2; i++){ TWCR=(1<<TWINT)|(1<<TWEA)|(1<<TWEN); while(!(TWCR&(1<<TWINT))); arrTemp[i]=TWDR; }
nTmp=arrTemp[0]<<8; nTmp=nTmp|arrTemp[1]; nTmp=nTmp>>4; //-측정된 12bit 온도 데이터 계산
fCValue=(float)nTmp*0.0625; //-온도값을 섭씨로 변환->data_value*0.0625--------------
TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN); _delay_ms(5); //-STOP condition
if((int)fCValue>TEMP_LIMIT)Run_DCM(); else Stop_DCM();
gTempValue=(int)fCValue; //-섭씨 온도값 저장
}
//
void Run_DCM(void){ //-DC Motor 동작
DCM_PORT&=~((1<<FORWARD_BIT)|(1<<BACKWARD_BIT)); //-정방향으로 회전
DCM_PORT|=(1<<FORWARD_BIT);
}
//
void Stop_DCM(void){ DCM_PORT=(1<<FORWARD_BIT)|(1<<BACKWARD_BIT); }
/*=LED관련 함수*/
//-LED On/Off
void LED_OnOff(unsigned char nNum){
if(nNum==LED_ON)PORT_LED=0x00; //-4개 LED ON
else PORT_LED=0xF0; //-4개 LED OFF
}
/*=ADC&Light 관련 함수*/
//-ADC&Light 초기화
void ADC_LED_Init(void){
//-LED 초기화
DDR_LED|=0xF0; PORT_LED|=0xF0;
//-ADC0 채널,AREF 기준 전압 및 채널을 선택
ADMUX=0;
//-채널,활성화,프리스케일 설정
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
/*==ADC 변환 함수 구현*/
void ADC_Convert(void){
unsigned int result;
cli(); //-ADC 변환 중 인터럽트 금지
ADCSRA|=(1<<ADSC); //-ADC 변환 시작
while(!(ADCSRA&(1<<ADIF))); //-ADC 변환 완료 신호 대기
result=ADCL; //-변환 결과 저장
result|=((ADCH&0x03)<<8);
sei(); //-인터럽트 허용
if(result>LX_LIMIT)LED_OnOff(LED_OFF); //-CDS Value>50 LED OFF
else LED_OnOff(LED_ON); //-CDS Value<=50 LED ON
//-조도값 저장
gLightValue=result;
}
//
void SendCommand(unsigned char command){ //-RBG_LCD 명령어 전달 함수 구현---------------------------------
RGB_LCD_PORT&=~((1<<RS_BIT)|(1<<RW_BIT)|(1<<EN_BIT)); //-Command 전송을 위한 RS=0,RW=0,EN=0
RGB_LCD_Write(command>>4); RGB_LCD_Write(command); //-Data Bus에 CMD 쓰기
}
//
void SendData(unsigned char data){ //-RBG_LCD 데이터 전달 함수 구현---------------------------------
RGB_LCD_PORT|=(1<<RS_BIT); RGB_LCD_PORT&=~((1<<RS_BIT)|(1<<EN_BIT)); //-Data 전송을 위한 RS=1,RW=0,EN=0
RGB_LCD_Write(data>>4); RGB_LCD_Write(data);
}
//
void SendText(unsigned char addrCommand,char*szText){ //-RBG_LCD 문자열 출력 함수 구현---------------------------------
SendCommand(addrCommand); //-DD Ram 주소 전달
while(*szText!='\0'){ SendData(*szText); szText++; }
}
//
void RGB_LCD_Write(unsigned char nValue){ //-RBG_LCD 명령어/데이터 레지스터 기록 구현---------------------------------
int nTmp=0;
RGB_DATA_PORT=0x00;
for(int nldx=0; nldx<4; nldx++){ nTmp=(nValue>>nldx)&0x01; RGB_DATA_PORT|=(nTmp<<(DATA_D4+nldx)); }
RGB_LCD_Enable();
}
//
void RGB_LCD_Enable(void){
RGB_LCD_PORT|=(1<<EN_BIT); _delay_us(1); RGB_LCD_PORT&=~(1<<EN_BIT); _delay_us(100);
}
//
void Set4BitMode(void){ //-RBG_LCD 4bit 인터페이스 설정 구현---------------------------------
RGB_LCD_PORT&=~((1<<RS_BIT)|(1<<RW_BIT)|(1<<EN_BIT)); //-Command 전송을 위한 RS=0,RW=0,EN=0
RGB_LCD_Write(CMD_8BIT_MODE); _delay_us(4500);
RGB_LCD_Write(CMD_8BIT_MODE); _delay_us(4500);
RGB_LCD_Write(CMD_8BIT_MODE); _delay_us(150);
RGB_LCD_Write(CMD_4BIT_MODE);
}
//
void RGB_LCD_Init(void){
RGB_LCD_DDR=((1<<RS_BIT)|(1<<RW_BIT)|(1<<EN_BIT)|(1<<RED_BIT)|(1<<GREEN_BIT)|(1<<BLUE_BIT));
RGB_LCD_PORT&=~((1<<RS_BIT)|(1<<RW_BIT)|(1<<EN_BIT)|(1<<RED_BIT)|(1<<GREEN_BIT)|(1<<BLUE_BIT));
RGB_DATA_DDR=ALL_SET; RGB_DATA_PORT=ALL_CLEAR; //-Data 입력 Pin Output 설정 및 초기화
Set4BitMode(); //-(2)RGB LCD 인터페이스 설정
SendCommand(CMD_FUNCTION_SET); //-(3)RGB LCD 출력을 위한 설정 //-LCD의 행,열,글자 크기 설정
SendCommand(CMD_DISPLAY_CONTROL); //-디스플레이,커서,문자 깜빡임 On/Off 설정
SendCommand(CMD_ENTRYMODE_SET); //-커서 이동 방향,문자 디스플레이 이동 여부 설정
SendCommand(CMD_CLEAR_DISPLAY); //-LCD 화연 지우고 커서는 1행 1열 위치,DDRAM AC=0
RGB_LCD_PORT|=(1<<GREEN_BIT); //-Green Backlight 켜기
_delay_us(2000);
}
//
void LCD_Display(void){ //-측정된 온도,조도값 LCD에 출력--------------------------
char arrTmp[16]="",pTmp[4]="";
itoa(gTempValue,pTmp,10); strcat(arrTmp,"T: "); strcat(arrTmp,pTmp); strcat(arrTmp,"C"); //-온도값 문자열로 변환
itoa(gLightValue,pTmp,10); strcat(arrTmp,"L: "); strcat(arrTmp,pTmp); strcat(arrTmp,"Lx "); //-조도값 문자열로 변환
SendText(DDRAM_ADDR|DDRAM_FS_ADDR,arrTmp);
}
/*===========================*/
// DESC:(1)일정 온도 이상이 되면 DC모터를 회전시키고 일정 밝기 이하면 LED를 켜준다.
//-(2)RGB_LCD에 현재 온도와 조도를 표시해 준다.
/*===========================*/
/*==Main 함수 구현==============*/
int main(void){
ADC_LED_Init(); //-Light&LED 초기화
TEMP_DC_Init(); //-Temp&DC 초기화
RGB_LCD_Init(); //-RGB_LCD 초기화
while(1){
TEMP_Read(); //-온도 측정
ADC_Convert(); //-조도 측정
LCD_Display(); //-현재 온도.조도 LCD 출력
_delay_ms(1000);
}
return 0;
}
타이핑 오타는 백만개라고 하더라도 자신이 직접 찾아야합니다.
댓글 : 1
조회수 : 4,756
master님의 댓글
master 작성일
본인 능력으로 오타도 찾지 못할만큼 복잡한 소스라면 이해하는 것도 어려울테니
간단하고 쉬운 예제를 많이 공부한 후에 복잡한 소스를 보시는 것이 힘이 덜 듭니다.