USB-シリアルポートアダプタ (RS-232C) は前に買っていたけど、RS-232C は正負 -12~+12 で1/0を表現うるので、マイコンのロジックレベル(0 or VCC)とは違っていて、そのままではマイコンと接続できない。
調べてみると、RS232トランシーバー (ドライバ) ICというのがあって、それを使えば簡単にレベル変換できることがわかった。有名なのは MAX232 というやつみたいだけど、ほぼ同じインターフェイス(ピンアサイン)でビットレートや電源電圧が違うやつがいろいろとあるみたいだ。
今回は ICL3232CPZ という 3.3V〜5V で動いて、なおかつ外付け部品が 0.1uF 5個だけというのを選んで作った。
繋いで以下のような、ボーレート 19200 で吐き出すコードを書いてみた (チップは ATTiny2313、レジスタ名がチップによって違うので、チップ変えるとそのままでは動かない)
#include <avr/io.h>
#include <string.h>
#include <util/delay.h>
#define clear_bit(v, bit) v &= ~(1 << bit)
#define set_bit(v, bit) v |= (1 << bit)
static inline void uart_putchar(char c) {
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
}
static inline void uart_puts(char* string) {
unsigned int len = strlen(string);
unsigned int i;
for (i = 0; i < len; i++) {
uart_putchar(string[i]);
}
uart_putchar('\r');
uart_putchar('\n');
}
void usart_init(unsigned short baudrate) {
unsigned int d = ((F_CPU + (baudrate * 8L)) / (baudrate * 16L) - 1);
UBRRL = d;
UBRRH = d >> 8;
UCSRB =
(1<<RXCIE) | // RX Complete Interrupt Enable
(1<<TXCIE) | // TX Complete Interrupt Enable
(0<<UDRIE) | // USART Data Register Empty Interrupt Enable
(1<<RXEN) | // Receiver Enable
(1<<TXEN) | // Transmitter Enable
(0<<UCSZ2) | // Character Size
(0<<RXB8) | // Receive Data Bit 8
(0<<TXB8) ; // Transmit Data Bit 8
UCSRC =
(0<<UMSEL) | // USART Mode Select: 0=Asynchronous Operation, 1=Synchronous Operation
(0<<UPM1)|(0<<UPM0) | // Parity Mode
(0<<USBS) | // Stop Bit Select
(1<<UCSZ1)|(1<<UCSZ0) | // Character Size (with UCSRB)
(0<<UCPOL) ; // Clock Polarity
}
static inline void setup_io () {
usart_init(19200);
}
int main(void) {
setup_io();
for (;;) {
uart_puts("Hello, World");
_delay_ms(1000);
}
}
PC 側では、この USB シリアルポートアダプタの場合、/dev/tty.usbserial-FTB3L9UG というようなファイルができるので、これを指定して GNU screen の window を1つ作ってる。変なことしてないのでボーレートを指定するだけでいける。
screen /dev/tty.usbserial-FTB3L9UG 19200
これで RX/TX があるチップならかなりデバッグが捗りそう。