PWMの周期は、タイマーのオーバーフロー率によって決まります。Modes of Operationセクションには、考慮すべき多くの設定があります。デューティサイクルが可変の一定周期の方形波を生成するだけの場合は、CTC(比較タイマーのクリアタイマー)モードを使用したいと思うでしょう。基本的な考え方は、次にピンをトグルするまでOCR0Aをタイマーティックの数に設定し、比較一致割り込みを使用して次回のその値を変更することです。したがって、avr-gccでは次のようになります。
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
// global variables defining number of ticks on and off
uint8_t on_time_ticks, off_time_ticks, csxx_bits=0;
void setup_timer(double p_ms, double duty){
TCCR0A = _BV(COM0A0) // toggle OC0A on Compare Match
TCCR0B = _BV(WGM02); // set CTC mode WGM0[2,1,0] = 0b100
// ... do some stuff based on your CPU frequency
// to define the csxx_bits of TCCR0B when the timer is running
// and consequently, to set on_time_ticks and off_time_ticks
OCR0A = on_time_ticks;
TCCR0B |= your_settings_here;
}
void start_timer(){
//start the timer running at the desired rate
TCCR0B |= csxx_bits;
}
int main(int argc, char **argv){
double period_ms, duty_cycle;
setup_timer(period_ms, duty cycle);
start_timer();
for(;;){
//spin or sleep or whatever
}
}
ISR(TIM0_COMPA_vect){
if(OCR0A == on_time_ticks){
OCR0A = off_time_ticks;
}
else{
OCR0A = on_time_ticks;
}
}
警告、これはテストされていないコードですが、アイデアは正しいと思います。これが唯一の方法でもありません。
ところで、ATTiny13について知っておくべきことが1つあります。内部RCオシレータは、工場フロアから10%以内の精度でのみ保証されています。ATTiny13の精度を2%にするユーザーキャリブレーションプロセス(atmel appnoteで説明)があります。あなたがそれよりももっとうまくやりたいなら、おそらく外部の水晶に対応するチップを使う必要があるでしょう...