책 pdf 367
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#define PRESCALE 256L
#define PULSE_PER_OVERFLOW 510L
#define MS_OVERFLOW_CYCLE ((double)(PULSE_PER_OVERFLOW * PRESCALE)\
/(double)((double)F_CPU/1000.0))
#define OC0 PB4
#define UP PB7
#define DOWN PB6
#define NUM_REQ 2
#define REQ_UP 0
#define REQ_DOWN 1
#define DEBOUNCE_CYCLE 50
volatile unsigned long timer0; //오버플로마다 1씩 증가 될 변수
volatile unsigned int number;
unsigned char led[]={0x48,0x7D,0xC4,0x64,0x71,0x62,0x43,0x7C,0x40,0x70};
volatile unsigned long req[NUM_REQ]={0,0};
double ms_ov_cycle;
// 타이머/카운터@ 인터럽트 서비스 루틴
ISR(TIMER0_OVF_vect)
{
int i;
timer0++; // 오버플로마다 1씩 증가
//오버플로 횟수가 짝수 일때 10자리, 홀수일때 1자리 디스플레이
PORTC = (timer0 % 2 == 0) ? led[(number % 100) / 10] : led[number%10];
PORTD = (PORTD | 0xC0) & ~(1<<((timer0 % 2 == 0) ? PD7 : PD6));
for(i=0; i<NUM_REQ; i++)
if( req[i] > 0) //REQ 요청이 있을때만
req[i]--; //시간 지연 경과 응답
}
// ms_interval초 시간 지연을 위한 오버플로 횟수 계산 함수
unsigned long ms_req_timer0(unsigned long ms_interval)
{
return (ms_interval <=0) ? 0 : \
+(unsigned long)(ms_interval / ms_ov_cycle);
}
int main(void)
{
DDRC = 0xFF;
DDRD |= 1 << PD7| 1<<PD6; //두 자리 7-세그먼트 LED를 켜기 위한 출력
DDRB |= 1 << OC0; //OC0 = PB4 출력
DDRB &= ~(1<<UP | 1<<DOWN); //UP, DOWN 스위치 위치를 입력 방향으로
PORTB |= 1<<UP | 1<<DOWN; //UP, DOWN 풀업 저항
TCCR0 = 1<<WGM00; //위상정정 PWM 파형 발생모드
TCCR0 |= 1<<CS02 | 1<<CS01; //프리스케일러 CS02:00 = (1,1,0) 256 분주
TCCR0 |= 1<<COM01; //상승 중 OCR0와 일치 0, 하강 중 일치 1
TIMSK |= 1<<TOIE0; //타이머/카운터0 인터럽트 활성화
timer0 = 0;
sei();
ms_ov_cycle = MS_OVERFLOW_CYCLE;
OCR0 = 0;
number = OCR0*100/256; //OCR0값과 number값을 일치
while(1){
if( (req[REQ_UP] == 0) && !(PINB & (1<<UP)) ){ //req[UP] 응답, UP 스위치 눌림 검사
req[REQ_UP] = ms_req_timer0(DEBOUNCE_CYCLE);
OCR0 = (OCR0 == 255) ? 255 : OCR0 + 1;
}
if((req[REQ_DOWN]==0) && !(PINB & (1<<DOWN))){ //req[DOWN] 응답, DOWN 스위치 검사
req[REQ_DOWN] = ms_req_timer0(DEBOUNCE_CYCLE);
OCR0 = (OCR0 == 0) ? 0 : OCR0 - 1;
}
number = OCR0 * 100/256;
}
return 0;
}
7segment부분 제거한것
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#define PRESCALE 256L
#define PULSE_PER_OVERFLOW 510L
#define MS_OVERFLOW_CYCLE ((double)(PULSE_PER_OVERFLOW * PRESCALE) /(double)((double)F_CPU/1000.0))
#define OC0 PB4
#define UP PB7
#define DOWN PB6
#define NUM_REQ 2
#define REQ_UP 0
#define REQ_DOWN 1
#define DEBOUNCE_CYCLE 50
volatile unsigned long timer0; //오버플로마다 1씩 증가 될 변수
volatile unsigned long req[NUM_REQ]={0,0};
double ms_ov_cycle;
// 타이머/카운터0 인터럽트 서비스 루틴
ISR(TIMER0_OVF_vect)
{
int i;
timer0++; // 오버플로마다 1씩 증가
for(i=0; i<NUM_REQ; i++)
if( req[i] > 0) //REQ 요청이 있을때만
req[i]--; //시간 지연 경과 응답
}
// ms_interval초 시간 지연을 위한 오버플로 횟수 계산 함수
unsigned long ms_req_timer0(unsigned long ms_interval)
{
return (ms_interval <=0) ? 0 : +(unsigned long)(ms_interval / ms_ov_cycle);
}
int main(void)
{
DDRB |= 1 << OC0; //OC0 = PB4 출력
DDRB &= ~(1<<UP | 1<<DOWN); //UP, DOWN 스위치 위치를 입력 방향으로
PORTB |= 1<<UP | 1<<DOWN; //UP, DOWN 풀업 저항
//TCCR0 |= 1<<WGM00 | 1<<CS02 | 1<<CS01 | 1<<COM01;
TCCR0 = 1<<WGM00; //위상정정 PWM 파형 발생모드 TCCR0 = 0b0110 0110; = 0x66;
TCCR0 |= 1<<CS02 | 1<<CS01; //프리스케일러 CS02:00 = (1,1,0) 256 분주
TCCR0 |= 1<<COM01; // TCNT 값이 OCR0값보다 높을때는 0으로 clear, OCR0값보다 낮을때는 1로 set.
// 1<<COM00 | 0<<COM01 으로 setting 하면 TCNT 값이 OCR0값보다 높을때는 1로 set, OCR0값보다 낮을때는 0으로 clear.
TIMSK |= 1<<TOIE0; //타이머/카운터0 인터럽트 활성화
timer0 = 0;
sei();
ms_ov_cycle = MS_OVERFLOW_CYCLE;
OCR0 = 0;
while(1){
if( (req[REQ_UP] == 0) && !(PINB & (1<<UP)) ){ //req[UP] 응답, UP 스위치 눌림 검사
req[REQ_UP] = ms_req_timer0(DEBOUNCE_CYCLE);
OCR0 = (OCR0 == 255) ? 255 : OCR0 + 1;
}
if((req[REQ_DOWN]==0) && !(PINB & (1<<DOWN))){ //req[DOWN] 응답, DOWN 스위치 검사
req[REQ_DOWN] = ms_req_timer0(DEBOUNCE_CYCLE);
OCR0 = (OCR0 == 0) ? 0 : OCR0 - 1;
}
}
return 0;
}
'임베디드 > Atmega128' 카테고리의 다른 글
PORTB = 1 << PB7; 와 PORTB |= 1 << PB7; 차이 (0) | 2021.01.21 |
---|---|
JMOD-128-1 AtmelStudio 7.0 에서 연결하기 (0) | 2021.01.21 |
착시현상 7SEGMENT (0) | 2021.01.07 |
atmega128 timer/counter0 normal 모터 (0) | 2021.01.07 |
고속pwm으로 똑같이 동작하게 (0) | 2021.01.06 |