目次
前
次
シリアルインタフェース拡張
現在、MCR-VC用システムは、以下の5個のマイコンで
動作する仕様です。
- R8C/Tiny(main computer)
- ADcU7026(SubBrain computer)
- ATtiny2313(Leg handling)
- ATtiny2313(Bar Code Scanner handling)
- ATmega328(Game Boy Camera handling)
これだけのマイコンがあると、階層構造を導入して
交通整理しないと、システム全体としての統制が
取れなくなります。
SubBrainマイコンである、ADcU7026にはシリアル
ポートが1チャネルだけです。
1チャネルのシリアルポートを利用して、3つの
マイコンの制御をできるかを検討しました。
次のようにテスト環境を作成し、動作させました。
ホストである、Windowsマシンからは1チャネルの
シリアルポートが見えています。
中間に置いたボードで、次の回路を組みます。
この回路では、ホストが送信したコマンドは
2つのマイコンが同時に受取ります。
マイコンのうち、一方だけが返信できます。
これで、SubBrain computer(ADcU7026)から
Leg handling(ATtiny2313)、BCS handling(ATtiny2313)、
GBC handling(ATmega328)の3つのマイコンに、コマンド
を与えられます。
BCS handling(ATtiny2313)、GBC handling(ATmega328)から
はセンサーデータが返送されるので、パラレル受信します。
この方式を採用すると、ADcU7026に必要な信号線は
次の18本になります。(電源は、除く。)
- シリアル 2本
- BCSデータ 8本
- GBCデータ 8本
この方式の採用で、SubBrainもホストであるPC
からは、同じバスに接続されたマイコンに見え
ます。
動作テストには、TeraTermを利用しました。
テスト用シリアルボードは、次のような簡単なものです。
Leg handlingのファームウエアは、以下に変更します。
#include <avr/io.h>
#include <avr/iotn2313.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#define FOSC 4000000
#define BAUD 9600
#define MYUBRR (FOSC/16/BAUD)-1
#define OFF 0
#define ON OFF+1
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
typedef signed char SBYTE ;
typedef signed short SWORD ;
typedef union {
struct {
unsigned char B0:1;
unsigned char B1:1;
unsigned char B2:1;
unsigned char B3:1;
unsigned char B4:1;
unsigned char B5:1;
unsigned char B6:1;
unsigned char B7:1;
} BIT ;
unsigned char DR ;
} FLAGSP ;
volatile FLAGSP x_flags ;
#define UFLAG x_flags.BIT.B0
#define TFLAG x_flags.BIT.B1
volatile UBYTE sbuf[8] ;
volatile UBYTE sindex ;
volatile UBYTE lduty ;
volatile UBYTE rduty ;
volatile UWORD lcount ;
volatile UWORD rcount ;
char msg[10] ;
volatile UWORD right_velocity ;
volatile UWORD left_velocity ;
#define NO 0
#define YES NO+1
#define MASKFF 0xff
#define MASK0F 0x0f
#define MASKF0 0xf0
#define INTERVAL 49999
const prog_char msg_h[] PROGMEM = "H help" ;
const prog_char msg_d[] PROGMEM = "D set" ;
/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void user_initialize(void);
void usart_putchar(UBYTE x);
void crlf(void);
void usart_puts(UBYTE *x);
UBYTE get_hex(UBYTE x);
void get_velocity(void);
void pid(void);
void show_help(void);
/*------*/
/* main */
/*------*/
int main(void)
{
UWORD xtmp ;
UBYTE cmd ;
UBYTE tmp ;
/* initialize port and variables */
user_initialize();
/* enable interrupt */
sei();
/* endless loop */
while ( ON ) {
/* usart receive handling */
if ( UFLAG ) {
UFLAG = OFF ;
/* get command */
cmd = *(sbuf+0) ;
/* update duty ratio */
if ( cmd == 'D' ) {
/* left duty */
tmp = get_hex( *(sbuf+1) ) ;
tmp = tmp * 10 + get_hex( *(sbuf+2) ) ;
xtmp = (tmp << 6) / 25 ;
lduty = xtmp & MASKFF ;
/* right duty */
tmp = get_hex( *(sbuf+3) ) ;
tmp = tmp * 10 + get_hex( *(sbuf+4) ) ;
xtmp = (tmp << 6) / 25 ;
rduty = xtmp & MASKFF ;
/* store duty ratio */
OCR0A = rduty ;
OCR0B = lduty ;
}
/* help */
if ( cmd == 'H' ) { show_help() ; }
/* new line */
crlf();
}
/* 100ms handling */
if ( TFLAG ) {
TFLAG = OFF ;
pid();
}
}
/* dummy */
return 0 ;
}
#/*-----------------------*/
/* Insert user functions */
/*-----------------------*/
void user_initialize(void)
{
UWORD tmp ;
/* PORT B */
PORTB = 0b00000000 ; /* 00000000 */
DDRB = 0b11111111 ; /* oooooooo */
/* PORT D */
PORTD = 0b00001100 ; /* 00001100 */
DDRD = 0b11110010 ; /* ooooiioi */
/* initialize flags */
x_flags.DR = 0 ;
/* initialize timer/counter0 */
{
TCCR0A = (1 << COM0B1) | (1 << COM0A1) | (3 << WGM00);
TCCR0B = (7 << CS00) ;
TCNT0 = 0 ;
OCR0A = 128 ;
OCR0B = 128 ;
}
/* initialize timer/counter1 */
{
/* compare match (1/8) -> 500kHz */
TCCR1B = (1 << WGM12) | (1 << CS10) ;
TCNT1 = 0 ;
OCR1A = INTERVAL ;
OCR1B = 60000 ;
}
/* initialize serial */
{
sindex = 0 ;
/* set Baud Rate Registers */
tmp = MYUBRR ;
UBRRH = (UBYTE)(tmp >> 8) ;
UBRRL = (UBYTE)(tmp & MASKFF) ;
/* Enable receive interrupt , receive module and transmit module */
UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE) ;
/* 8 bits , 1 stop , non parity */
UCSRC = (3 << UCSZ0);
}
/* set INT0 and INT1 */
MCUCR = (1 << ISC11) | (1 << ISC01) ;
/* set TIMER1 interrupt */
TIMSK = (1 << OCIE1A) ;
/* enable interrupt (global) */
GIMSK = (1 << INT1) | (1 << INT0) ;
/* set duty ratio */
lduty = 0 ;
rduty = 0 ;
/* initialize velocity */
right_velocity = 0 ;
left_velocity = 0 ;
}
void usart_putchar(UBYTE x)
{
while ( !(UCSRA & (1 << UDRE)) ) ;
UDR = x ;
}
void crlf(void)
{
usart_putchar('\r');
usart_putchar('\n');
}
void usart_puts(UBYTE *x)
{
/* send charactor one by one */
while ( *x != '\0' ) {
usart_putchar( *x ) ;
/* pointer increment */
x++ ;
}
crlf();
}
UBYTE get_hex(UBYTE x)
{
UBYTE result ;
/* default */
result = 0 ;
/* judge */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
return result ;
}
/* EXTERNAL INT0 */
ISR(INT0_vect)
{
rcount++ ;
}
/* EXTERNAL INT1 */
ISR(INT1_vect)
{
lcount++ ;
}
/* timer1 interrupt */
ISR(TIMER1_COMPA_vect)
{
TFLAG = ON ;
}
/* UART receive interrupt */
ISR(USART_RX_vect)
{
volatile UBYTE ch ;
/* get 1 charactoer */
ch = UDR ;
/* store */
*(sbuf+sindex) = ch ;
sindex++ ;
/* judge */
if ( ch == '\r' ) {
UFLAG = ON ;
sindex = 0 ;
}
}
void get_velocity(void)
{
/* disable external interrupt */
GIMSK = 0 ;
/* get counter */
right_velocity = rcount ;
left_velocity = lcount ;
/* clear counter */
lcount = 0 ;
rcount = 0 ;
/* enable external interrupt */
GIMSK = (1 << INT1) | (1 << INT0) ;
}
void pid(void)
{
UWORD cr ;
UWORD cl ;
UBYTE dd ;
/* judge */
if ( rduty != lduty ) return ;
/* get velocity */
get_velocity();
cr = right_velocity ;
cl = left_velocity ;
/* adjust */
dd = OCR0B ;
/* increment */
if ( cr > cl ) { dd += (cr - cl) / 10 ; }
/* decrement */
if ( cr < cl ) { dd -= (cl - cr) / 10 ; }
/* update */
OCR0B = dd ;
}
void show_help(void)
{
strcpy_P(msg,msg_h) ; usart_puts((UBYTE *)msg);
strcpy_P(msg,msg_d) ; usart_puts((UBYTE *)msg);
}
コマンドは、'D'としておき、続ける4パラメータに
左、右のDUTY比を10進2けたとします。
目次
前
次