本チュートリアルではスマホやタブレットへのデータ送信方法を示すプログラムについて説明する。

フローコントロール

C-09でブルートゥース・ローエナジー(BLE)を紹介したが、REOボードのモジュールが適切に機能するにはフローコントロールが必要である。

モジュール

REOボードのブルートゥースは現在20バイトのメッセージが送信可能なので、当プログラムは20バイトの文字列を繰り返し送信する。REOボードのBLE(BlueGigaBLE112) はビットレートの制限がある。ビデオやオーディオを転送するには不適切である。ブルートゥース・ローエナジーは省電力用に作製されたため、ビットレートは低くなっている。短いコマンドや低頻度の測定(例:数百バイト/秒)に最適である。

プログラム

当プログラムはC-09のソースコードを再使用するが、インクリメント番号を表示するメッセージを実現する。0x01を送信するとインクリメントはデクリメントに切り替えられ、0x02を送信するとインクリメントに戻る。0x00でカウンターはリセットされる。

タイマー割込及びUART受信割込が1つずつある。

割込み付きタイマー設定及びUART設定については前チュートリアルで説明済みである。割込みルーチンが2つあるので、_DINT() 及び _EINT(); を使用し、一方が割込中には他方が延期される。

結果

インクリメント数字列は、iOS BLExplrやそれに相当するもので表示される。コマンド送信については、ブルートゥースチュートリアル(C-09)と同様に行われる。

下のオシロスコープ画面はフローコントロールで生じる状態を示している。青線は、モジュールがバイト送信を許可した時を示している。下図では、常に許可されている状態を示している(許可=0、禁止=1)。

Flow1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

次の画面コピーは、モジュールにより送信が禁止されている時を示している。通常は1.7ms位でメッセージ送信が完了するがCTSが送信禁止の場合2ms位に延長される。

Flow2

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ソースコード

--------------------

#include <msp430F5659.h>
#include "F5659Utils.h"
#include <stdio.h>

#define    BT_CTS_DIR    P8DIR
#define BT_CTS_OUT    P8OUT
#define BT_RTS_DIR    P1DIR                 //    Changed to P8 in recent versions
#define    BT_RTS_IN    P1IN                //    Changed to P8 in recent versions
#define    BT_RST_DIR    P5DIR
#define    BT_RST_OUT    P5OUT

#define    GREEN_LED    0x01
#define    RED_LED        0x02
#define    LEDS        0x03
#define    BT_RTS        0x01               //    Changed to 0x02 in recent versions
#define    BT_CTS        0x01
#define    BT_RESET    0x40

#define MSG_PERIOD    4095

void ConfigLEDs(void);
void BTUartInit(void);
void MessageTimerInit(void);

char BTMessage[20];
int16 CurrentVal;
uint8 Backwards;

int main(void) {
    WDTCTL = WDTPW + WDTHOLD;               //    Stop WDT
    SetCoreVoltage(VCORE19);                //    Set the core to 1.9V
    SetFLL(24);                             //    Set master clock to 24 MHz
    ConfigLEDs();                           //    Config port 2 for LEDs
    BTUartInit();                           //    Config UART for BlueTooth
    MessageTimerInit();
    __bis_SR_register(LPM0_bits + GIE);     //    Enter LPM0, enable interrupts
}

void ConfigLEDs(void) {
    P2DIR |= LEDS;        //    Enable LEDs
    P2OUT |= LEDS;
}

void MessageTimerInit(void) {
    TA0CCTL0 = CCIE;                        //    CCR0 interrupt enabled
    TA0CCR0 = MSG_PERIOD;                   //    1 per second
    TA0CTL = TASSEL_1 + MC_1 + TACLR;       //    SMCLK, upmode, clear TAR
}

void BTUartInit(void){
    P8SEL |= 0x0C;                          //    Config P8.2 & P8.3 for UART
    BT_CTS_DIR |= BT_CTS;                   //    Config P8.0 for output
    BT_RTS_DIR &= ~BT_RTS;                  //    Config P8.1 for input
    BT_RST_DIR |= BT_RESET;                 //    Configure bluetooth reset pin
    BT_RST_OUT |= BT_RESET;
    UCA1CTL1 |= UCSWRST;                    //    Put state machine in reset
    UCA1CTL1 |= UCSSEL_2;                   //    CLK = SMCLK
    UCA1BRW = 208;                          //    24MHz / 115.2k
    UCA1CTL1 &= ~UCSWRST;                   //    Initialize USCI state machine
    UCA1IE |= UCRXIE;                       //    Enable interrupts
    P5OUT &= ~BT_RESET;                     //    Reset bluetooth
    Delay(10);                              //    Delay
    P5OUT |= BT_RESET;                      //    Free reset. Ready to go.
    BT_CTS_OUT &= ~BT_CTS;                  //    Clear to send
}

void SendMessage() {
    uint8 i;
    uint8 len;
    len = sprintf(BTMessage, "%d", CurrentVal);
    for(i = len ; i < 20 ; ++i) {
        BTMessage[i] = ' ';
    }
    if(Backwards) CurrentVal--;             //    Decrement if backwards
    else CurrentVal++;                      //    Increment if forwards
    BT_CTS_OUT |= BT_CTS;
    for(i = 0 ; i < 20 ; ++i) {
        while(BT_RTS_IN & BT_RTS);          //    Wait until module is ready
        while(!(UCA1IFG & UCTXIFG));        //    Wait until UART is cleared
        UCA1TXBUF = BTMessage[i];
    }
    BT_CTS_OUT &= ~BT_CTS;                  //    Clear to send
}

#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void) {
    uint8 val;
    _DINT();
    val = UCA1RXBUF;
    P2OUT = val;                            //    Set the message to outputLEDs
    if(val == 0) CurrentVal = 0;
    else if(val == 1) Backwards = 1;
    else Backwards = 0;
    _EINT();
}

// Timer0 A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void) {
    _DINT();
    SendMessage();
    _EINT();
}

--------------------