UART経由の予期しないAtmega16応答


8

UART経由の予期しないAtmega16応答

問題の概要

私はコードではATmega16を点滅している必要があります私は端子を介してそれを送るどんなキャラクターはATmega16送信バックにつながります。返事はもらえますが、送ったキャラクターはめったにありません。ボーレートを変更すると正しい出力が表示されますが、正しいボーレートが機能する理由がわかりません。

もっと詳しく

私はかなり楽しんでいるので、自分の時間にファームウェアプログラミングについてもっと学びたいと思っています。これまでに私がuniで行ったファームウェアプログラミングでは、ペリフェラルインターフェースの多くを実行してセットアップするスケルトンコードファイルが提供されましたが、これを自分で学びたいと思います。私がここで何をしているのかについていくつか質問がありますが、最後に項目ごとに説明します。私の知識の誤解や潜在的なギャップを見つけたら、私はあなたが持っているかもしれないどんなインプットにも大いに感謝します。

コード

私のAtmega16にフラッシュしたコードは、このページにある「AVR-GCCでのUSARTの使用」チュートリアルからほぼ一行ずつ取得されています。追加したのは、F_CPUの#defineだけです。元のコードにはF_CPUの#defineがなかったため、コードがAtmelStudio 7でコンパイルされませんでした。作成者が元のファイルでF_CPUを定義しなかった理由を誰かが説明できますか?彼らはAtmel Studio 7以外のツールやコンパイラーを使用していたのではないかと思いますが、確かなことは言えません。

#include <avr/io.h>
#define F_CPU 7372800 //this was chosen because the tutorial states this is the frequency we want to operate at
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((( F_CPU / 16) + ( USART_BAUDRATE / 2)) / ( USART_BAUDRATE )) - 1)

int main ( void )
{
    char ReceivedByte ;
    UCSRB = (1 << RXEN ) | (1 << TXEN ); // Turn on the transmission and reception circuitry
    UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 ); // Use 8- bit character sizes
    UBRRH = ( BAUD_PRESCALE >> 8); // Load upper 8- bits of the baud rate value into the high byte of the UBRR register
    UBRRL = BAUD_PRESCALE ; // Load lower 8- bits of the baud rate value into the low byte of theUBRR register
    for (;;) // Loop forever
    {
        while (( UCSRA & (1 << RXC )) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
        ReceivedByte = UDR ; // Fetch the received byte value into the variable " ByteReceived "
        while (( UCSRA & (1 << UDRE )) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
        UDR = ReceivedByte ; // Echo back the received byte back to the computer
    }
}

ハードウェアのセットアップ

ハードウェア設定の写真

  • MCU:Atmega16;
  • ツールチェーン:Atmel Studio 7、AVR dragonで点滅。
  • 電源:大学提供の開発ボード(コンピュータUSBから取得)から取得した5Vレール。ブレッドボードの電力線のバイパスに使用される100nFセラミックディスクコンデンサ
  • USBからシリアルへのコンバーター:これ。RXD Atmega(ピン15)に接続されたUSBシリアルコンバーターのTXD。AtmegaのRXD(ピン14)に接続されたコンバーターのRXD。
  • 端末ソフトウェア:PuTTY(ボーレート9600)。

    誤った応答の証拠

    繰り返しますが、Atmega は送信されたもの返す必要があります。つまり、OUTPUTはINPUTとまったく同じである必要があります。

    PuTTY出力

    入力出力ff6z>d0スペース0バツ8

    オシロスコープのキャプチャ

    私のPicoscopeとシリアルデコードを使用して、Atmegaが正しい入力を受け取っていることを確認しました。たとえば、 'f'キーを押すと、正しく受信されます。出力はまだ「6」(または場合によってはアンパサンド「&」)です。

Atmega16のRXピンでのスコープキャプチャは、正しい文字がターミナルソフトウェアを介して送信されていることを示します( 'f')

Atmega16のTXピンのスコープキャプチャは、望ましくない応答が返送されていることを示します( '6')

よくわからない修正を見つけました

ボーレートを2500in PuTTYに変更すると、すべてが正しく表示されます。私はこの値をランダムに選択しましたが、なぜ機能するのかわかりません(ボーレートでエラーが発生したと思われますが、チュートリアルをほぼ正確にコピーしたため、どこにあるのかわかりません...思想)。

ご質問

  1. 私は何をしましたか/ここで何が起こっていますか?
  2. 元のチュートリアルがF_CPUを#defineしないのはなぜですか?
  3. なぜボーレートを2500に設定すると問題が解決するのですか?(質問1が回答された場合、これは回答されると思います)

2
F_CPUをある値に定義するだけでは、マイクロはその周波数で実行されません。F_CPUは、マイクロを実行するように構成した頻度として定義する必要がありますが、これをどこかに構成したという証拠はありません...
brhans

よく書かれた質問。それを改善する唯一のものは回路図でしょう。
ブレアフォンヴィル2018

テーブルに対してのみ+1 。LTEバツ
アーセナル

ブレッドボードに外部クリスタルがないことに気づきました。内部RCクロックを使用していますか?プロセッサーの実行頻度はどのくらいですか?
scotty3785

F_CPUについてのあなたの議論のおかげで、私はいくつかの調査と遊んで、解決策を投稿しました。あなたには自明だと思いますが(今のそうです)、他の人の役に立つかもしれません。
daviegravee

回答:


0

私はそれを理解しました!OPへの応答でのF_CPUに関するコメントのおかげで、私はいくつか調査しました(これは皆さんには明らかかもしれません)。

簡単なソリューションの概要

Atmega16は、システム周波数を変更する方法がわからなかったためだと思った周波数で実行されていませんでした。Atmel Studioでヒューズをチェックインすると、2MHz(これは私が知る限り標準のクロック周波数ではありませんが、それには入りません)で実行されていることがわかり、チュートリアルのように7.3728MHz ではありません

F_CPUはMCU(Atmega16)のクロック周波数を変更しませ。コード例を機能させるために必要だったため、Atmega16の周波数は7.3728MHzに変更されませんでした。それはヒューズによって定義された周波数(この場合は2MHz、これについては以下でさらに詳しく説明します)でまだ実行されていたため、望ましいボーレートの紙の計算は実際に使用されたものとは異なります。

作業コード

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 2000000 //THIS LINE IS **NOT** CHANGING THE FREQUENCY OF THE MCU: CHANGE MCU FREQUENCY IN FUSES
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((( F_CPU / 16) + ( USART_BAUDRATE / 2)) / ( USART_BAUDRATE )) - 1)

int main ( void ){
    char ReceivedByte ;
    UCSRB = (1 << RXEN ) | (1 << TXEN ); // Turn on the transmission and reception circuitry
    UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 ); // Use 8- bit character sizes
    UBRRH = ( BAUD_PRESCALE >> 8); // Load upper 8- bits of the baud rate value into the high byte of the UBRR register
    UBRRL = BAUD_PRESCALE ; // Load lower 8- bits of the baud rate value into the low byte of theUBRR register
    for (;;){ // Loop forever
        while (( UCSRA & (1 << RXC )) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
        ReceivedByte = UDR ; // Fetch the received byte value into the variable " ByteReceived "
        while (( UCSRA & (1 << UDRE )) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
        UDR = ReceivedByte ; // Echo back the received byte back to the computer
    }
}

もっと詳しく

望ましいボーレートとAtmegaが実際に行っていたこと

(チュートリアルからの)望ましいボーレートは9600でした。これは、PuTTYで使用したボーレートです。実際のボーレートは、Atmega16データシートの表60(146ページ)で強調表示されている式を使用して計算できます。

147ページのAtmega16データシートからボーレートとUBRRを計算するための方程式の表

コード例でBAUD_PRESCALEは、計算のUBRRです。およびBAUD_PRESCALEに対して定義された値で47として評価されます。F_CPUUSART_BAUDRATE

ボー=fosc16UBRR+1
ボー=20000001647+1
ボー2604

そして、これが問題の根源でした。Atmega16は2MHzで動作していました。つまり、f_ {osc}の値はチュートリアルの例とは異なり、ボーレートは9,600ではなく2,604でした。

f_oscはMCUの実際のシステム周波数であり、によって決定されないことに注意してくださいF_CPU

つまり、これは私の3番目の質問にも答えます。ボーレートを2,500に変更すると、幸運にも、端末が結果を正しく解釈できるMCUの動作ボーレートに十分近づきました。

MCUの周波数の変更

AtmelStudio 7でMCUの周波数を変更するには、次のようにします。

Tools > Device programming > Fuses > Change SUT_CKSEL (or LOW.SUT_CKSEL in my case) to desired frequency (make sure you have read up on the side effects of this). 

例で使用されている周波数は標準の内部クロック周波数ではないので、2MHzに固執します。

私自身の質問に対する回答の要約

  1. 私は何をしましたか/ここで何が起こっていますか?回答:実際には、チュートリアルのクロック周波数をクロック周波数に変更しなかったため、ターミナルソフトウェア(PuTTY)がMCUと同期しなくなることが予想されるものとは異なるボーレートになりました。
  2. 元のチュートリアルがF_CPUを#defineしないのはなぜですか?回答:まだ完全には定かではありませんが、チュートリアルでは指定されていないmakefileで定義されており、作成者がAtmel StudioのようなIDEを使用していないと思います
  3. なぜボーレートを2500に設定すると問題が解決するのですか?(質問1が回答された場合、これは回答されると思います)回答:幸運にも、Atmega16のボーレートに近い数を推測しました
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.