AVR マイクロ コントローラ用の同じC コードは他のどんな型でも動きますか?

私はマイクロコントローラについて学んでいて、この問題に関する知識は非常に限られています。

私は、レジスタにビットを設定し、基本的にuCを動作させるためにそれらを操作する必要があることを知っています。レジスタはマイクロコントローラ内の電子機器をセットアップし制御する。

私がAtmel Studioで特定の8 ビット uC用にC コードを書いたとしよう。このuCのデータシートには、例えばTCNT0のようなレジスタ名があります。同じコードを他の8ビットAVRで使用したい場合はどうすればいいですか?私はすべてを最初から書くべきですかそれとも少し修正を加える必要があるだけですか?ほとんどのレジスタ名は共通ですか?

例えば、CでATmega328Pをプログラミングする場合、例えばATmega168で同じコードが他の8 ビット型でも動くでしょうか?もしそうでなければ、あなたは通常それを最初から書くのでしょうか、それとも前のものを修正するのでしょうか?

コードの互換性について混乱しています。 AVR32のような32ビットのuCに8ビットのuCのコードを使用するのと同じ質問はどうですか。

2
問題は、コードやライブラリの何パーセントかがチップ内の特定の周辺機器やアドレスとベアメタル通信していることです。同じファミリ内の1つのチップから完全に異なるチップファミリまたは企業まで、設計が同一で同じアドレスを持つ同数のペリフェラルを持つと仮定する理由はありません。移植性を高めることを試みるための環境を作ることは可能です(arduino、mbed)が、あなたはまだあなたの上にあるチップが持っていないということ、あるいはそのチップのためのライブラリがないのならノーと言うことはできません。
追加された 著者 Bartosz Radaczyński,
特定のレジスタが呼び出されると、ファミリ全体に移植されないことさえあります。 2つのデータシートを調べなければなりません。
追加された 著者 Bartosz Radaczyński,

6 答え

たとえば、CでATmega328Pをプログラムした場合、ATmega168などの他の8ビットタイプで同じコードが機能するでしょうか。

その場合、答えははいです。 ATmega168Pと328Pの唯一の違いはフラッシュ メモリの量です - あなたのプログラムが168Pに収まる限り(すなわちそれが16 KBより大きくない限り)、それはその部分で同じように動きます。

それ以外の場合は……。周辺機能が同じ名前を持つ状況であっても、AVR系列間で周辺機能と機能には若干の違いがあります。詳細についてはデータシートを注意深く比較してください。

AVR32のような32ビットのuCに8ビットのuCのコードを使用するのと同じ質問はどうですか?

AVR32は、8ビットAVRとはまったく異なる アーキテクチャです。それらは名前以外にはほとんど何も共通点がありません。だからあなたはおそらくあなたのプログラムを書き直す必要があるでしょう。

3
追加された
Cレベルでは、あなたが考えているほどには違いはありませんが、Cレベルでは、本格的なUnixプログラムのコードがそれほど異なるわけではありません。 AVRアーキテクチャ間で大きく異なる点は、命令セット、メモリマップ、ペリフェラルです。しかし、CはまだCです。
追加された 著者 jmknetspeed,

コードはマイクロコントローラ間で移植できるように書くことができます。あなたのアプリケーションが非常に単純であるか、あなたが大きな急いでいるのでなければ、これをするのは良い考えです:)

その目的は、上位レベルの手順(メインプログラムフロー)を下位レベルのハードウェア操作(ピンのオン、レジスタの設定など)から分離することです。

簡単な例として、LEDを制御したい回路を考えます。 LED用にまったく別のモジュールを用意してコードを設定することができます。(AVRでは動作しません。エラーがあればご容赦ください)。

led.c:

// For simplicity, this assumes all LEDs are on Port D.

void ledInit(uint8_t ledPin)
{

    DDRD |= (1 << ledPin);  //Configure the pin as an output
    PORTD &= ~(1 << ledPin);//Set the pin low
}

void ledOn(uint8_t ledPin)
{
    PORTD |= (1 << ledPin);
}

void ledOff(uint8_t ledPin)
{
    PORTD &= ~(1 << ledPin);
}

そして、メインラインのコードでは、これらのコマンドでLEDにアクセスするのは だけです。トグルコマンドのようにもっとアクセスが必要な場合は、それをled.cファイルに追加します。メインコードは、LEDモジュールの内部で何が起きているのかを認識していません。

これにより、メインラインのコードをマイクロコントローラ間で簡単に移動できます。基本的には、led.cファイルを書き換えるだけで済みます。メインラインのコードをまったく変更する必要はありません

このロジックは、タイマー、通信ポート(SPI、I2C、USARTなど)などにも使用できます。


大規模プロジェクトでは、実際には3層のコードを使用するのが最善です。

  • すべてを統括するメインラインコード
  • 中間レベル。メインラインコードに機能と名前(#defines)を提供します。これは、メインラインコードの意図と、物事を実現するために必要な低レベルの機能との間の変換になります。
  • 低レベル(ドライバ)。実際には正しいビットが反転します。

この場合、低レベル関数は中レベルブロックからしか見えません。中間レベルのブロックは、メインラインコードに公開されています。

これは過度に複雑に思えるかもしれませんが、実際にはそれ以上の作業はかかりません。より大きな実装の詳細を変更しなければならない場合は、利点があります。

たとえば、SPIペリフェラルを使用するようにプログラムを設計したが、実際には新しい設計ではI2Cを使用する必要があるとします。低レベルのSPIコマンドの代わりに低レベルのI2Cコマンドを正しく呼び出すように、ミッドレベルコードブ​​ロックを変更することができます。高レベルの低レベルのコードを変更する必要はありません。

それが言われている、あなたがまだ基本を学んでいる間、私はこれを推薦しないでしょう:)

3
追加された

簡単に言うと、いいえ、1つのマイクロコントローラ用に書かれたCコードが他のマイクロコントローラで実行されることは保証されません。

長い答えですが、あなたのコンパイラはそのようなことを大部分の世話をするかもしれません、そして多くの内部の詳細の世話をするライブラリも書くことができます。

例えば、私はCCSのPIC Cコンパイラを使ってPICファミリのマイクロコントローラを扱う傾向があります。単純なマイクロコントローラ用に書かれたコードは、異なるhファイルを含めるだけで、通常は複雑なコントローラ上で実行されます。存在しないペリフェラルを実行しようとすると、コンパイラがエラーを出します(複雑なコントローラから単純なコントローラに移行するのを妨げる)

これについては何の魔法もありません。誰かが時間をかけて、関連するすべてのメモリ位置についてdefを書き、これらのdefを呼び出して適切なアクションをとるための関数を書きます。

STM32コアコントローラには、CMSISライブラリがあります。理論上 は、もしあなたのチップメーカーがCMSISライブラリを提供すれば、あなたのコードはSTM32コアファミリの他のメンバーに、たとえ他のメンバーからでも移植可能ですメーカー。

2
追加された

コードは動作するかもしれません、それはあなたのコンパイラに依存します、そしてあなたのコードで使用される周辺機器、すなわちタイマーとカウンタが同じレジスタを持っているかどうか。

1
追加された

同じコードを別の8ビットAVRで使用したい場合はどうすればよいですか。

コードの性質に依存します。

ハードウェア依存のコードは明らかに異なるハードウェアを持つMCU上では動作しません。 2つのmcusが同じハードウェア(たとえばTIMER0)を持っている限り、コードは変更されずに実行されます。

コンパイラがサポートしている限り、ハードウェアに依存しないコードは明らかにどのMCUでも実行できます。

1
追加された

あなたが同じAVRファミリーで働いているならば、登録簿の名前は全く同じであるために使います。一部のレジスタが表示されることがありますが、機能が同じでない場合は消えます。 しかし、あなたが他の英国の製造業者を買うならば、レジスターの名前は全く異なるでしょう。 (マイクロチップからTIなどに行く場合)

ほとんどのuCはCプログラミングを使用しているので、古いコードから始めることができます。アルゴリズム部分は変更されない可能性があります。意図したとおりにuCを動作させるには、登録を調整する必要があります。

0
追加された