ATtiny202 正弦波のノイズ問題 TCAで解決! [Arduino]
ATtiny202 正弦波のノイズ問題が解決できました。
Timer/Counter Type A (TCA) は megaTinyCore のデフォルトで millis()/micros() に使われていたため、今まで手を出さなかったのですが、TCBにはない、PERにバッファーが付いた PERBUF や、CMPnにバッファーが付いた CMPnBUF を使わないとなんともならないようでした。
そこで、以下のサンプルプログラムとデータシートを見ながら作ってみました。
Getting Started with TCA
https://www.microchip.com/content/dam/mchp/documents/MCU08/ApplicationNotes/ApplicationNotes/TB3217-Getting-Started-with-TCA-DS90003217.pdf
★はまったところ
はまったところは、megaTinyCore特有のところでした。
・PORTMUXの代替ピンが使用されていた
PA3 (megaTinyCore 4番ピン) → PA7 (megaTinyCore 1番ピン)
・TCAの Split Mode が使用されていた
いくら PERBUF や CMP0BUF を変更しても値が変わらない、、
なぜなら、Split Mode にはこれらがないから。
TCA0.SINGLE.CTRLD = 0; でSplit Mode から Normal Mode に戻す必要があった。
この設定は 「millis()/micros() Timer;"Disabled(save flash)"」にしても有効。
megaTinyCoreでmillis()/micros()は使わないけど、PWMには使うから。
megaTinyCore_megaavr_extras_TakingOverTCA0.md at master · SpenceKonde_megaTinyCore · GitHub
https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/TakingOverTCA0.md
以下、スケッチ。millis()/micros() の割り込みは解除してあります。
Timer/Counter Type A (TCA) は megaTinyCore のデフォルトで millis()/micros() に使われていたため、今まで手を出さなかったのですが、TCBにはない、PERにバッファーが付いた PERBUF や、CMPnにバッファーが付いた CMPnBUF を使わないとなんともならないようでした。
そこで、以下のサンプルプログラムとデータシートを見ながら作ってみました。
Getting Started with TCA
https://www.microchip.com/content/dam/mchp/documents/MCU08/ApplicationNotes/ApplicationNotes/TB3217-Getting-Started-with-TCA-DS90003217.pdf
★はまったところ
はまったところは、megaTinyCore特有のところでした。
・PORTMUXの代替ピンが使用されていた
PA3 (megaTinyCore 4番ピン) → PA7 (megaTinyCore 1番ピン)
・TCAの Split Mode が使用されていた
いくら PERBUF や CMP0BUF を変更しても値が変わらない、、
なぜなら、Split Mode にはこれらがないから。
TCA0.SINGLE.CTRLD = 0; でSplit Mode から Normal Mode に戻す必要があった。
この設定は 「millis()/micros() Timer;"Disabled(save flash)"」にしても有効。
megaTinyCoreでmillis()/micros()は使わないけど、PWMには使うから。
megaTinyCore_megaavr_extras_TakingOverTCA0.md at master · SpenceKonde_megaTinyCore · GitHub
https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/TakingOverTCA0.md
以下、スケッチ。millis()/micros() の割り込みは解除してあります。
// megaTinyCore(mTC) ATtiny202/212/402/412 Sine Wave with TCA
#include <avr/io.h>
#include <util/delay.h>
static const uint16_t OCTAVE9[] = { 7023, 7441, 7883, 8352, 8848, 9375, 9932, 10523,11148,11811,12513,13258 };
static const uint8_t SINE256[] = {
0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 90, 93, 97,100,103,106,109,112,115,118,121,124,
128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173, 176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,
218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244, 245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246, 245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,
218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179, 176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,
128,124,121,118,115,112,109,106,103,100, 97, 93, 90, 88, 85, 82, 79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0 };
void setup(){ // Register Settings
PORTA.DIRSET = PIN7_bm; // PA7 OUTPUT (mTC:1)
//PORTMUX.CTRLC = 0; // turn off TCA port multiplexer (PA7(mTC:1) to default PA3(mTC:4))
TCA0.SINGLE.CTRLD = 0; // turn off split mode
TCA0.SINGLE.CTRLC = 0; // PWM output pins override - disable
TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
TCA0.SINGLE.INTCTRL = 0; // turn off Arduino(mTC) time system
TCA0.SINGLE.PERBUF = 0xff; // top value = 255
TCA0.SINGLE.CMP0BUF = 0; // output value
TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm; // 20MHz / 1 / 256 -> 78,125Hz
}
void loop(){
sineWave( 60, 500); // C4
sineWave( 64, 500); // E4
sineWave( 67, 500); // G4
sineWave( 72, 2000); // C5
_delay_ms(1000);
}
void sineWave(uint8_t midiNum, uint16_t msDuration) {
uint16_t i, di = OCTAVE9[ midiNum % 12 ] >> (10 - midiNum / 12); // 256 times the Wave Table subscript to advance in one cycle
uint32_t cycDuration = F_CPU / 256 / 1000 * msDuration; // Convert duration to number of cycles
do {
TCA0.SINGLE.CMP0BUF = SINE256[ (i += di) >> 8 ]; // 8bit PWM (78,125Hz)
while( !(TCA0.SINGLE.INTFLAGS & TCA_SINGLE_OVF_bm) ); // Waiting for TCA0 overflow
TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; // cleared by writing a '1'
} while( --cycDuration ); // Exit if note data is 0
TCA0.SINGLE.CMP0BUF = 0; // Set output to 0
}
2023-11-25 01:38
nice!(0)
コメント(0)
コメント 0