🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

1回答

2114閲覧

ソフトウェアからハードウェアに置換えが分かりません

jyojyo

総合スコア3

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2021/02/05 03:41

編集2021/02/09 01:49

この2つを同じ意味合いにしていますがコンパイルは通り動作が違います‼️
どこをどのように変えればいいですか?

動作成功

Arduino

1#define F_CPU 8000000UL 2#include<avr/io.h> 3#include<util/delay.h> 4const uint8_t tempo = 100; /*記憶*/ 5void playTone(uint16_t tone, uint16_t duration) { 6 for (uint32_t i = 0; i < duration * 1000L; i += tone * 2 / 10) {/*duration=期間*/ 7 PORTC = 0x0000001; 8 for (uint16_t j = 0; j < tone / 10; j++) { 9 _delay_us(1); /*X ミリ Oマイクロ*/ 10 } 11 PORTC = 0x0000000; 12 for (uint16_t j = 0; j < tone / 10; j++) { 13 _delay_us(1); 14 } 15 } 16 17 return; 18}

動作失敗
※このプログラムを動作同じにしていくこと

Arduino

1#define F_CPU 8000000UL 2#include<avr/io.h> 3#include<util/delay.h> 4#include <avr/interrupt.h> 5const uint8_t tempo = 100; //char 6const byte PIN_BUZZLE = 10; 7const byte PIN_INTERRUPT = 23; 8volatile byte state = LOW; 9void playTone(uint16_t tone, uint16_t duration) { 10 pinMode( PIN_BUZZLE, OUTPUT ); 11 digitalWrite( PIN_BUZZLE, state ); 12 13 attachInterrupt( 14 digitalPinToInterrupt(PIN_INTERRUPT), 15 toggle_BUZZLE, FALLING ); 16} 17 void duration() { 18 digitalWrite( PIN_BUZZLE, state ); 19} 20 void toggle_BUZZLE(){ 21 state != state; 22 _delay_us(1); 23 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2021/02/05 06:03

なにをハードウエアに置き換えるというはなしでしょうか
jyojyo

2021/02/05 10:15

ブザーとスイッチとの時間で動作するプログラムをハードウェアに置換えるという話をです
y_waiwai

2021/02/05 10:43

その中のどれをハードウエアで置き換えるんでしょうか。
y_waiwai

2021/02/05 10:45

質問が意味不明です なので回答しようにもやりようがないという状況
jyojyo

2021/02/06 14:36 編集

Tmr0レジスタを使って割り込みを行うこと考えています そして音楽みたいになるべく正確にしていくようなタイマーを考えています。
thkana

2021/02/06 04:35

レジスタはそもそもハードウェアですが?(ついでに言えばスイッチもブザーもハードウェア) タイマーペリフェラルを使うことを「ハードウェア」と言っているのだと想像はしていますが... よくわからない言葉を無理に間違って使うより、平易な言葉でもやりたいことをちゃんと主語述語を揃えて表現したほうが伝わると思います。 [事象1]から[事象2]までの時間をできるだけ正確に1秒にしたい。そのためにはタイマーを使うのが解になると思われる。そうすると以下のプログラムをどう変更するのか という質問なのかなぁ。ただ、質問には事象1/事象2が何なのか明らかにされていないのですよ。なにが1秒? あと、「ピン番号は変えないで行うこと 」が課題感を醸し出して、意欲を削ぎますね。
jyojyo

2021/02/06 14:53 編集

thkanaさん何言っているのか分からないので答え方が分かりません‼️ 結局、 thkanaさんは曲をシャウト(TTJ)に置換えたいということかなぁ❔ だったらよろしくお願いします
thkana

2021/02/06 21:56

「[事象1]から[事象2]までの時間をできるだけ正確に1秒にしたい。そのためにはタイマーを使うのが解になると思われる。そうすると以下のプログラムをどう変更するのか」 これで質問の趣旨が合っているなら、事象1と事象2を説明して下さい、ということです。事象というのは、「何かが、変化する」ということです。 事象1: なにが、どうなること 事象2: なにが、どうなること その間が1秒、という話になるでしょう。 そういう質問でないのなら、そう言っていただければまた考えますが。
jyojyo

2021/02/07 02:10

やっと理解した。 1.ledのランダムの曲からブザーが鳴るまでの時間を正確にすること 2.押しボタンをたたいてledとブザーが鳴るまでの時間を正確にすること を考えています。
thkana

2021/02/07 05:01

事象1と事象2をそれぞれ置き換えて、 [ledのランダムの曲からブザーが鳴るまでの時間を正確にすること]から[押しボタンをたたいてledとブザーが鳴るまでの時間を正確にすること]までの時間をできるだけ正確に1秒にしたい。そのためにはタイマーを使うのが解になると思われる。そうすると以下のプログラムをどう変更するのか」 ということですか?
jyojyo

2021/02/07 11:30

ledのランダムの曲からブザーが鳴るまでの時間と,押しボタンをたたいてledとブザーが鳴るまでの時間をできるだけ正確に1秒にしたい。そのためにはタイマーを使うのが解になると思われる。そうすると以下のプログラムをどう変更するのか」 ということです。
thkana

2021/02/07 12:24

「ledのランダムの曲からブザーが鳴るまでの時間」というのはわかりかねますが、 「押しボタンをたたいてledとブザーが鳴るまでの時間をできるだけ正確に1秒」というのは もしかして、前者の(これまでの質問で育ててきた)プログラムとは全く関係なく、 「参考」と称するプログラムを原型としてスイッチをONにしてからタイマーでカウントして1秒後にLEDが点灯してブザーが鳴る動作をするプログラムをArduino環境で作成すればよい、ということですか?
thkana

2021/02/07 23:39

ぎゃふん。 参考のプログラムには押しボタンスイッチはないですがどうしましょう。 そもそもないのでは > ※ピン番号は変えないで行うこと という条件を満たしようがないです。
jyojyo

2021/02/08 11:21 編集

ピン番号は変えなかったら大丈夫です
thkana

2021/02/08 11:18

> 回答1に表して置きました それは、 「参考」と称するプログラムを原型としてスイッチをONにしてからタイマーでカウントして1秒後にLEDが点灯してブザーが鳴る動作をするプログラム とは似ても似つかぬものなのですが...
jyojyo

2021/02/08 11:22

質問のところに置きました そしてこれ以上の質問は分かりません
guest

回答1

0

ハードに変更したいというよりも、多分、音が悪いから改善したい、という事だと思いますけど、
この書き方だと、当然ながら音(周波数)は理想値とはかけ離れます。
作者の人も理想値の音は聞いていないでしょう。
※但し、逆にこのプログラムに合わせてデータ部を調整した可能性はあります。
その場合、プログラムを良くしても、逆に鳴る音が悪くなる事もあり得ますから。

最も悪い部分は

for (uint16_t j = 0; j < tone / 10; j++) {
_delay_us(1); /X ミリ Oマイクロ/
}
PORTC = 0x0000000;
for (uint16_t j = 0; j < tone / 10; j++) {
_delay_us(1);
}

です。for文の部分の繰り返し処理で8クロック程度かかるのではないでしょうか。
8クロックだとMHz駆動で1usです。
そうなると、本来の時間の2倍のディレイになります。

この1usを時間分繰り返す処理は、固定しか引数に出来ない_delay_us関数の仕様から来ています。
これをArduinoの関数にします。

PORTC = 0x0000001;
delayMicroseconds(tone/10);
PORTC = 0x0000000;
delayMicroseconds(tone/10);

これでほんの僅かしか、理想値とのずれはありません。

同じ理由で、繰り返し処理になっている

for(uint16_t k = 0; k < beat[line[i]][j] * tempo; k++) {
_delay_ms(1); //rest(milli)
}

ですけど、こちらは_deley_msですから、上述の_delay_usとは誤差が1/1000も違います。
なのでこのままでも問題ないでしょうけど、ついでなので直した方が良いです。つまり

delay(beat[line[i]][j] * tempo);

で、これが、「ハードに変更」したものに極近い音です。
これ以上は苦労の割りに、それほど変わらないと思いますよ。
っていうか、タイマ割り込みで作るなら1から書き直しでしょう。

投稿2021/02/06 20:59

nac_tnk

総合スコア494

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jyojyo

2021/02/08 06:30

そのままソフトウェアですよね?
nac_tnk

2021/02/08 08:56

そうですね。ただし、元も、今回のも全くのソフト処理ではありませんよ。 元のは1usというのをハード(クロック数)で計測しています。 後者はタイマーを参照して時間を計測しています。 要は、「それ以外の無駄な時間」を省いた、というだけです。
jyojyo

2021/02/08 09:28

要するにこのプログラムにして欲しい #define F_CPU 8000000UL #include<avr/io.h> #include<util/delay.h> const uint8_t tempo = 100; //char //Korobushka uint8_t notes[2][50] = {"gdefedccegfeddefgecc facbagdgfeddefgecc n", "afgefdc afgeegba n"}; //a space represents a rest uint8_t level[2][50] = {{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0}, {4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 0}}; uint8_t beat[2][50] = {{ 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2+1, 2, 1, 2, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2}, {4, 4, 4, 4, 4, 4, 4, 4+1, 4, 4, 4, 4, 2, 2, 4, 4, 4}}; uint8_t line[] = {0, 0, 1}; void playTone(uint16_t tone, uint16_t duration) { for (uint32_t i = 0; i < duration * 1000L; i += tone * 2 / 10) { ISR(TIMER0_COMPA_vest)//タイマ割り込み { PORTC = 0xFF;//ポートCを反転 } return; } void playNote(uint8_t note, uint16_t level, uint16_t duration) { uint8_t names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b'}; uint16_t tones[] = { 19111, 17026, 15169+1, 14317, 12755, 11364, 10124}; /* timeHigh = period / 2 = 1 / (2 * toneFrequency) where the different tones are described as in the table: note frequency period timeHigh c4 261.63 Hz 3830 1911.0958223445323548522722929328 (261->1915=1915.7088122605363984674329501916) d4 293.66 Hz 3400 1702.6493223455697064632568276238 (294->1700=1700.6802721088435374149659863946) e4 329.63 Hz 3038 1516.8522282559233079513393805175 (329->1519=1519.7568389057750759878419452888) f4 349.23 Hz 2864 1431.7212152449674999284139392378 (349->1432=1432.6647564469914040114613180516) g4 392 Hz 2550 1275=1275.5102040816326530612244897959 a4 440 Hz 2272 1136=1136.3636363636363636363636363636 b4 493.88 Hz 2028 1012.3916740908722766663966955536 (493->1014=1014.1987829614604462474645030426) c5 523.25 Hz 1912 955.566172957477305303392259914 (523->956=956.02294455066921606118546845124) */ //play the tone corresponding to the note name for (uint8_t i = 0; i < 7; i++) { if (note == names[i]) { uint8_t a = level - 4; playTone(tones[i] / pow(2, a), duration); } } return; } void setup() { /* DDRx:Set i/o. 0->input, 1->output. When input, must pullup. cf.mega88A.pdf:14.2.3. "入出力間の切り替え" PORTx:write only PINx:read only */ DDRC = 0b0000001; //output:buzzer(PORTC0) DDRB = 0x00; //input:switch(PINB5) //<iom328.h>#define PINB5 5 PORTB = 0xff; //When input, must pullup. DDRD = 0x00; //i/o:key(PORT0-7) PORTD = 0xff; //When input, must pullup. //タイマ0,CTC,割り込み用、比較A一致で割り込み TCCR0A = 0b00000010; TCCR0B = 0b00000011; // N=64 OCR0A = 78; // 5msごとに割り込み TIMSK0 = 0b0000010; //比較A一致割り込み有効 //方向レジスタの設定 DDRC = 0xff; //Cを出力 DDRD = 0xff; //Dを出力 PORTB = 0xff; //割り込み許可 sei(); while(1){ ; } } void loop(){ static bool a_mode = 0; //0-manual, 1-auto main_loop: if(bit_is_clear(PORTD,PORTD7)) PORTB = PORTB & ~_BV(PB1); if(a_mode){ //auto(PINB == 0b00100000) DDRD = 0xff; //output only for(uint8_t i = 0; i < 3; i++){ //num of line for (uint8_t j = 0; ; j++) { if (notes[line[i]][j] == ' ') { delay(beat[line[i]][j] * tempo); _delay_ms(1); //rest(milli) } else if (notes[line[i]][j] == 'n') { //When (j < length[i]), for{} continues. break; } else{ uint8_t k; if(notes[line[i]][j] == 'c'){ if(level[line[i]][j] == 4){ k = 0; } else{ k = 7; } } else if(notes[line[i]][j] == 'a'){ k = 5; } else if(notes[line[i]][j] == 'b'){ k = 6; } else{ for(k = 0; k < 5; k++){ if(notes[line[i]][j] == 'c'+k){ break; } } } PORTD ^= _BV(k); playNote(notes[line[i]][j], level[line[i]][j], beat[line[i]][j] * tempo); PORTD ^= _BV(k); }//if if(!(PINB & _BV(5))){//auto(PINB is 0x00) a_mode = 0; goto main_loop; } }//for }//for }//auto else{ //manual(PINB == 0x00) DDRD = 0x00; //input only PORTD = 0xff; //pull up switch(PIND){ case 0b11111110: do{ playNote('c', 4, 1 * tempo); }while(PIND == 0b11111110); break; case 0b11111101: do{ playNote('d', 4, 1 * tempo); }while(PIND == 0b11111101); break; case 0b11111011: do{ playNote('e', 4, 1 * tempo); }while(PIND == 0b11111011); break; case 0b11110111: do{ playNote('f', 4, 1 * tempo); }while(PIND == 0b11110111); break; case 0b11101111: do{ playNote('g', 4, 1 * tempo); }while(PIND == 0b11101111); break; case 0b11011111: do{ playNote('a', 4, 1 * tempo); }while(PIND == 0b11011111); break; case 0b10111111: do{ playNote('b', 4, 1 * tempo); }while(PIND == 0b10111111); break; case 0b01111111: do{ playNote('c', 5, 1 * tempo); }while(PIND == 0b01111111); break; default: break; } if(PINB & _BV(5)){//manual(PINB is 0x20) a_mode = 1; } }//manual }//while そしたらエラーが出たからなおして error: expected unqualified-id before string constant error: a function-definition is not allowed here before '{' token error: a function-definition is not allowed here before '{' token error: a function-definition is not allowed here before '{' token error: a function-definition is not allowed here before '{' token error: expected '}' at end of input exit status 1 expected unqualified-id before string constant
nac_tnk

2021/02/08 09:47

> TIMER0_COMPA_vest 名称が違いますけど、根本的な問題で、割り込み関数を関数内に書く事はできません。
jyojyo

2021/02/08 11:49

ならばできるようにするにはどうしたらいいですか? そして上のエラーについてなおして欲しいです。
nac_tnk

2021/02/08 13:57

まず割り込みの意味合いが違います。 割込みはプログラムのどこを実行していようとそのタイミングになったらプログラム中に割り込みます。 全く逆です。 そんな感じでそこで音を鳴らしたいだけなら↑のdelayMicrosecondsが適当だとおもいます。 割り込みでおこないたいのなら、ほぼ全てのプログラムを割り込み中に書く、という全く異なるプログラムになると思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問