AVRマイコン総合スレ Part41
■ このスレッドは過去ログ倉庫に格納されています
>>572
static int stdPutc( char c, FILE *stream );
static FILE suStream = FDEV_SETUP_STREAM( stdPutc, NULL, _FDEV_SETUP_WRITE );
static int stdPutc( char c, FILE *stream )
{
while ( !( UCSRA & (1<<UDRE) ) );
UDR = c;
return 0;
}
int main( void )
{
stdout = &suStream;
printf_P( PSTR("Hello world") );
}
ヘッダファイルとUSARTの初期化は省略しているので注意。(あくまでも標準出力を設定するサンプルなので) そもそも、Cにおいてprintf()ってのは関数を呼び出す以上の
意味はないからな…
printf()が具体的に何をするかは知らんもの コンソールアプリでC言語勉強はじめたばかりのガキ臭がする デバッガ使うまでも無い小さなプログラムならprintf()で変数の内容表示とか割と便利(出力先をLCDにしておいても良いし)
ただ標準のprintf()はコードが無駄に大きいので似たような関数を自作した方が良いと思う 何故画面に出力される事が標準乃動作と思ふのだらうか >>576
平気で、printf()は「画面に」出力する「命令」です
なんて教える教師や教科書があるからなぁ…
そう言うのに当たっちゃったら、やむを得ない気がする まぁパソコンのソフトウェア開発から入れば高級言語しか知らんだろうし… lcd繋げて、それに出力する様作っても良いんだよ! >>580
おまえらの世代はパンチカードだったかもしれんが、
入門者には画面と教えて問題ないだろ >>574
いまいち何やってるのかよく分からないけど
printf_UART()
なる関数を自作するよりかはスマートな方法なのね
たしかにprintf()で書いていた方が
UARTに出力するかLCDに出力するかそのときに応じて
ソースコードをほとんどいじらずに瞬時に対応できるよね >>584
マニュアルちゃんと読もうぜ
avr-libcのマニュアルに丁寧な解説付きで書いてあるぞ 久しぶりにマイコンいじった。mega3208ってやつ
これ8bitAVRコアにUC系のペリフェラルっぽいな xmega系列になって従来のmega/tinyとちょっと変わったんだ。
UC系の周辺と揃えようって意思はあったんだろうね。
mega3208は名前こそmegaだけどxmega系の子孫なのよ。 同じ処理を、3種類の環境でコンパイルしてみた。
cc5xは、制限の多いコンパイラで、ページを自分で割り付けなければ
ならないのと、固有の構文を多用する。
xcは、proバージョンでどのくらいコードがスリム化するんだろう?
gccベースという使いやすさと、PIC以外でも使えるので価格が折り合えば使いたいな。
avrgccは、データメモリとレジスタの転送でコードが膨らんでいるけど、対CPUクロックで考えると速度的に問題ないはず。要求プログラムメモリは要注意。PICは、word,avrは byteで単純比較できないけどね。
PIC cc5x (PIC16F18313)
; RAM usage: 51 bytes (11 local), 205 bytes free
; Maximum call level: 4 (+3 for interrupt)
; Total of 1027 code words (50 %)
PIC xc8 free (PIC16F18313)
Memory Summary:
Program space used 5ECh ( 1516) of 800h words ( 74.0%)
Data space used 41h ( 65) of 100h bytes ( 25.4%)
avrgcc (atmega48)
Program Memory Usage 3586 bytes 87.5 % Full
Data Memory Usage 42 bytes 8.2 % Full ATmega328PのUARTポート(RX, TX)とUSBシリアル変換器
http://akizukidenshi.com/catalog/g/gK-06894/
のUARTポート(TX, RX)をつないでPC上で立ち上げたTera Termをモニタ代わりに使用してる。
これはこれで問題無くモニタ出来てるんだけど他に問題があって
AVRの電源を切ってもAVRが稼働し続けてることに気付いた。
はじめ何が起きてるのかよく分からなかったけどテスターを当てていくと
USBシリアル変換器のUARTポートからAVRのUARTポートに電気が流れて
その電流が寄生ダイオードを経由してかAVRの電源側に回り込んで結果的に
AVRが稼働し続けてるっぽいことに気付いた。
大元たどるとパソコンのUSBポートの5Vが電気の供給源ってことになるね。
この状態でAVRの書き込みも出来るから恐ろしい。
AVRのUSBポートから流れ込んできた電気でAVRが稼働するってのも
AVRにとってあまりよろしくない状況だと思うんだけど何か解決方法ってあるかな? そもそも電源の入っていないマイコンにUSBシリアル変換を接続しっぱなしにするのが間違った使い方。根本的な解決方法はない。
ポートに抵抗入れる、AVRの電源ラインにシャント抵抗を入れて電圧を下げるなどの対症療法はある。
しかし残留電圧でヒューズがリセットされないためデバッグワイヤが解除できない等の不具合が発生するので、その辺を理解して使うこと。 >>591
AVRに限らず禁止事項だよ。うっかりするとチップ内の保護ダイオードを壊したり、
外部にレギュレータがあると、こいつを破壊する。
とりあえずの対策としてはFT232XのRESET#をLowにしておけばOK
ATmegaの余っているポートをPull Downしておいて、ここにRESET#をつないでおく。
ATmegaの電源On時に、このポートをHiにしてRESET#を解除すれば普通に使えるし、
電源を落とせばFT232XはResetステートに入る。
FT232XはReset#がLoになっている間、UARTポーtははTri-state、入力は内部200kΩで
プルアップされる(データシートVer. 1.2だったらp. 23)
これで、ほとんどの場合問題はないが、Resetステートの時にUARTピンが浮くので、
気になる場合は弱く(高抵抗で)プルダウンしておけばよい。 >>591
根本的にはAVRの入力に74VHC04のような入力保護ダイオードが入っていない
バッファを入れる。インバータなので2段入れる。 ↑が正解
不都合だけじゃなく、流しすぎるとデバイスがお釈迦になるよ
オレは↓を使ってる
http://akizukidenshi.com/catalog/g/gI-09418/ 小信号ダイオードはさんでオープンドレインもどき接続にして
USBシリアルからのHレベルを遮断すればとりあえず大丈夫なんじゃね >>592
>>593
AVR書き込むたびにUSBケーブルも抜き差しするの面倒くさくてさぼってたけど
やっぱこういう使い方禁則事項だよね^^;)
> FT232XはReset#がLoになっている間、UARTポーtははTri-state、入力は内部200kΩでプルアップされる
FT232XのRESET#ピンを制御するのはいい方法かも
ただ細かいことを言うとまっさらな状態のAVRに書き込もうとしたときは
RESET#ピンの制御は無理になるかな。
初回限定のほんとどうでもいい細かいことだけど。
>>595
> 74VHC04のような入力保護ダイオードが入っていないバッファを入れる
あ、この方法もいいね。ものぐさな自分にはぴったりの方法かもしれん。
VHCシリーズを選べば入力に保護ダイオードが入っていないことは
確約されるんだっけ? >>598
VHCシリーズはVCCに関係なく入力電圧の上限が5.5Vまで印加可能だったと思う
簡易電圧変換なんかにも使われるよね >>599
VHC, LVC, LCX, VCXは入力から電源にむけて寄生ダイオードが無いから
電源に電流が流れることが無いのね
https://toragi.cqpub.co.jp/Portals/0/backnumber/2006/06/p171-172.pdf
一つ勉強になった
ありがとう float型の変数を文字列に変換する際の定番の sprintf はメモリを馬鹿食いするから
次点の dtostrf を使ってみたんだけどこれも結構メモリ馬鹿食いするんだよね
もうちょい軽く済ます方法って無いかしらん >>601
float使わずにintで固定小数点数として格納する 誰しもが通る系の道よ…
固定少数にしても表示が遅い、間に合わないってんで
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
ここのオッチャン、リレー式計算機とか作ったり色々とやってるな
しかし電子工作者のこの文体のテンション、ついていけない… ■ このスレッドは過去ログ倉庫に格納されています