BASIC4MCU | 질문게시판 | atmega128 pwm 질문드립니다
페이지 정보
작성자 안녕수야 작성일2023-10-23 22:35 조회2,557회 댓글6건본문
스위치를 눌렀을때, pwm으로 4digit fnd의 밝기 조절을 하려는데 도저히 감이 잡히질 않습니다.
4digit 의 셀렉트핀을 atmega128 의 pwm 부분에 연결은 했는데
소스를 어떻게 짜야할지 잘 모르겠습니다
댓글 6
조회수 2,557master님의 댓글
master 작성일
회로도와 소스코드를 첨부하셔야지 구체적인 조언이 가능하겠습니다.
//
외부 회로없이 4개의 셀렉트 핀을 PWM 제어하려면
PWM 출력이 4개가 필요합니다.
만약, 1개의 PWM으로 구동하려면 PWM 인터럽트에서 세그먼트를 구동하면 됩니다.
비교매치 인터럽트와 오버플로우 인터럽트를 둘 다 사용하고
오버플로우 인터럽트에서 세그출력과 셀렉트 출력을 하고
비교매치 인터럽트에서 OFF 출력을 하면 되겠습니다.
PWM(OC)출력을 할 것이 아니므로 PWM핀을 사용하지는 않고, PWM 설정만 하면 됩니다.
안녕수야님의 댓글
안녕수야
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
unsigned int fnd_data[10]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
int digit_0=0, digit_1=0, digit_2=0, digit_3=0;
int number=0000;
void timer0_pwm_init()
{
TCCR0|=(1<<CS02)|(1<<CS01)|(1<<CS00);
TCCR0|=(1<<WGM01)|(1<<WGM00);
TCCR0|=(1<<COM01);
TCNT0=0;
}
int digit(int value)
{
digit_0=(value/1)%10;
digit_1=(value/10)%10;
digit_2=(value/100)%10;
digit_3=(value/1000);
}
void fnd_control()
{
PORTG = ~(1<<3);
PORTC = fnd_data[digit_0];
_delay_ms(1);
PORTB = ~(1<<2);
PORTC = fnd_data[digit_1];
_delay_ms(1);
PORTB = ~(1<<1);
PORTC = fnd_data[digit_2];
_delay_ms(1);
PORTB = ~(1<<0);
PORTC = fnd_data[digit_3];
_delay_ms(1);
}
void timer0_Nomalmode_init()
{
TCCR0 |= (1<<0) | (1<<1) | (1<<2);
TCNT0 = (256-252);
TIMSK|=(1<<TOIE0);
}
ISR(TIMER0_OVF_vect)
{
static int repeat=0;
TCNT0=(256-252);
repeat++;
if (repeat>=62*1)
{
repeat=0;
}
}
void timer0_pwm_init()
{
TCCR0|=(1<<CS02)|(1<<CS01)|(1<<CS00);
TCCR0|=(1<<WGM01)|(1<<WGM00);
TCCR0|=(1<<COM01);
TCNT0=0;
}
짜놓은 코드는 이정도 입니다. portb의 4 5 6 7번을 셀렉트 핀을 제어하려고 합니다
master님의 댓글
master 작성일pwm 주기가 1~2ms 정도가 되도록 설정하면 깜박임이 보이지 않습니다.
master님의 댓글
master 작성일
timer0_pwm_init()
같은 함수가 두개 작성되어 있습니다.
하나 삭제하세요
//
timer0_Nomalmode_init()
이 함수도 필요없으니 삭제 해야겠죠
//
인터럽트에서 사용하는 전역 변수는 volatile를 사용해야 합니다.(코드비젼은 volatile 없어도 됨)
//
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//
volatile unsigned char fnd_data[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
volatile int dgt_0=0,dgt_1=0,dgt_2=0,dgt_3=0;
volatile int num=0;
//
int dgt(int val){
dgt_0=val%10; dgt_1=val/10%10; dgt_2=val/100%10; dgt_3=val/1000%10;
}
//
void fnd_control(){
PORTG=~(1<<3); PORTC=fnd_data[dgt_0]; _delay_ms(1);
PORTB=~(1<<2); PORTC=fnd_data[dgt_1]; _delay_ms(1);
PORTB=~(1<<1); PORTC=fnd_data[dgt_2]; _delay_ms(1);
PORTB=~(1<<0); PORTC=fnd_data[dgt_3]; _delay_ms(1);
}
//
ISR(TIMER0_OVF_vect){
static unsigned char repeat=0;
TCNT0=(256-252);
if(++repeat>=62)repeat=0;
}
//
void timer0_pwm_init(){
TCCR0|=7; TCCR0|=(1<<WGM01)|(1<<WGM00); TCCR0|=(1<<COM01);
}
질문코드를 대충 정리했습니다.(답변은 아님)
master님의 댓글
master 작성일
void timer0_pwm_init(){
TCCR0=(1<<WGM01)|(1<<WGM00)|(1<<COM01)|7; // fast pwm mode
}
분주비를 1024로 설정하면 pwm주기는 16.384ms가 되고 초당 61회라서 4자리를 구동하면 초당 15번 밖에 안되서 깜박거림이 발생하게 됩니다.
분주비는 256이하로 설정해야 합니다.(4자리 구동에 초당 61회)
master님의 댓글
master 작성일
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//
volatile unsigned char fnd_data[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
volatile int dgt_0=0,dgt_1=0,dgt_2=0,dgt_3=0;
volatile int num=0;
//
int dgt(int val){
dgt_0=val%10; dgt_1=val/10%10; dgt_2=val/100%10; dgt_3=val/1000%10;
}
//
ISR(TIMER0_OVF_vect){ // segment on
static char c=0;
switch(c){
case 0: PORTC=fnd_data[dgt_0]; break;
case 1: PORTC=fnd_data[dgt_1]; break;
case 2: PORTC=fnd_data[dgt_2]; break;
case 3: PORTC=fnd_data[dgt_3]; break;
}
PORTB=~(8>>c);
if(++c>3)c=0;
}
ISR(TIMER0_COMP_vect){ // segment off
PORTB|=0x0F;
}
//
void timer0_pwm_init(){
TCCR0=(1<<WGM01)|(1<<WGM00)|(1<<COM01)|6; TIMSK=3; // fast pwm mode
}