簡易AVR-DDS 1KHz発振器

提供: 泣かないでゆり子
移動先: 案内検索

手元に古いAVRマイコンAT90S2313が転がってて、しかもPLLの基準信号用に1KHzが欲しかったので、AVR-DDSを作ってみた♪

基準信号作るのに74HC192とかを何石も使って分周すると、基板面積を食うので1石で1KHzの信号作れるのはイイ。

なお、さらに実装面積をケチれるように、8pinのATtiny13Aでも1KHz発振できるようにした。条件コンパイルを使ってどちらのCPUでも、同じコードで動作するようにした♪

ただしATtiny13Aは外部水晶振動子が使えず、内蔵CR発振器による動作になるので、あまり周波数精度を高くできない・・・

C言語コード

main()関数内のfreq変数を変更すれば任意の周波数で発振可能。

クロックは8MHz水晶 or 9.6MHz内蔵発振器としているが、異なる周波数を使用する場合はF_CPUを違う値に変えればおk。

なお、define定義は_AVR_ATtiny2313A_H_となっているが、AT90S2313ATtiny2313でも実行可能。

コード

/*
 * ATtiny2313-DDS.c
 *
 * Created: 2016/04/08 12:50:12
 *  Author: 市川ゆり子
 */ 

#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/fuse.h>
#include <avr/signature.h>
//#include <io2313.h>

//Define clkCPU
#ifdef _AVR_ATtiny2313A_H_
#define F_CPU 8000000UL	//tiny2313 Ext.XTAL 8MHz
//#define F_CPU 8000000UL	//90S2313 Ext.XTAL 8MHz
#elif _AVR_ATTINY13A_H_
#define F_CPU 9600000UL	//tiny13 Internal OSC 9.6MHz
#endif

#ifdef _AVR_ATTINY13A_H_
FUSES = {
	.low = (FUSE_SPIEN & FUSE_SUT0 & FUSE_CKSEL0),	//SPIEN, InterOSC 9.6MHz 14CK 64ms
	.high = FUSE_BODLEVEL0	//BODLEVEL 1.8V
};
#elif _AVR_ATtiny2313A_H_
//stub
#endif

volatile uint16_t freq;

//Calling interval 31.25KHz (8MHz/256)
#ifdef _AVR_ATtiny2313A_H_
ISR(TIMER0_OVF_vect){
#elif _AVR_ATTINY13A_H_
ISR(TIM0_OVF_vect){
#endif
	static uint32_t p;
	
	if (p < F_CPU/512)
	{
		PORTB |= _BV(PINB0);
	} 
	else
	{
		PORTB &= ~_BV(PINB0);
	}
	p+=freq;
	if (p > F_CPU/256)
	{
		p = 0;
	}
}

int main(void)
{
	//All Ports set OUTPUT
#ifdef _AVR_ATtiny2313A_H_
	DDRD = 0b01111111;
#endif
	DDRB = 0b11111111;
	
	TCCR0B = _BV(CS00);//Timer Clock Source: clkI/O
	//Enable Interrupt Timer0 Overflow
#ifdef _AVR_ATtiny2313A_H_
	TIMSK = _BV(TOIE0);
#elif _AVR_ATTINY13A_H_
	TIMSK0 = _BV(TOIE0);
#endif
	
	freq = 1000;
	sei();
	
    while(1)
    {
    }
}