satotsuのいろいろつくってみた日記

いろいろつくってみたあれこれの記録。

arduinoで相補PWMをだしてみる(再び)

タイマについて聞かれて、前のソースみたらちょっと使いづらかったので修正。

わかりやすく、スイッチング周波数とDuty入れるようにした。

ISR (TIMER1_OVF_vect)は空っぽでも、ないと変になるので注意。

#include <avr/io.h>
#include <avr/interrupt.h>

void PWM_init(uint16_t fs, float duty) {
  TCCR1A  = 0;
  TCCR1B  = 0;
  TCNT1   = 0;
  
  // 0:in, 1:out, DDRB,DDRD: DIO, DDRC: AnalogIn
  // timer0->PD6,5, timer1->PB1,2, timer2->PB3,PD3
  DDRB    = DDRB | B00000110;

  // TCCR1A: COM1A1,COM1A0,COM1B1,COM1B0,-,-,WGM11,WGM10
  // TCCR1B: ICNC1,ICES1,-,WGM13,WGM12,CS12,CS11,CS10
  // COM1x1,COM1x0:   10: OCR1/TOP, 11:1-(OCR1/TOP)
  // WGM13,12,11,10:  1000(updown)
  // CS12,11,10: 000:stop, 001:clk, 010:clk/8, 011:clk/64,
  //             100:clk/256, 101:clk/1024
  TCCR1A  = (TCCR1A & B00001100) | bit(COM1A1) | bit(COM1B1) | bit(COM1B0);
  TCCR1B  = (TCCR1B & B11100000) | bit(WGM13) | bit(CS10);

  // TCNT1: counter
  // TIMSK1: -,-,ICIE1,-,-,OCIE1B,OCIE1A,TOIE1
  TCNT1   = 0;
  TIMSK1  = bit(TOIE1);

  // fpwm = fclk(16MHz)/(2(updown)*N*TOP), TOPmax=2^16
  // N*TOP = 16MHz/(2*1kHz)=8000, N=1, TOP=8000
  ICR1    = 8000 / fs;
  OCR1A   = ICR1 * duty;
  OCR1B   = OCR1A + 8; // deadtime 0.5us -> 0.5us*16MHz=8
}

// TIMER1_COMPB_vect, TIMER1_COMPA_vect, TIMER1_OVF_vect
ISR (TIMER1_OVF_vect) {
  
}

void setup() {
  // put your setup code here, to run once:
  noInterrupts();  
  PWM_init(10, 0.8);
  interrupts();
}

void loop() {
  // put your main code here, to run repeatedly:
}

 

波形はこんな感じ。デッドタイムの500nsもちゃんと入ってる。

f:id:msatotsu:20180519082809p:plain