Arduno UNOでPWMを使う

PWMの設定

TCCR1A = _BV(COM1A1)|_BV(WGM11); //Compare match A enable,Fast PWM (ICR1 as TOP)
TCCR1B = _BV(WGM13)|_BV(WGM12)|_BV(CS10); //Fast PWM (ICR1 as TOP),Clock Source enable

前書いたコードと同じだけど、再掲。

//#define F_CPU 1000000UL
#include <avr/io.h>
//#include <util/delay.h>
#include <stdio.h>

void rs_putc (char c)
{
	loop_until_bit_is_set(UCSR0A, UDRE0); 
	UDR0 = c;
}
void rs_puts (char *st)
{
	while (*st) {
		rs_putc (*st);
		if (*(st++) == '\n') rs_putc('\r');
	}
}

int main(void)
{
	UCSR0B = _BV(TXEN0)|_BV(RXEN0); /* TX/RX interrupt enable */
	UCSR0C = 0b00000110;//8bit
	UBRR0H = 0x00;
	UBRR0L = 0x19;
	
	  TCCR1A = 0b10000010;  //10:コンペアマッチAでLOW,10:高速PWM動作
	  TCCR1B = 0b00011001;  //11:高速PWM動作, 001:分周なし
	  ICR1 = 64999; 		  //0から数える. 全体時間 65ms
	  //0.000001 * 65000 : 65ms
	  OCR1A = 0; 		  //0から数える. High時間 32.5ms
	  //0.000001 * 32500 : 32.5ms
	  //OCR1AはPD5ピン	  
	  DDRB |= (1 << PORTB1);
	while(1){
		int i;
		unsigned int val;
		char buf[7];
		unsigned int iter = 15;		
		unsigned long j;
		for(i=0;i<iter;i++){
			j = 0;
			while(j<100000){
  			  val = (64999/iter)*i;
		 	  OCR1A = val;
			  j++;
			};
			//sprintf(buf,"%u\n",val);
			//rs_puts(buf);
		}
		for(i=iter;i>0;i--){
			j = 0;
			while(j<100000){
				val = (64999/iter)*i;
				OCR1A = val;
				j++;
			};
			//sprintf(buf,"%u\n",val);
			//rs_puts(buf);
		}
		//char msg[] = "Hello\n";
		//rs_puts(msg);
		//_delay_ms(2000);
	}
}


_delay_ms()を使ってもう少し上手く実装してみた。

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>

#define FOSC 16000000UL
#define BAUD 9600
#define MYUBRR ((FOSC/(16UL*BAUD))-1)

void USART_init(unsigned int ubrr){
  UBRR0H = (ubrr>>8);
  UBRR0L = ubrr;
  UCSR0B = _BV(RXEN0)|_BV(TXEN0); //RX-TX enable
  UCSR0C = (3<<UCSZ00);//define data frame: CSZ = CharacterSiZe
}

void USART_Transmit(unsigned char data){
  loop_until_bit_is_set(UCSR0A,UDRE0);
  UDR0 = data;
}

char USART_recv(void)
{
  while(!(UCSR0A & (1<<RXC0)));
  return UDR0;
}

void putString(char msg[])
{
  int i;
  for(i=0;msg[i];i++){
    USART_Transmit(msg[i]);
  }
}

void PB1_PWM_init(){
  DDRB |= _BV(PORTB1);//For PWM output
  TCCR1A = _BV(COM1A1)|_BV(WGM11); //Compare match A enable,Fast PWM (ICR1 as TOP)
  TCCR1B = _BV(WGM13)|_BV(WGM12)|_BV(CS10); //Fast PWM (ICR1 as TOP),Clock Source enable
  ICR1 = 65000;
}

void PB1_dim(){
  int i;
  char buf[20];
  for(i=0;i<10;i++){
    unsigned long j;
    for(j=0;j<1000000;j++){
        //nop;
    }
  OCR1A = 6500 * i;
  //_delay_ms(200);
  }
}

void PWM_test(){
  ICR1 = 65000;
  int i;
  for(i=0;i<10;i++){
  OCR1A = 6500*i;
  _delay_ms(200);
  }
  for(i=10;i>0;i--){
  OCR1A = 6500*i;
  _delay_ms(200);
  }
}

int main(void){
  DDRB |= _BV(PORTB5);//For monitor LED13
  USART_init(MYUBRR); 

  char data;
  putString("Hello\n");
  putString("Hello\n");

  PB1_PWM_init();
  OCR1A = 65000;
  while(1){
      //data = USART_recv();
      //USART_Transmit(data);
      //PB1_dim();
      PWM_test();
  }
  return 0;  
}