2011年のNHKロボコンで使われるマスター基盤用のプログラムを作っていきます。(添付ファイルを参照してください)
(注意):version3.1以降は大幅に仕様が変更されたため以前のプログラムとは互換性がありませんのであしからず。
またversion3.1からはps2コントローラーの信号受信プログラム(ps2.c ps2.h)とLCDの表示プログラム(lcd.c lcd.h)が
入っています。
1.使われている関数について。
1.1 void initialize(void)
void initialize(void) は、TWI通信に必要なレジスタの初期化する関数です。
まずTWSRとTWBRの値を変更して、SCL周波数を400kHzに設定します。
そしてTWAMRをセットすることで従装置アドレスの遮蔽を解除します。
1.2 void start(void)
void start(void) は、TWI通信を開始する関数です。
TWSTAとTWENとTWINTをセットにすることで開始条件を送信します。
またloop_until_bit_is_set(TWCR,TWINT)で開始条件が送信されるまで待ちます。
1.3 void send(uint8_t buf)
void send(uint8_t buf)は、1バイトのデータを送信する関数です。
引数をTWDRに代入して、TWINTをクリアすることでTWDRに入っているデータを送信します。
1.4 uint8_t receive(uint8_t ack)
uint8_t receive(uint8_t ack)は、データレジスタから受信したデータを取り出す関数です。
データレジスタの値を返し値にすることでデータを取り出します。
また受信したデータの数が規定数に達したとき、ack=0となりTWEAをクリアすることでNACK応答をします。
1.5 void stop(void)
void stop(void) は、TWI通信を終了する関数です。
TWSTOとTWENとTWINTをセットすることで、終了条件を送信します。
1.6 uint8_t MS_send(uint8_t address,uint8_t *buffer,uint8_t length)
これは、上記の1.1~1.5の関数を組み合わせてスレーブのアドレス(uint8_t address)に
必要な数(uint8_t length)のデータを送信する関数です。
ただし*bufferは配列の先頭のアドレスにそれまでに送信したデータの数分を足したアドレスになります。
1.7 uint8_t MS_receive(uint8_t address,uint8_t *buffer,uint8_t length) これは、上記の1.1~1.5の関数を組み合わせてスレーブのアドレス(uint8_t address)から
必要な数(uint8_t length)のデータを受信する関数です。
ただし*bufferは配列の先頭のアドレスにそれまでに受信したデータの数分を足したアドレスになります。
1.8 void Error(void)
void Error(void)はエラーチェック用の関数ですが未実装です。 2.プログラムの作成
上記の関数を利用することで、
基本的なプログラムを作ることができます。
例)基礎的な送信(受信)プログラム
//////////////////////////////////////////////////////////
include <avr/io.h>
void initialize(void);
void start(void);
void stop(void);
void Error(void);
void send(uint8_t buf);
uint8_t receive(uint8_t ack);
uint8_t MS_send(uint8_t address,uint8_t *buffer,uint8_t length);
uint8_t MS_receive(uint8_t address,uint8_t *buffer,uint8_t length); address = 0x02;
data[3] = {0x01,0x02,0x03};
initialize();
int main (void)
{
while(1)
{
send(address,data,3); //受信する際は、send(address,data,3)をreceive(address,data,3)に変更すればよい。
return 0;
}
}
void initialize(void)
{
TWBR = 0x02; TWSR = 0x00;
TWAMR = 0x00;
} void start(void)
{
TWCR |= _BV(TWINT)| _BV(TWEN)| _BV(TWSTA); loop_until_bit_is_set(TWCR,TWINT); return; } void send(uint8_t buf)
{
TWDR = buf; TWCR |= _BV(TWINT) | _BV(TWEN); loop_until_bit_is_set(TWCR,TWINT); return; } uint8_t receive(uint8_t ack)
{ if(ack)TWCR = _BV(TWINT)|_BV(TWEN)|_BV(TWEA); else TWCR = _BV(TWINT)|_BV(TWEN); loop_until_bit_is_set(TWCR,TWINT); return TWDR; } void stop(void)
{ TWCR = _BV(TWSTO) | _BV(TWINT) | _BV(TWEN); return; } uint8_t MS_send(uint8_t address,uint8_t *buffer,uint8_t length)
{ uint8_t i; start(); send(address & 0xFE); for(i = 0;i < length;i++)send(buffer[i]); stop(); return 0; } uint8_t MS_receive(uint8_t address,uint8_t *buffer,uint8_t length)
{ uint8_t i; start(); send((address & 0xFE)+1); for(i = 0;i < (length-1);i++)buffer[i] = receive(length-i); stop(); return 0; } void Error(void)
{
while(1);PORTD = 0b11110000; return; } //////////////////////////////////////////////////////////////////////
またより複雑なプログラムを組む場合は、main文の中を変えることで作ることができます。 3.今後の方針
つぎはエラーチェック関数を付け加えるつもりです。
3.1 エラーチェック関数
TWSRの前置分周器ビットにマスクをかけ、状態コードを判定することでエラーチェックを行うことができます。
//例
uint8_t error_flag;
switch( TWSR & 0xF8 )
{
case 0x18:
error_flag=1;
case 0x20:
error_flag=2;
case 0x30:
error_flag=3;
}
………………………………
↓TWIの状態コードと TWIの状態
更新日2010.12.11 |