ATmega328PBを使う (3) PWMでLEDを点ける
初めに
LED調光にPWMを使いますので、テストプログラムで動作確認してみます。
PWMモード
ATMega328PBタイマーの動作モードには、標準(Normal)、位相補正PWM(PWM,PhaseCorrect)、CTC、高速PWM(Fast PWM)モードがあります。
TC0であれば、動作モードやTOP値などの組み合わせで下表のようなモードを選べます。
LED調光用のため高速PWMでTOP値0xFFのMode 3を設定します。
16bitタイマーのTC1などでは9bit,10bitも選択できますが。すべて8bitにしています。
クロックは8MHzの256分周としました。PWMの周期は約8.2msとなります。
PWMの配置
PWM0~3を追加します。ただし他の用途で使うポートとぶつかるので全ては使えません。
今回PWM3に割り当てたTC3のOCAは他のポート(UART)とバッティングするのでOCBだけPWMとして使います。
コンポーネントの設定
TC3/TC4をPWM出力として使う場合は注意が必要です。
TC3/TC4はOutput Compare Modulatorに接続されています。
そのためTC3/TC4を別々のPWM出力として使えません。またModulatorの設定にPD2を使います。
TC3をPWM出力とするにはPD2を出力とし、’1’を設定します。
コード
7本のPWMを同時に変化させるコードです。
PWMの初期設定後、タイマーで明るさを変化させています。
#define NUMBER_OF_PWM (7)
uint16_t PwmTbl[] ={
0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
90, 80, 70, 60, 50, 40, 30, 20, 10
};
int PwmTblSize;
static uint8_t PwmStage[NUMBER_OF_PWM];
static uint16_t PwmTopVal;
void PWM_0AB_init(void)
{
// Enable pin output
PWM_0_enable_output_ch0();
PWM_0_enable_output_ch1();
// Set channel 0 duty cycle value register value to specified value
PWM_0_load_duty_cycle_ch0(0x3f);
PWM_0_load_duty_cycle_ch1(0x3f);
// Set counter register value
PWM_0_load_counter(0);
}
void PWM_1AB_init(void)
{
// Enable pin output
PWM_1_enable_output_ch0();
PWM_1_enable_output_ch1();
// Set channel 0 duty cycle value register value to specified value
PWM_1_load_duty_cycle_ch0(0x3f);
PWM_1_load_duty_cycle_ch1(0x3f);
// Set counter register value
PWM_1_load_counter(0);
}
void PWM_2AB_init(void)
{
// Enable pin output
PWM_2_enable_output_ch0();
PWM_2_enable_output_ch1();
// Set channel 0 duty cycle value register value to specified value
PWM_2_load_duty_cycle_ch0(0x3f);
PWM_2_load_duty_cycle_ch1(0x3f);
// Set counter register value
PWM_2_load_counter(0);
}
void PWM_3AB_init(void)
{
PWM_3_enable();
// Enable pin output
PWM_3_enable_output_ch1();
// Set channel 0 duty cycle value register value to specified value
PWM_3_load_duty_cycle_ch1(0x3f);
// Set counter register value
PWM_3_load_counter(0);
}
void timerIntr(void)
{
static unsigned int count = 0;
uint16_t width[NUMBER_OF_PWM];
count++;
if (count >= 400) {
count = 0;
for (int i = 0;i < NUMBER_OF_PWM; i++) {
PwmStage[i]++;
if (PwmStage[i] >= PwmTblSize) {
PwmStage[i] = 0;
}
width[i] = ((uint16_t)PwmTopVal*(uint16_t)PwmTbl[PwmStage[i]]);
width[i] /= 100;
}
PWM_0_load_duty_cycle_ch0((PWM_0_register_t)width[0]);
PWM_0_load_duty_cycle_ch1((PWM_0_register_t)width[1]);
PWM_1_load_duty_cycle_ch0((PWM_1_register_t)width[2]);
PWM_1_load_duty_cycle_ch1((PWM_1_register_t)width[3]);
PWM_2_load_duty_cycle_ch0((PWM_2_register_t)width[4]);
PWM_2_load_duty_cycle_ch1((PWM_2_register_t)width[5]);
PWM_3_load_duty_cycle_ch1((PWM_3_register_t)width[6]);
}
}
int main(void)
{
/* Initializes MCU, drivers and middleware */
atmel_start_init();
PwmTblSize = sizeof(PwmTbl)/sizeof(uint16_t);
PwmTopVal = 0xff;
PwmStage[0] = 0;
PwmStage[1] = 0;
PwmStage[2] = 0;
PwmStage[3] = 0;
PwmStage[4] = 0;
PwmStage[5] = 0;
PwmStage[6] = 0;
PWM_0AB_init();
PWM_1AB_init();
PWM_2AB_init();
PWM_3AB_init();
/* Replace with your application code */
while (1) {
;
}
}
内容に不備等ありましたら連絡お願いします。
Author And Source
この問題について(ATmega328PBを使う (3) PWMでLEDを点ける), 我々は、より多くの情報をここで見つけました https://qiita.com/toshidln/items/406f60c534b6ecc7c9e6著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .