制御プログラム
制御用として、AtmelのATtiny85という8ピンのマイコンを使いました。このマイコンには、USI(Universal Serial Interface)というシリアル通信機能が組み込まれていますが、汎用ゆえ使い方が難解です。そこで、がた老AVR研究所の温度ロガーで公開されていたsoft_I2C.cの主要ルーチンをほぼそのまま利用させて頂きました。また、JimCom氏のソースコードも参考にさせて頂いています。この場をお借りしてお礼申し上げます。
メインルーチン Si570.c(一部、#includeに続く括弧を全角に変更しています)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/sleep.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#define I2C_FUNCTIONS
#include ”soft_I2C.h”
/*
PB5 I (Reset)
PB4 I DIP SW 1-1
PB3 I DIP SW 1-2
PB2 I/O SCL/(ISP SCK)
PB1 I/O (ISP MISO)
PB0 I/O SDA/(ISP MOSI)
*/
uint8_t I2C_comd(uint8_t cmd)
{
I2C_start_cond();
if( I2C_status_flag != 1) return(I2C_status_flag);
I2C_Master_send(Si570_ADR);
if( I2C_status_flag != 1) return(I2C_status_flag);
I2C_write(cmd);
if(I2C_status_flag !=1) return(I2C_status_flag);
return(1);
}
void I2C_put(uint8_t cmd, uint8_t data)
{
if( !(I2C_status_flag = I2C_comd(cmd)) ) return;
I2C_write(data);
if(I2C_status_flag != 1) return;
I2C_stop_cond();
}
void init_si570(void)
{
// Freeze DCO
I2C_put(137,0x10);
// Set HSDIV, N1, RFREQ
switch (((bit_is_clear(PINB,4))<<1) | (bit_is_clear(PINB,3))) {
case 0: // 122.880MHz
I2C_put(7, 0x21); // HSDIV=1, N1=7
I2C_put(8, 0xC2); // RFREQ=0x02B021DE77
I2C_put(9, 0xB0);
I2C_put(10, 0x21);
I2C_put(11, 0xDE);
I2C_put(12, 0x77);
break;
case 1: // 73.728MHz
I2C_put(7, 0xE1); // HSDIV=7, N1=5
I2C_put(8, 0x42); // RFREQ=0x02A9404015
I2C_put(9, 0xA9);
I2C_put(10, 0x40);
I2C_put(11, 0x40);
I2C_put(12, 0x15);
break;
case 2: // 61.440MHz
I2C_put(7, 0x23); // HSDIV=1, N1=15
I2C_put(8, 0xC2); // RFREQ=0x02B021DE77
I2C_put(9, 0xB0);
I2C_put(10, 0x21);
I2C_put(11, 0xDE);
I2C_put(12, 0x77);
break;
case 3: // 12.288MHz
I2C_put(7, 0xE8); // HSDIV=7, N1=35
I2C_put(8, 0xC2); // RFREQ=0x02A9404015
I2C_put(9, 0xA9);
I2C_put(10, 0x40);
I2C_put(11, 0x40);
I2C_put(12, 0x15);
break;
default: // 122.880MHz
I2C_put(7, 0x21); // HSDIV=1, N1=7
I2C_put(8, 0xC2); // RFREQ=0x02B021DE77
I2C_put(9, 0xB0);
I2C_put(10, 0x21);
I2C_put(11, 0xDE);
I2C_put(12, 0x77);
}
// UnFreeze DCO
I2C_put(137, 0x00);
// Set New Freq
I2C_put(135, 0x40);
}
int main(void)
{
// 出力ポート初期化
// 入力ポート、1:プルアップ
PORTB = 0b011101;
// ポート設定 0:入力, 1:出力
DDRB = 0b000101;
// USIインタフェースの初期化
I2C_Master_init();
// Si570の設定
init_si570();
while(1); // 無限ループ
}
soft_I2C.c(変更箇所のみ抜粋)
//#include <avr/iotn861.h>
//#define I2C_FUNCTIONS
void I2C_Master_init()
{
// USIPP = I2C_USIPOS;
soft_I2C.h(変更箇所のみ抜粋)
//#define RTC8564_ADR 0xA2 //8564 RTC
#define Si570_ADR 0xAA // Si570 I2C Address: 0x55<<1
#define I2C_PORT PORTB
#define I2C_PIN PINB
#define I2C_DDR DDRB
#define I2C_SDA PB0
#define I2C_SCL PB2
ところで、HSDIVとN1の分周比と、実際にレジスタに書き込む値とは若干異なっています。
HSDIV
3ビットで表現しますが、少し変則的です。
000 = 4
001 = 5
010 = 6
011 = 7
101 = 9
111 = 11
N1
7ビットで表現します。分周比から1を引いた値をセットします。
0000000 = 1
1111111 = 128
たまご様
返信削除jr1pwzです。
LAOさんの掲示板ではお世話になりました。
先ほどMouserからメールが届き、Si570を送ったとのこと。数日中には届くらしいので、来たらいじり倒したいと思います。大変興味深いデバイスなので楽しみです。
昔、このデバイスがちらちらネットに出始めた頃、グループ購入に参加しようとしたのですが、「相手にされず」に悔しい思いをしたことがありましたっけ。
これからもこのブログを参考にさせていただきます。
では
良かったですね!
返信削除このデバイス、コマンドを送り込むだけで任意のクロックが取り出せるので、今までの苦労は何だったのかという気分になります。
私は。高速DDSのクロックに使えないかなぁと、妄想を広げております。