ITGenerations
[avr]서보모터+LCD 본문
// source 30
//서보모터+LCD
// 오렌지=PWM-> PB5번 연결
#include <avr/interrupt.h>
#include <avr/io.h> // I/O 레지스터정의
#include <util/delay.h> // 시간지연함수
#include <string.h>
#include "lcd.h" // LCD 제어프로그램 헤더파일
#include "rcservo.h"
#define DEBOUNCING_DELAY 20
#define MAX_ANGLE 90
#define MIN_ANGLE -90
float degree = 0;
unsigned short on_width[3]={NEUTRAL_WIDTH, NEUTRAL_WIDTH, NEUTRAL_WIDTH}; // 중립일 때의 펄스폭
char string[20]; // 문자열을 구성할 배열
void msec_delay(int n); // 시간지연함수
static char lcdtitle[] = "ANGLE:"; // 실습 제목
void set_angle(int n, float angle)
{
on_width[n] = (unsigned short)(-100.f * angle / 9.f + 1500.f);// +- 90degree일 때의 수식
}
ISR(INT0_vect) // + 5 deg
{
TIMSK &= ~(1 << OCIE2);
msec_delay(DEBOUNCING_DELAY);
while (~PIND & 0x01);
msec_delay(DEBOUNCING_DELAY);
degree += 5.f;// data를 10 증가한다.
if (degree > MAX_ANGLE)
degree = MAX_ANGLE;
set_angle(0, degree);
RCServoSetOnWidth(on_width);
LcdMove(1,0); // HOME
sprintf(string,"%d ", (int)degree);
LcdPuts(string);
EIFR = (1 << INTF0);
}
ISR(INT1_vect) // -5 deg
{
TIMSK &= ~(1 << OCIE2);
msec_delay(DEBOUNCING_DELAY);
while (~PIND & 0x02);
msec_delay(DEBOUNCING_DELAY);
degree -= 5.f ;// data reset
if (degree < MIN_ANGLE)
degree = MIN_ANGLE;
set_angle(0, degree);
RCServoSetOnWidth(on_width);
LcdMove(1,0); // HOME
sprintf(string,"%d ", (int)degree);
LcdPuts(string);
EIFR = (1 << INTF1);
}
ISR(INT2_vect) // Auto Mode Setting
{
if (TIMSK & (1 << OCIE2))
{
TIMSK &= ~(1 << OCIE2);
}
else
{
TIMSK |= (1 << OCIE2);
}
msec_delay(DEBOUNCING_DELAY);
while (~PIND & 0x04);
msec_delay(DEBOUNCING_DELAY);
EIFR = (1 << INTF2);
}
ISR(TIMER2_COMP_vect) // Auto Mode
{
static int n_enter2 = 0;
static int direction = 1; // 1: + direction, -1: - direction
n_enter2+=50;
if (n_enter2 == 50) // 100 msec
{
n_enter2 = 0;
if (direction> 0)
{
degree+= 5.f;
if (degree > MAX_ANGLE)
{
direction = -1;
degree = MAX_ANGLE;
}
set_angle(0, degree);
}
else
{
degree-= 5.f;
if (degree < MIN_ANGLE)
{
direction = 1;
degree = MIN_ANGLE;
}
set_angle(0, degree);
}
RCServoSetOnWidth(on_width);
LcdMove(1,0); // HOME
sprintf(string,"%d ", (int)degree);
LcdPuts(string);
}
}
int main()
{
char i;
degree = 0.f;
LcdInit(); // LCD 초기화
RCServoInit(20000); // 20ms PWM Period
LcdMove(0,0); // HOME
LcdPuts(lcdtitle); // 실습 제목을 쓴다.
LcdMove(1,0);
sprintf(string,"%d ", (int)degree);
LcdPuts(string); // SRAM내의 문자열 출력
/////////////////////////// Switch ////////////////
SFIOR &= ~(1 << PUD); // PUD는 io.h에 정의되어 있음.
PORTD |= (1 << PD0) | (1 << PD1) | (1 << PD2); // Switch로 사용할 PD0와 PD1을 출력으로 설정.
EICRA = (1 << ISC21) | (1 << ISC11) | (1 << ISC01); // Interrupt 1과 0을 하강모서리 트리거 (교재 p110)
EIMSK |= (1 << INT0) | (1 << INT1) | (1 << INT2);
TCCR2 = (1 << WGM01) | (0<WGM00) | (1 << COM00) | (1 << CS02) | (0 << CS01) | (1 << CS00);
TCNT2 = 0x00;
OCR2 = 0x9C;
TIMSK |= (1 << OCIE2);
sei(); // 전역 인터럽트 허용.
while(1);
}
// 시간지연함수
//////////////////////////////////////////
void msec_delay(int n)
{
for(; n >0; n--) // 1msec 시간지연을 n회 반복
_delay_ms(1); // 1msec 시간지연
}
'Univ > AVR atmega128' 카테고리의 다른 글
[AVR] 한 학기동안 AVR Atmega128을 공부하면서 (0) | 2017.12.10 |
---|---|
[avr]코드 목록 (0) | 2017.12.10 |
[avr] LCD 타이머 표시 (0) | 2017.12.10 |
[avr] LCD제어 모듈 테스트, 가변저항 x (0) | 2017.12.09 |
[avr]키패드 입력, 세븐세그먼트 [실패] (0) | 2017.12.09 |