TOPへ戻る

20100407 ATtiny2313 シリアル出力の確認【送信割り込み編】

ATtiny2313 の USART を使用して送信割り込みを使用したサンプルプログラムを書いてみました。
といっても、wiki http://www7a.biglobe.ne.jp/~attlee/avr-jp-wiki/wiki.cgi?page=Getting+Started+Notes+-+UART#p12
のリングバッファによる送信サンプルプログラムを最新版コンパイラで通すように変更しました。

確認用回路図


図に書いていませんが、20MHzのセラロックを使用しています。

PCとATtiny2313間の接続ケーブルは、RS-232C クロスケーブルを使用する。

// ATtiny2313 UART 送信割り込みサンプル
// wikiから最新版コンパイラ版へ移植
// http://www7a.biglobe.ne.jp/~attlee/avr-jp-wiki/wiki.cgi?page=Getting+Started+Notes+-+UART#p12
//
// uart.c:85: error: expected declaration or statement at end of input
// →{}の数が間違っている。
//

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdlib.h>

#define rx_bufsize (16)
#define tx_bufsize (16)

#define FOSC 20000000                   // 20MHz
#define BAUD 38400                      // 38400bps
#define MYUBRR FOSC/16/BAUD-1           // UART分周率

typedef struct
{
    char buf[tx_bufsize];  /*送信バッファサイズ*/
    uint8_t buf_in;     /* バッファに文字を押し込むときの位置*/
    uint8_t buf_size;   /*バッファに貯められている文字数 */
} TxBuf_t;

volatile TxBuf_t TxBuf;

const prog_char a[]  = "\nTCNT1 = ";

//SIGNAL(SIG_UART_DATA)
ISR(USART_UDRE_vect)
{
    /* TxBuf.buf_size==0の状態でDATA割り込みを許可すると変なことになります。注意。 */
    uint8_t buf_out;
    buf_out=TxBuf.buf_in-TxBuf.buf_size;
    if (TxBuf.buf_in<TxBuf.buf_size) buf_out += tx_bufsize;
    UDR = TxBuf.buf[buf_out];
    TxBuf.buf_size--;
    if (TxBuf.buf_size==0) UCSRB = UCSRB & ~_BV(UDRIE); /* UDR空き割り込み禁止 */
}

void uart_putchar(char c)
{
    while (TxBuf.buf_size > (tx_bufsize-1)) ;  /* バッファが空くまで待つ */
    cli(); //バッファを書き換える(読み出しも含む)操作は必ず割り込み禁止で!
    TxBuf.buf[TxBuf.buf_in++] = c;
    TxBuf.buf_size++;
    if (TxBuf.buf_in==tx_bufsize) TxBuf.buf_in=0;
    UCSRB = UCSRB | _BV(UDRIE); /* UDR空き割り込みを有効にする。 */
    sei();
}

//void uart_putstr_pgm(char *s)
void uart_putstr_p(const prog_char *pgm_s)
{
    char c;
    c=pgm_read_byte(pgm_s);
    while ((c=pgm_read_byte(pgm_s++)) != 0)
        uart_putchar(c); 
}

void uart_putstr(char *s)
{
    char c;
    for(;;)
    {
        c = *s++;
        if (c==0) break;
        uart_putchar(c);
    }
}

void sio_init(unsigned int baud){
    UBRRH = (unsigned char)(baud>>8);   // ボーレート上位
    UBRRL = (unsigned char)baud;        // ボーレート下位
    UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE); // 送受信許可
    UCSRC = (1<<USBS)|(3<<UCSZ0);
}

int main(void)
{
    char buf[8];
    sio_init(MYUBRR);                   // USART設定
    TCCR1B = 1;      /* TCNT1を動かす */
    TxBuf.buf_size = 0;    /*バッファを空にする */
    for(;;)
    {
        uart_putstr_p(a);
        itoa(TCNT1,buf,10);
        uart_putstr(buf);
    }
    return 0;
}
ソースファイルのダウンロード