PWM
動的走査の双方向デジタル駆動制御を、各々は、我々は、そのデューティ・サイクルの値にこれを呼び出し、時間の50%のみが明るい有します。ピン高い照明はLED聞かせて、デューティ比が100%です。
ときは、デジタルドライブ、あなたが実際には2つが同時に異なる番号を表示させないことができるので、我々は、50%のデューティサイクルを作ることを余儀なく。しかし、我々はまた、意図的に輝度を減少させるために、100%未満のLEDのデューティサイクルをさせることができます。
デューティ・サイクルは、プログラム内で調整することができます。次の手順では、ユーザがデジタル制御により、キー、およびディスプレイの青色LEDのデューティサイクルを調整することを可能にします。
#include <ee1/ee.h>
#define DUTY_MAX 9
int main()
{
led_init();
button_init(PIN_NULL, PIN_NULL);
segment_init(PIN_NULL, PIN_8);
uint8_t duty = 0;
while (1)
{
if (button_pressed(BUTTON_0) && duty > 0)
--duty;
if (button_pressed(BUTTON_1) && duty < DUTY_MAX)
++duty;
segment_dec(duty);
segment_display(SEGMENT_DIGIT_R);
for (uint8_t i = 0; i != DUTY_MAX; ++i)
{
if (i < duty)
led_set(LED_BLUE, true);
else
led_set(LED_BLUE, false);
delay(1);
}
}
}
duty
範囲の整数である0
と9
、それぞれ、LEDのデューティ比0/9
には9/9
。例えば、デューティ比がある場合4/9
、LED後9秒、最初のLEDライト4ミリ秒、5ミリ秒の周期が照明されません。
、より大きなデューティサイクルを見ることができ、LEDの輝度が高くなっています。元々、明暗間、LEDの中間状態があります。私たちは、0Vと5Vの間のピンの出力電圧を持つことではありませんが、すぐにピンレベルに達成するためにハイとローの間で変動します。
この効果は、パルス幅変調と呼ばれる平らな技術ホッピングアナログ電気速いによって達成PWMと呼ばれます。
タイマー
タイマーほとんどのマイクロコントローラを出力することができるPWM波、周辺機器の豊富なAVRマイクロコントローラも例外ではありません。タイマ0言及最後の講義は、4つの動作モードがあり、後者の二つは、高速PWM位相基準PWMモードです。
高速PWMモードでは、TCNT0
通常のレジスタ・モードの動作ではなく、あってもよいOCR0A
上限。非反転出力の場合、TCNT0
上限に達してクリアされ、出力端子はハイであり、場合TCNT0
とのOCR0A
、またはOCR0B
マッチ、OC0A
およびOC0B
それぞれ、ローレベルを出力し、反転出力のために、前者が高く、低い、です。通常、非反転PWM出力周波数は(F_ {} CPU / 256N \)\(上限の場合255であり; \(N \)の分割係数である)、デューティ比が((をOCR0x + \ 1)/ 256 \) 。デューティサイクルが2の分母256 8乗、8ビットPWM出力解像度であるので。
主に例より厳格な要件の位相補正PWMモータ制御PWM波の形状のために使用され、それはここでは詳細には触れません。タイマ1は、より多くの作業モード、より豊富なタイマクロックシステム2を持っている、あなたは、データシートを詳しく見てとることができます。
倉庫
デューティサイクル式((をOCR0x + 1)/ 256 \)\ にOCR0x
とり得る値を、デューティサイクルが1に到達することができ、LEDは、最大PWMモードに最大輝度0デューティサイクルはそうで、達成することができませんLEDのPWM制御は、すべての暗いではありません。このことは、トラブルのビットは、あなたがいないだけに、暗くするLED PWMをオフにする必要があり、書き込みの値。使用の将来の容易さのために、我々は(それをやってライブラリ全体を)ラップ操作を登録する機能を使用しています。0
255
OCR0x
アトメルStudioで、静的ライブラリと実行可能ファイルは、溶液に並んで存在することができ、プロジェクトに属しています。上記のソフトウェアのPWMプログラムが属するのソリューションでは、メニューバーの[ファイル] - > [新規作成]> [プロジェクト(またはCtrl + Shiftキー+ N)をクリックして、で、「PWM」という名前の「GCC C静的ライブラリプロジェクト」を選択し「ソリューション:」 「ソリューションへの追加」を選択し、「OK」の後にMCUの種類を選択し、静的ライブラリプロジェクトは、デフォルトで、作成されたlibrary.c
ファイル。
「ソリューションエクスプローラ」では、library.c
名前変更oc0a.c
。>追加- >新しい項目やメニューバー- - >プロジェクト- >新しい項目またはCtrl + Shiftキー+ Aを追加し、「ファイルを含める」を選択し、名前の「PWM」プロジェクト、右は選択しoc0a.h
(通常は必要な同じ名前を取ることはなく、 A)。
ライブラリのニーズは2つの機能を提供する。oc0a_init
ためのOC0A
PWM出力としてピン、oc0a_pwm
出力PWMデューティサイクルパラメータを設定する8ビットの符号なし整数です。
// oc0a.h
#ifndef OC0A_H
#define OC0A_H
#include <stdint.h>
/*
* 函数:oc0a_init
* 参数:无
* 返回:void
* 功能:将OC0A引脚配置为PWM输出,占空比为0。
*/
void oc0a_init();
/*
* 函数:oc0a_pwm
* 参数:uint8_t _duty - 占空比的整数表示
* 返回:void
* 功能:将OC0A引脚输出PWM波的占空比设置为(_duty / 256)。
*/
void oc0a_pwm(uint8_t _duty);
#endif
ヘッダファイルにoc0a.h
、我々は2つの機能を定義し、パラメータ、戻り値および機能を含むコメントとして説明を提供します。
その後、oc0a.c
我々はこれらの機能の実装を提供します。
#include "oc0a.h"
#include <avr/io.h>
void oc0a_init()
{
PORTB &= ~(1 << PORTB3); // PB3 low level
DDRB |= 1 << DDB3; // PB3 output mode
TCCR0A = 0b00 << COM0A0 // normal port operation
| 0b11 << WGM00; // fast PWM mode
TCCR0B = 0b0 << WGM02 // fast PWM mode
| 0b010 << CS00; // 8 prescale
}
void oc0a_pwm(uint8_t _duty)
{
#define COMA_MASK (~(0b11 << COM0A0)) // mask for COMnA bits
if (_duty) // fast PWM mode
TCCR0A = (TCCR0A & COMA_MASK) // protect other bits
| 0b10 << COM0A0, // non-inverting mode
OCR0A = _duty - 1; // duty = (OCRnx + 1) / 256
else // turn PWM off
PORTB &= ~(1 << PORTB3); // PB3 low level
TCCR0A = (TCCR0A & COMA_MASK) // protect other bits
| 0b00 << COM0A0; // normal port operation
}
最初の実装ファイルには、一貫性のある関数インタフェースを確保するために、対応するヘッダファイルが含まれている必要があります。
基礎となるレジスタの機能の多くが含まパッケージとして動作。レジスタの動作は、マイクロコントローラのプログラミングに固有の番号が、ビット操作の様々な組み合わせを割り当てるために直接書き込まれていません。例えば、PORTB3
マクロが定義され<avr/io.h>
、値3
の意味PORTB
最初3
のビットは、(最初のための最下位ビット0
の制御ビット)PB3
端子は、1 << PORTB3
このビットをれる生成1
残りのビット0
数を、それを取る~
、これだけが得られ0
、残りのビット1
数の、その結果PORTB
の数と&=
このいずれかの他のビットとなりつつ操作不変に保つことができ0
、なぜなら0
「AND」での結果0
ではなく1
、「および」であることの結果ビット値。別の例はCOM0A0
され6
、2つの塗りつぶし、共感を塗りつぶし、数2 置くオペレータ、同時にこれら2には記入(データシートビューを参照する定義ビット)。0b00 << COM0A0
COM0A1:0
00
0b11 << WGM00
WGM1:0
11
|
TCCR0A
また、さまざまな理由を記述しますためPORTB
、このようなレジスタとして、関数はそれらの1のための唯一の責任がある、と割り当ては他のビットに影響を与えます;用OCR0A
レジスタ等、明示、すべての名前と値を書かれたコードを向上させることができます読みやすさ。
ライブラリはオープンソースである場合は、コメントを表示するには、ユーザーを理解したいために取り組まれました。それはクローズドソースのライブラリ、ヘッダファイルとライブラリファイルの形式で配布された場合、コメントは後で彼の表情に書いている。要するに、コメントの必要性。目的は、(私を含め)読者のコメントである疑いを排除することです。読者が知らない0b010 << CS00
のデータシートに書かれている「8による除算」マークの意味を、;なぜ読者は理解していないOCR0A
割り当てが必要とされ-1
、式のデューティサイクルを含む、入力されて置きます+1
。
ので、また、上記のコードの移植性の欠如のいくつかのことを思い出したする必要が0b
進数の接頭辞は、GCCの拡張機能、標準のC言語の一部ではありません。標準的なバイナリ表現に最も近い16進数であるが、手動で変換する必要があり(内とするときF-AB K-BDと解答用紙を描いたように、との間のマッピングを確立する)、レジスタに割り当てられています執筆の理由を展開します。0b0000
0b1111
0x0
0xF
呼吸光
このライブラリをテストするために、我々は新しいプロジェクトを作成します、この時間はあなたが前に何回もやったと推測した後、「GCC C実行可能なプロジェクト」、プロセスを選択します。違いは、ヘッダファイルを書き込む前に、少し変化が書かれている参考文献であるoc0a.h
に位置して../pwm/
、ディレクトリ../
の親ディレクトリを意味し、「ライブラリ」プロジェクトの「ソリューションエクスプローラ」で、手動での必要性だけでなく、ライブラリを追加するライブラリを追加」を右クリック「ページをチェックし、」PWM「プロジェクトのプロジェクトライブラリ「の」;あなただけ書かれた二つの機能を使用できるように。
我々の結果は、すなわち、LEDからの光が徐々に呼吸のように、調光器その後、暗くなり、呼吸光を達成しました。
#include <ee1/delay.h>
#include "../pwm/oc0a.h"
int main()
{
oc0a_init();
int brightness = 0, fadeAmount = 5;
while (1)
{
oc0a_pwm(brightness);
brightness = brightness + fadeAmount;
if (brightness <= 0 || brightness >= 255)
fadeAmount = -fadeAmount;
delay(30);
}
}
OC0A
ピンは、RGBW開発ボードのいずれかに左に接続されている、とあなたは、対応するLEDが光を呼吸する効果があるでしょう。
RGBW
赤、緑、青と白のRGBWを表します。理論的には、緑および青は、全ての色の組み合わせとすることができる、すなわち、白の添加は、純粋な白色光を提供し、それはまた、LEDの明るさを向上させることができます。
あなたが屋内に上記の手順の結果の下で観測される光の場合は、変数があることを見つけるだろうbrightness
、と呼ばれる明るさが直線的に時間とともに変化するが、視覚的な効果は、全体のプロセスを点灯し、輝度変化の明確速い前半、ほぼ一定の明るさの背後にあります。あなたが輝く懐中電灯で行くし、それを観察する場合と、あなたは後半の明るさの変化を感じることができます。人間の目は、低光条件下の光の変化に敏感ではないので、これはおそらくです。
rgbw_set
関数は、この問題を解決します。これは、直接パラメータに転送されていないpwm_set
が、マップされたパラメータで呼び出され、このマッピング数学の関数として、でx
小さいときy
より遅い成長、大きな急速な成長、人間の目の錯覚を相殺します。
// oc0a.c
#include <ee1/delay.h>
#include <ee1/rgbw.h>
void init();
void breathe();
void flash();
int main()
{
init();
while (1)
breathe(), flash();
}
void init()
{
rgbw_init(PIN_4, PIN_5, PIN_6, PIN_7);
}
void breathe_phase(uint8_t* _status, int8_t* _alter)
{
for (uint8_t step = 0; step != 200; ++step)
{
for (uint8_t which = 0; which != 4; ++which)
rgbw_set(which, _status[which] += _alter[which]);
delay(5);
}
}
void breathe()
{
uint8_t status[4] = {0, 0, 0, 0};
int8_t pre[4] = {1, 0, 0, 0};
int8_t loop[][4] =
{
{-1, 1, 0, 0},
{0, -1, 1, 0},
{1, 0, -1, 0},
};
int8_t post[4] = {-1, 0, 0, 0};
breathe_phase(status, pre);
for (uint8_t cnt = 2; cnt--;)
for (uint8_t pha = 0; pha != sizeof(loop) / sizeof(*loop); ++pha)
breathe_phase(status, loop[pha]);
breathe_phase(status, post);
}
void flash_phase(bool* _pattern)
{
for (uint8_t which = 0; which != 4; ++which)
rgbw_set(which, _pattern[which] ? 200 : 0);
delay(500);
}
void flash()
{
bool extra[4] = {0, 0, 0, 0};
bool loop[][4] =
{
{1, 0, 0, 0},
{1, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 1, 0},
{1, 0, 1, 0},
};
flash_phase(extra);
for (uint8_t cnt = 2; cnt--;)
for (uint8_t pha = 0; pha != sizeof(loop) / sizeof(*loop); ++pha)
flash_phase(loop[pha]);
flash_phase(extra);
}
このコードは変更して拡張することは容易であるランプモードは数字ではなく、ハードコードのプログラムに定数パラメータ関数の呼び出しによって表される変更します。
仕事
実現データシート、
OC1A
位相および周波数補正波PWMピンと12ビット分解能の出力、。0と1つの注デューティ・サイクル。光は、それをプレイ!