USART / レジスタを少しいじってみる / ボーレートを変えてみる

UBRR0H、UBRR0Lの両レジスタでボーレートを変えてみる。
f:id:ti-nspire:20190413091238p:plain:w600

  • これが4800ボーのとき。1ビットの幅は約0.2 msec (≒ 1 sec/4800)。
    f:id:ti-nspire:20190413084856p:plain

  • これが38.4kボーのとき。1ビットの幅は約26 μsec (≒ 1 sec/38400)。
    f:id:ti-nspire:20190413085255p:plain

#include <avr/io.h>

/*
extern "C" {
    #include "USART.h"
}
*/

// 1バイトの各ビットを任意の順番に並べ換えるための函数。
uint8_t byte2pos(uint8_t oneByte, const uint8_t *pos){
    uint8_t mask = 0b10000000;
    uint8_t sorted = 0;
    for(int i=0; i<8; i++){
        if(oneByte & mask){
            sorted |= (1 << pos[i]);
        }
        mask >>= 1;
    }
    return sorted;
}

int main(){
    // 配線のし易さを優先して各ビットをこの順番に並べ換える。
    // bit[7]をPB0から、bit[6]をPB7から、...、bit[0]をPB5からそれぞれ出力する。
    const uint8_t POS[] = {PB0,PB7,PB6,PB1,PB2,PB3,PB4,PB5};

    DDRB = 0xff;    // ポートBのIOを全部OUTにする。
    uint8_t rxData; // 受信したデータを格納するための変数。

    // ボーレートを設定する。12ビット値で指定する。
    //uint16_t BRate = 103; // 4800 baud
    uint16_t BRate = 51; // 9600 baud
    //uint16_t BRate = 34; // 14.4k baud
    //uint16_t BRate = 25; // 19.2k baud
    //uint16_t BRate = 12; // 38.4k baud
    //uint16_t BRate = 8; // 57.6k baud
    //uint16_t BRate = 1; // 230.4k baud
    UBRR0H = BRate >> 8; // 上位4ビット(0b0000????)
    UBRR0L = BRate & 0xff; // 下位8ビット

    // 倍速モードの設定
    //UCSR0A &= ~(1 << U2X0); // 通常モード(これがデフォルトなので設定しなくてもよい)
    //UCSR0A |= (1 << U2X0); // 倍速モード


    // USARTを有効化する。これで端子2、3はGPIOとしては使えなくなる。
    UCSR0B = (1 << RXEN0) | (1 << TXEN0);

    // 1フレームのデータビット数を設定する。
    //UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8ビット(これがデフォルトなので設定しなくてもよい)

    while(1){
        // 受信したらポートBに出力する。
        loop_until_bit_is_set(UCSR0A, RXC0);  // UCSR0AレジスタのRXC0ビットが1になるのを(受信が完了するのを)待ってから、
        rxData = UDR0;
        PORTB = byte2pos(rxData, POS); // ポートBに出力する。
        
        // 送受バッファー(UDR0)に何かを書き込んでシリアルから送信する。
        loop_until_bit_is_set(UCSR0A, UDRE0); // UCSR0AレジスタのUDRE0ビットが1になるのを(送信バッファーが空になるのを)待ってから、
        UDR0 = rxData; // 送信バッファーに書き込む。すると送信される。
    }
    return 0;
}