AVRマイコン総合スレ Part41
■ このスレッドは過去ログ倉庫に格納されています
誰しもが通る系の道よ… 固定少数にしても表示が遅い、間に合わないってんで LCD表示ルーチンの改良してみたり 割り込みでマルチスレッド的に出来ないか? とか アセンブラで書くか? とか、やる訳よ… >>602 >>604 その発想は無かったわ たとえばfloat型数値 3.1415 を小数点第2桁まで文字列にするとしたら まずこいつをint型にキャストして3を取り出し (int) 3.1415 → 3 取り出した3を引いて小数点以下を抽出し、 3.1415 - 3 = 0.1415 抽出した小数点以下に100をかけて再びint型でキャストし 0.1415 x 100 = 14.15 (int) 14.15 → 14 3と14を atoi() 使って文字列に変換。ピリオドを間に挟んで結合すれば 文字列 3.14 のできあがり。こういうことか >>607 >>602 >>604 の助言を無視して float で演算してどうするんだ? 30年前だがZ80でどうしてもfloatが使いたくて、MSX-C 買ったらできないでやんの。 しょうがないからアセンブラでやるfloatのライブラリが載ってる本買って、そこだけ関数呼び出し に書き直してしのいだわ。 sprintfが重いって話だろ? floatの演算自体は仕方なかろうし、大した負荷じゃなかろう。 まあでも小数2桁って決まってるんなら最初から100倍しておいて整数で演算するわな。 そう考えると、昔のBASICとか優秀だよな あれしかメモリなかったのに プログラムのフットプリントを意識出来ないのは池沼やで 昔、友人が変数名がアルファベット1文字というVTL系のコンパイラを作っって 私にくれたことがある。 プログラムサイズは512バイト程度だったと思う。 付属のサンプルプログラムが「月面着陸ゲーム」 だった。 Digi-keyにTiny3216¥119が入荷している。 マルツは¥166 マルツってdigikey発注代行だろ? それでこんなに取るのか ボリ松もびっくりだな 50円でボッタクリ。 じゃあ、Digikey で買えよ。送料払って。 すぐ欲しい数個で買って 数十百個になったら海外通販使う 新しい品種とかは前者で探すのが困難だけど >>621 どうせ人件費は0円とかいう無職の発想でしょ 親が買い置きした家にある食い物はタダ、みたいな >>625 爺さんしか居ないスレでsyamuなんかわかる奴ほぼいないだろ… 632です。神様、今週ボン円140円で買い戻しさせて下さい! UARTで何かデータを受信したら割り込みを発生するテストプログラムを書いてみた。 volatile unsigned char moji='a'; ISR(USART_RX_vect) { char x = UDR0; while (!( UCSR0A & (1<<UDRE0))); UDR0 = ++moji; } int main() { UCSR0B = 0x00; UCSR0A = 0x00; UCSR0C = 0b00000110; UBRR0L = 25; UBRR0H = 0; UCSR0B = (1<<RXCIE0) | (1<<TXCIE0) | (1<<RXEN0) | (1<<TXEN0); while(1) { } } うまく動けばUART経由で一文字打ち込むたびに変数mojiがインクリメントされていきターミナルには bcdefgh・・・ みたいな感じの文字が表示されてしかるべきなのになぜか bbbbbb・・・・ といつまでたってもbしか表示されない。なにか設定おかしいところある? >>636 送信完了ベクタが登録されていないので動作がおかしくなっているんじゃない? 送信割り込みを使わないような設定にすれば良いと思う UCSR0B = (1<<RXCIE0) | (1<<TXCIE0) | (1<<RXEN0) | (1<<TXEN0); ↓ UCSR0B = (1<<RXCIE0) | (0<<TXCIE0) | (1<<RXEN0) | (1<<TXEN0); main()関数内に sei(); が無いけど、割り込み発生するの? >>638 > 送信割り込みを使わないような設定にすれば良いと思う それ!ビンゴだった! え?どゆこと? ”送信割り込み使う”に設定すると ISR(USART_TX_vect) { } 送信側をきちんと定義してあげないと ISR(USART_RX_vect) { } 受信側の挙動に影響が出るってこと? sei()はごめん、コピペするの忘れた^^;) >>639 割り込みベクタテーブルの初期値は 0x0000 だったハズ(データシートを読んでみて下さい) ISR(〜) を定義しないと割り込み発生時に 0x0000 にジャンプする 送信完了→送信完了割り込み発生→ベクタテーブルを参照して 0x0000 にジャンプ(見かけ上、リセット動作となる) 送信完了割り込みが必要無いのなら空の ISR(USART_TX_vect) {} を定義するよりも、送信完了割り込みを禁止したほうがコードサイズが小さくなるし余計な割り込みも発生しませんよ >>639 補足 >受信側の挙動に影響が出るってこと? ISR(USART_RX_vect) 内で送信処理しているでしょ 送信処理が完了すれば ISR(USART_TX_vect) に飛ぼうとするので結果として 0x0000 にジャンプします >>640 そういうことなのね UARTで一文字送信するたびにリセットボタンを押してたようなものか どうりで変数が常に初期化されるわけだ こういう挙動ってちゃんとしっとかんとあかんね(´・ω・`) >>640 横からだけど、なんか勉強になった。ありがとう ATMEGA328P使って環境モニターっぽいことやってる 常時起動してるのは電池の無駄だからスリープ使ってるんだけど スリープ復帰後にI2Cセンサとの通信ができなくなることがある。 詳細に調べてみるとスリープモードが ・パワーダウン ・パワーセーブ ・スタンバイ のときはスリープ復帰後にI2Cが使えない(通信途中でフリーズする)ことが分かった。 ただ唯一、一番省エネ効果が低い ・アイドル に設定するとスリープ復帰後もI2Cは問題無く使える。 I2Cってディープスリープ状態から復帰後は使えなくなるんだっけ? そんな話聞いたことないし、そうだとすれば大炎上してるよ。 ソース晒してみなよ。 もしかしてTWIの電力削減レジスタ弄って、なおかつウェークアップ後初期化してないとか? >>646 全部掲載はさすがに足りないから無理だけど要所くらいなら・・・ ちなみにTWIの電力削減レジスタとか難しいことは一切やってないよ やってることだけどRTC使って一定時間ごとにAVRに割り込み(INT0)かけて起動してデータセーブ。 セーブが終わったらスリープして待機。 具体的にはRTC使ってINT0ピンをLowに引っ張って割り込みをかけてやる。 RTCの仕様でそのままLowに引っ張り続けるからI2C経由でAVRからRTCに命令出してHighに戻すよう命令 (release_interruption関数)。 問題はこのI2C通信で発生するっぽい。パワーダウンスリープから目覚めた直後だとI2C通信の途中で応答不能になり アイドルスリープから目覚めた直後だと問題無く動作する。スリープを一切使わない場合もむろん問題無く動作する。 ↓ちなみに以下ソース #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include "FatFs/ff.h" #include "FatFs/diskio.h" volatile UINT Timer; ISR(TIMER0_COMPA_vect) { Timer++; disk_timerproc(); } // 以上FatFsで必要なタイマー割り込み volatile unsigned char int0_cnt; ISR(INT0_vect) { int0_cnt--; release_interruption(); // ←I2Cで通信しようとするこの関数で止まる } volatile char usart_recvData[256]; volatile unsigned char usart_recv_write; ISR(USART_RX_vect) { char x = UDR0; usart_recvData[++usart_recv_write] = x; } int main(void) { TIMSK0 = _BV(OCIE0A); TCCR0A = _BV(WGM01); TCCR0B = 0b101; OCR0A = F_CPU / 1024 / 100 - 1; EICRA = (0<<ISC01) | (0<<ISC00); EIMSK = 1<<INT0; UCSR0B = 0x00; UCSR0A = 0x00; UCSR0C = 0b00000110; UBRR0L = 25; UBRR0H = 0; UCSR0B = (1<<RXCIE0) | (0<<TXCIE0) | (1<<RXEN0) | (1<<TXEN0); sei(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); int0_cnt = 5; while (1) { if ( int0_cnt == 0 ) { int0_cnt = 5; save_data(); } sleep_mode(); } } 俺は小心者なので、 割り込みハンドラの中で通信ルーチンコールとか、 怖くて出来ない スタック食い潰しの原因追求で泣きそう になったこととかあるし… INT0割り込み→i2cでRTCにINT0ピンHIGH指示→割込処理から抜ける。でもこのときRTCはまだINT0ピンHIGHの処理完了してないので、またINT0割り込み入る。AVRはi2c始めようとするけどRTCは前の指示実行中なのでしらんぷり。 >>INT0ピンHIGH指示 の後に割り込みをすぐに抜けずに、INT0ピンがHiになるのを待ってから抜ければOKってことか。 ちょっと待て EICRA = (0<<ISC01) | (0<<ISC00); ってなんぞ? これじゃ EICRA=ISC01|ISC00 と同じだから、立ち上がりトリガにならんか? (他もだけど…) >>655 ならない。無意味ではあるけど… 普通は EICRA &= ~(_BV(ISC01) |_BV(ISC00) ); かな。 _BV() 使ったり、直接シフトしたり一貫性がないとは思う >>656 ちょっと興味あったので・・・ DDRA = (0 << PA0) | (0 << PA1) ; は out DDRA, zero ふむふむ DDRA |= (0 << PA0) | (0 << PA1) ; は in tmp, DDRA out DDRA, tmp うーむ -Os オプション付けても刈取らないのね・・・ (atmel stuido 7) 意図して読み出した1を書き戻すことも有るからね。バグになっちゃう。 秋月の通販サイトみたらDIPのAVRマイコンATMEGA1284P−PUが売ってた。 750yen AVRマイコンの未来は明るい。 >>660 http://akizukidenshi.com/catalog/g/gI-04461/ 発売日 2011/01/04 128Kバイトもの巨大なプログラムメモリと、16Kバイトもの広大なSRAMを内蔵しています。 ちなみに http://akizukidenshi.com/catalog/g/gI-13921/ 発売日 2019/02/22 プログラムメモリ:256KB RAM:28KB >>664 DIPだからクソデカくて面白いって話なのにSMD貼られても…… >DIPだからクソデカくて面白いって話 それどこに書いてる? >>665 の脳内、しかも17:37:05頃のこと。 フラッシュを10,000回書き換えて 書き込み不能にした強者っているのかな >>669 オレもどっかで見た。だけどフラッシュではなくEEPROM(PICの) >>670 http://madlabo.oops.jp/MAD/0026/0026.htm ここのオッチャン、リレー式計算機とか作ったり色々とやってるな しかし電子工作者のこの文体のテンション、ついていけない… >>672 罐パッケージのAVRがあるのかと思ったw > フラッシュを10,000回書き換えて > 書き込み不能にした強者っているのかな 何回書きかえたら壊れるか(書けなくなるか)に関しては 実際に試して確認した情報を どっかで見たな ESP-WROOM-02にリセットボタンを付けて連続でパチパチとリセットしてたら、 テレビの受信デシベルが低くなって映像が途切れたりした。 2.4Ghzって地デジの電波に影響あるんだな >>678 球状の缶からウニみたいに出てくるリード 誰か作らんかなぁ フラッシュに書き込んだプログラムがいつまで保持されてるのか気になる たしか100年ぐらいは持つんだっけな? 書き込みを繰り返したやつは酸化膜がやられてて電荷が抜けるのが早くなるだろう >>680 フラッシュは20年や データシートの表紙みろや ちょっとさっきくしゃみしたら 変換基盤に仮置きしていたATtiny10が全部消えたんだが? こないだ家電のケンちゃんで書き込み用補助具買ったばかりなんだが? 秋月の10個入り全部消えたんだが? 朝の鼻くそに混ざっていそうなんだが? 小せいのはICでなくお前のケツの穴というオチかい? >>673 缶のオペアンプを開けて中にATtiny85埋め込むか? >>684 バカヤロー鼻くそだって書いてあっだろ! 俺の繊細なケツからあんなもん出てきたらあっという間にパンツ血まみれ SSDなら耐久テストをしたサイトがあったな 東芝製が書き込み禁止にして保護するとか UART経由でターミナルに文字列吐いてからパワーダウンスリープするプログラム作ってみたんだけど、 void uputc(unsigned char x) { while( !(UCSR0A & (1<<UDRE0)) ) ; UDR0 = x; } ターミナルに表示される文字列の末尾が文字化けしてしまう。 (上記のプログラムは一文字UARTに送信する関数。 これを連続呼び出しすることで文字列をターミナルに送ってる) パワーダウンではなくアイドルスリープに変更したり、スリープそのものをしないようにすれば 末尾まで正常に表示されることからUARTの送信バッファから文字が全て吐かれる前に AVRがスリープしちゃってるのが原因じゃ無いかと踏んだ。 だったら送信バッファが空になるまで待てばいいじゃんと思い、 void uputc(unsigned char x) { while( !(UCSR0A & (1<<UDRE0)) ) ; UDR0 = x; while( !(UCSR0A & (1<<UDRE0)) ) ; } と修正してみたけど変わらなかった。他にも送信シフトレジスタが空になったとされるTXCフラグが1 になるまで待ってみたりしたけど、 while( !(UCSR0A & _BV(TXC0)) || !(UCSR0A & _BV(UDRE0)) ) ; これも変わらなかった。最後の一文字までターミナルに無事送り届けられたタイミングを知るには どうしたらいいのかな? >>689 AVRのプログラム経験あまり無いけどバッファが空に成った後に空ループ回しながら暫く待ってスリープは試してみた? TXCフラグは割り込みを使用していなければ、 プログラムから動的にクリアされなければならない。 UDR0 = x; の次に UCSR0A |= _BV(TXC0); っていれてみれば? >>690 の対症療法でもいいが…そもそも根本的な勘違いがある。TXCフラグの説明読んだか? 『The TXCn Flag bit is automatically cleared when a transmit complete interrupt is executed, or it can be cleared by writing a one to its bit location.』 とある。日本語にすると『TXCnフラグは、送信完了割込みを起こすか、自分で1を書くことで初期化できます。』ということだ つまり、送信完了割込みを使ってないのならば、自分で毎回クリアしないと、最初に何か送信して空になって1になったら…あとはずっと1のままだ!!! 送信中は0で終わったら1に勝手に変わるとかいう便利なものではないぞ??? なぜ動かないんだ!MPUのバグか? って時の99%は、データシートをちゃんと読んで 無かった自分のせい どうでも良いけど、なぜ loop_until_bit_is_clear(); 使わないんだ? >>690 ↓みたいにforループ1000回入れてみたら最後までターミナルに正しく表示されるようになったから たぶん送信バッファを確実に空にするまで待つ、という戦略であってると思う void uputc(unsigned char x) { while( !(UCSR0A & (1<<UDRE0)) ) ; UDR0 = x; for(int i=0;i<1000;i++) ; } >>691 ほ、ほんとだ! void uputc(unsigned char x) { while( !(UCSR0A & (1<<UDRE0)) ) ; UDR0 = x; UCSR0A |= _BV(TXC0); while( !(UCSR0A & (1<<UDRE0)) ) ; } これでも正しく末尾まで正しくターミナルに表示されるようになった! >>692 そういうことなのね。自分で1にsetしてやらないと0に戻らないのね。 勉強になった、ありがとうノシ Aliで売ってる1000円以下のJTAGって使い物になる? >>695 for(int i=0;i<1000;i++); って、最適化したら真っ先に消されるコードだろ? >>697 intの前に「volatile」付ければ? >>695 問題解決良かったね。 >>692 AVR初心者として参考になった。 ありがとう。 >>693 そう。焦れば焦るほどバグ、つまり自分のミスに気付かない。 俺はプログラミングは己れの煩悩を取り払う能力を養う最強の修行法だと解ったわ。 >>695 送信後のウエイト処理で見ているフラグが違うと思います。 while ( !(UCSR0A & (1<<TXC0)) ); こうじゃないですか? ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる