Fogeaters, Light The World.

15

2016-Jan

AVR 멀티채널 PWM (타이머 하나로 여러 PWM 구동)

작성자: title: MoonBlonix IP ADRESS: *.148.87.98 조회 수: 1651

출처 : https://gist.github.com/funkfinger/954874

Blonix 첨언 : 소프트웨어 pwm 이므로 정밀도는 떨어짐. 아두이노의 analogWrite 명령어가 이 방식일 것으로 추정됨.
이 방법을 사용하면 어떤 핀에서도 pwm을 뽑아낼 수 있다. 타이머도 아낄 수 있고 말이다.
아래 코드는 ATMega128A 가 아니라 ATTiny85 에 기반해 작성되었으나 이니셜라이즈 부분을 제외하면 뭐 그거나 이거나 딱히 차이는 없다.

PWM 코드뿐 아니라 매크로 사용법, 변수 선언 방법 등에서 좀 더 세련된 AVR 코딩을 위해 배울점이 많아보인다.
아래 코드에서 pwm 주파수는 인터럽트 발생주파수/256 이다. 고로 사용할 주파수를 고려해서 수정해 사용하자.
softcount 를 99가 되면 0 으로 돌려버린다던가 하면 pwm 주파수를 인터럽트 주파수/100으로 만들 수 있다.
인터럽트 주파수는 프리스케일러와 TCNT를 적당히 설정하면 된다.


ATTiny85 3 channel software PWM to drive RGB LED




 
// based largely on Atmel's AVR136: Low-Jitter Multi-Channel Software PWM Application Note:
// http://www.atmel.com/dyn/resources/prod_documents/doc8020.pdf
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define CHMAX 3 // maximum number of PWM channels
#define PWMDEFAULT 0x00 // default PWM value at start up for all channels
#define RED_CLEAR (pinlevelB &= ~(1 << RED)) // map RED to PB0
#define GREEN_CLEAR (pinlevelB &= ~(1 << GREEN)) // map GREEN to PB1
#define BLUE_CLEAR (pinlevelB &= ~(1 << BLUE)) // map BLUE to PB2
//! Set bits corresponding to pin usage above
#define PORTB_MASK (1 << PB0)|(1 << PB1)|(1 << PB2)
#define set(x) |= (1<<x)
#define clr(x) &=~(1<<x)
#define inv(x) ^=(1<<x)
#define RED PB0
#define GREEN PB1
#define BLUE PB2
#define LED_PORT PORTB
#define LED_DDR DDRB
void delay_ms(uint16_t ms);
void init();
unsigned char compare[CHMAX];
volatile unsigned char compbuff[CHMAX];
int r_val = 0x00;
int g_val = 0x55;
int b_val = 0xAA;
float dim = 1;
int main() {
init();
int r_dir = 1;
int g_dir = 2;
int b_dir = 4;
for(;;) {
if (r_val > 254 - 1) {
r_dir = -1;
}
if (r_val < 1 + 1) {
r_dir = 1;
}
if (g_val > 254 - 3) {
g_dir = -2;
}
if (g_val < 1 + 3) {
g_dir = 2;
}
if (b_val > 254 - 4) {
b_dir = -4;
}
if (b_val < 1 + 4) {
b_dir = 4;
}
r_val += r_dir;
g_val += g_dir;
b_val += b_dir;
compbuff[0] = r_val;
compbuff[1] = g_val;
compbuff[2] = b_val;
delay_ms(50);
}
}
void delay_ms(uint16_t ms) {
while (ms) {
_delay_ms(1);
ms--;
}
}
void init(void) {
// set the direction of the ports
LED_DDR set(RED);
LED_DDR set(GREEN);
LED_DDR set(BLUE);
unsigned char i, pwm;
CLKPR = (1 << CLKPCE); // enable clock prescaler update
CLKPR = 0; // set clock to maximum (= crystal)
pwm = PWMDEFAULT;
// initialise all channels
for(i=0 ; i<CHMAX ; i++) {
compare[i] = pwm; // set default PWM values
compbuff[i] = pwm; // set default PWM values
}
TIFR = (1 << TOV0); // clear interrupt flag
TIMSK = (1 << TOIE0); // enable overflow interrupt
TCCR0B = (1 << CS00); // start timer, no prescale
sei();
}
ISR (TIM0_OVF_vect) {
static unsigned char pinlevelB=PORTB_MASK;
static unsigned char softcount=0xFF;
PORTB = pinlevelB; // update outputs
if(++softcount == 0){ // increment modulo 256 counter and update
// the compare values only when counter = 0.
compare[0] = compbuff[0]; // verbose code for speed
compare[1] = compbuff[1];
compare[2] = compbuff[2];
pinlevelB = PORTB_MASK; // set all port pins high
}
// clear port pin on compare match (executed on next interrupt)
if(compare[0] == softcount) RED_CLEAR;
if(compare[1] == softcount) GREEN_CLEAR;
if(compare[2] == softcount) BLUE_CLEAR;
}
profile
List of Articles
번호 제목 글쓴이 날짜 조회 수
공지 [Web] 클라우드 IDE + 2 title: MoonBlonix 2017-06-25 15128
32 [AVR] HC_SR04 초음파센서 사용 file title: MoonBlonix 2016-02-13 1669
31 [AVR] 피에조 부저 활용 file + 1 title: MoonBlonix 2016-02-12 1956
30 칼만필터(Kalman Filter) + 2 title: MoonBlonix 2016-02-11 4378
29 low pass filter, high pass filter (저역통과필터, 고역통과필터) file title: MoonBlonix 2016-02-11 1456
28 [AVR] 루프 실행시간 측정 (아두이노의 Millis(), Micros() 분석) title: MoonBlonix 2016-02-09 1457
27 상보필터(Complementary Filter) file title: MoonBlonix 2016-02-09 1740
26 가속도, 자이로 센서에 대해 title: MoonBlonix 2016-02-09 1572
25 [AVR] UART 통신 file title: MoonBlonix 2016-02-07 1609
24 C++ 과 C 를 같은 프로젝트에서 사용하기 title: MoonBlonix 2016-02-07 1506
23 라즈베리파이 운영체제에 관하여 title: MoonBlonix 2016-02-05 1459
22 [리눅스] 기본 명령어 title: MoonBlonix 2016-02-05 1632
21 [리눅스] C 언어 개발환경 구축 title: MoonBlonix 2016-02-05 1865
20 라즈베리파이 GPIO 핀 배열 file title: MoonBlonix 2016-02-05 2061
19 C++ 멤버 함수 포인터 title: MoonBlonix 2016-01-23 1775
18 AVR 직접만든 DC모터 라이브러리 (C++ Class) file title: MoonBlonix 2016-01-16 1519
17 [AVR] I/O 포트 메뉴얼 (ATMega128) file title: MoonBlonix 2016-01-16 1594
16 AVR delay 함수 (_delay_ms, _delay_us) title: MoonBlonix 2016-01-15 1641
» AVR 멀티채널 PWM (타이머 하나로 여러 PWM 구동) title: MoonBlonix 2016-01-15 1651
14 AVR 초패스트 PWM title: MoonBlonix 2016-01-14 1566
13 AVR 타이머 응용 여러 PWM 방식과 예제 file + 1 title: MoonBlonix 2016-01-14 1652