簡易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_となっているが、AT90S2313やATtiny2313でも実行可能。
コード
/*
* 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)
{
}
}