Arduino AVRでマルチタスクしてみる タスク2 [ATmarquino Arduino]
ファイル名を変えずに中身を書き換えちゃったのは、まずかったかなぁ、、、
マルチタスクのサンプルとして、PWMで50Hzのサイン波を出力するデモ。
別途用意したスイッチを押す度に別途用意したLPFを通してサイン波が出力される。ただし10秒間掛けて波形はフェードアウトする。
/**********************************************************/ /* マルチタスクやってみる */ /* PWMで50hzのサイン波を出力する。10秒掛けてフェードアウト。 */ /**********************************************************/ #include <avr/io.h> #include <FlexiTimer2.h> #include "delivertive.h" extern "C" { #include "mul_tsk.h" } /**********************************************************/ /* prototypes */ /**********************************************************/ void tsk_ini( void ); void stackMonitor( void ); void switchScanTask( void ); void pwmGenerateTask( void ); /**********************************************************/ /* valiables */ /**********************************************************/ SYSTIM systim; // 1msでインクリメントする変数 uint8_t tsk0_stk[ 128 * 1 ]; uint8_t tsk1_stk[ 128 * 1 ]; uint8_t tsk2_stk[ 128 * 1 ]; #define PWM_PIN 10 #define TRIGGER_PIN 2 #define LED_PIN 13 #define TIMER_COUNTER_CLOCK (8 * 1000000UL) #define PWM_FREQUENCY (10 * 1000) #define RESOLUTION (40) /* 50hz * 40 over sampling. */ #define DELTA_SLOPE (1.0f / 500) int scale = TIMER_COUNTER_CLOCK / PWM_FREQUENCY / 2; /* 1000000 is timer clock */ int offset = TIMER_COUNTER_CLOCK / PWM_FREQUENCY / 2; /* center position */ int waveTableCounter; float slope = 1.0f - DELTA_SLOPE; /* 10s = 20ms * 500 */ int originalWaveTable[ RESOLUTION ]; unsigned int waveTable[ RESOLUTION ]; unsigned char switchScanUpdate; unsigned long timer1CompbIsrCounter; bool conversionStart = false; /**********************************************************/ /* setup */ /**********************************************************/ void setup() { Serial.begin( 115200UL ); Serial.println( "AVR Multi Task Demo." ); /* ststem and pwm update timer start. */ FlexiTimer2::set( 5, 1.0f / 10000, pwmUpdateHandler ); FlexiTimer2::start(); tsk_ini(); //タスクの初期化 sta_rdq( ID_monitor ); //ラウンドロビン開始。ここからタスクが開始される } /**********************************************************/ /* loop ※使われない */ /**********************************************************/ void loop() { } /**********************************************************/ /* タスク初期化 */ /**********************************************************/ void tsk_ini( void ) { reg_tsk( ID_monitor, (void *)stackMonitor, (void *)tsk0_stk, sizeof(tsk0_stk), 0,0,0,0 ); reg_tsk( ID_switchScan, (void *)switchScanTask, (void *)tsk1_stk, sizeof(tsk1_stk), 0,0,0,0 ); reg_tsk( ID_pwmGenerate, (void *)pwmGenerateTask, (void *)tsk2_stk, sizeof(tsk2_stk), 0,0,0,0 ); sta_tsk( ID_monitor ); // sta_tsk( ID_switchScan ); // sta_tsk( ID_pwmGenerate ); } /**********************************************************/ /* stack monitor task */ /**********************************************************/ static unsigned int RemainStack( void *stk, unsigned int sz ); static void stackPrint( const char *msg, void *stk, unsigned int sz ); void stackMonitor( void ) { sta_tsk( ID_pwmGenerate ); while( 1 ) { dly_tsk( 10 * 1000UL ); stackPrint( "task1 stack : ", tsk1_stk, sizeof(tsk1_stk) ); stackPrint( "task2 stack : ", tsk2_stk, sizeof(tsk2_stk) ); stackPrint( "monitor stack : ", tsk0_stk, sizeof(tsk0_stk) ); } } static void stackPrint( const char *msg, void *stk, unsigned int sz ) { Serial.print( msg ); Serial.print( RemainStack( stk, sz ), DEC ); Serial.print( "/" ); Serial.println( sz, DEC ); } static unsigned int RemainStack( void *stk, unsigned int sz ) { unsigned int i; char *ptr = (char *)stk; for( i = 0; i < sz; i++ ) { if( *ptr++ != 0 ) break; } return sz - i; // return i; } /**********************************************************/ /* switchScanTask */ /**********************************************************/ void switchScanTask( void ) { pinMode( TRIGGER_PIN, INPUT_PULLUP ); unsigned char sw = 0x00; while( 1 ) { sw <<= 1; if( digitalRead( TRIGGER_PIN ) == LOW ) sw |= 1; if( (sw & 0x0f) == 0x07 ) { switchScanUpdate++; } dly_tsk( 50UL ); } } /**********************************************************/ /* PWM Generate Task */ /**********************************************************/ void pwmGenerateTask( void ) { pinMode( PWM_PIN, OUTPUT ); digitalWrite( LED_PIN, LOW ); pinMode( LED_PIN, OUTPUT ); /* wave table generate. */ for( int i = 0; i < RESOLUTION; i++ ) { int tempI = (int)(sin( 2 * M_PI * i / RESOLUTION) * scale); originalWaveTable[ i ] = tempI; waveTable[ i ] = (unsigned int)tempI + offset; Serial.print( waveTable[ i ], DEC ); Serial.print( "," ); if( (i % 10) == 9 ) Serial.println(); } /* start switch scan task. */ sta_tsk( ID_switchScan ); while( 1 ) { /* wait for switch pushed. */ unsigned char switchScanUpdateBase = switchScanUpdate; while( switchScanUpdateBase == switchScanUpdate ) dly_tsk( 50UL ); switchScanUpdateBase = switchScanUpdate; Serial.println( "pwmGenerateTask PWM start." ); /* timer counter initialize. */ TCCR1B = 0x00; // timer1 stop TCNT1 = 0x0000; // 16bit counter clear TIMSK1 = 0x00; // interrupt disable TCCR1A = 0b00100011; // 0b00 10 00 11 // OC1A : normal port and not connected OC1A. // OC1B : compare match goes OC1B to clear and top goes OC1B to set. // fast PWM and top is OCR1A. TCCR1B = 0b00011001; // 0b0 0 0 11 001 // fast PWM and top is OCR1A. // clkIO / 1 priscaller. OCR1A = (unsigned int)(TIMER_COUNTER_CLOCK / PWM_FREQUENCY); OCR1B = waveTable[ 0 ]; TIMSK1 = 0x00; /* interrupt timer start. */ slope = 1.0f - DELTA_SLOPE; waveTableCounter = 1; conversionStart = true; digitalWrite( LED_PIN, HIGH ); /* wait 10s. */ dly_tsk( 11 * 1000UL ); conversionStart = false; for( int i = 0; i < RESOLUTION; i++ ) { int tempI = originalWaveTable[ i ]; waveTable[ i ] = (unsigned int)tempI + offset; } Serial.println( "pwmGenerateTask PWM stop." ); digitalWrite( LED_PIN, LOW ); } } /**********************************************************/ /* pwm update handler */ /**********************************************************/ void pwmUpdateHandler() { static int count = 0; /* system timer update */ if( count & 1 ) systim += 1UL; count++; if( conversionStart == true && slope >= 0.0f ) { OCR1B = waveTable[ waveTableCounter ]; float tempF = (float)originalWaveTable[ waveTableCounter ] * slope; waveTable[ waveTableCounter ] = (unsigned int)tempF + offset; if( ++waveTableCounter >= RESOLUTION ) { waveTableCounter = 0; slope -= DELTA_SLOPE; } } }
2018-10-25 16:17
nice!(0)
コメント(0)
コメント 0