MPU6050のサンプルプログラム2

Dependencies:   ConfigFile SDFileSystem mbed

Fork of LAURUS_program by LAURUS

Files at this revision

API Documentation at this revision

Comitter:
onaka
Date:
Fri Jun 12 04:00:23 2015 +0000
Parent:
5:182f6356bce1
Child:
7:0ec343d29641
Child:
8:602865d8fca3
Commit message:
logger update

Changed in this revision

BufferedSerial/Buffer/Buffer.cpp Show annotated file Show diff for this revision Revisions of this file
BufferedSerial/Buffer/Buffer.h Show annotated file Show diff for this revision Revisions of this file
BufferedSerial/BufferedSerial.cpp Show annotated file Show diff for this revision Revisions of this file
BufferedSerial/BufferedSerial.h Show annotated file Show diff for this revision Revisions of this file
Log/Log.cpp Show annotated file Show diff for this revision Revisions of this file
Log/Log.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BufferedSerial/Buffer/Buffer.cpp	Fri Jun 12 04:00:23 2015 +0000
@@ -0,0 +1,76 @@
+
+/**
+ * @file    Buffer.cpp
+ * @brief   Software Buffer - Templated Ring Buffer for most data types
+ * @author  sam grove
+ * @version 1.0
+ * @see     
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "Buffer.h"
+
+template <class T>
+Buffer<T>::Buffer(uint32_t size)
+{
+    _buf = new T [size];
+    _size = size;
+    clear();
+    
+    return;
+}
+
+template <class T>
+Buffer<T>::~Buffer()
+{
+    delete [] _buf;
+    
+    return;
+}
+
+template <class T>
+uint32_t Buffer<T>::getSize() 
+{ 
+    return this->_size; 
+}
+
+template <class T>
+void Buffer<T>::clear(void)
+{
+    _wloc = 0;
+    _rloc = 0;
+    memset(_buf, 0, _size);
+    
+    return;
+}
+
+template <class T>
+uint32_t Buffer<T>::peek(char c)
+{
+    return 1;
+}
+
+// make the linker aware of some possible types
+template class Buffer<uint8_t>;
+template class Buffer<int8_t>;
+template class Buffer<uint16_t>;
+template class Buffer<int16_t>;
+template class Buffer<uint32_t>;
+template class Buffer<int32_t>;
+template class Buffer<uint64_t>;
+template class Buffer<int64_t>;
+template class Buffer<char>;
+template class Buffer<wchar_t>;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BufferedSerial/Buffer/Buffer.h	Fri Jun 12 04:00:23 2015 +0000
@@ -0,0 +1,167 @@
+
+/**
+ * @file    Buffer.h
+ * @brief   Software Buffer - Templated Ring Buffer for most data types
+ * @author  sam grove
+ * @version 1.0
+ * @see     
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#ifndef BUFFER_H
+#define BUFFER_H
+
+#include <stdint.h>
+#include <string.h>
+
+/** A templated software ring buffer
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "Buffer.h"
+ *
+ *  Buffer <char> buf;
+ *
+ *  int main()
+ *  {
+ *      buf = 'a';
+ *      buf.put('b');
+ *      char *head = buf.head();
+ *      puts(head);
+ *
+ *      char whats_in_there[2] = {0};
+ *      int pos = 0;
+ *
+ *      while(buf.available())
+ *      {   
+ *          whats_in_there[pos++] = buf;
+ *      }
+ *      printf("%c %c\n", whats_in_there[0], whats_in_there[1]);
+ *      buf.clear();
+ *      error("done\n\n\n");
+ *  }
+ * @endcode
+ */
+
+template <typename T>
+class Buffer
+{
+private:
+    T   *_buf;
+    volatile uint32_t   _wloc;
+    volatile uint32_t   _rloc;
+    uint32_t            _size;
+
+public:
+    /** Create a Buffer and allocate memory for it
+     *  @param size The size of the buffer
+     */
+    Buffer(uint32_t size = 0x100);
+    
+    /** Get the size of the ring buffer
+     * @return the size of the ring buffer
+     */
+     uint32_t getSize();
+    
+    /** Destry a Buffer and release it's allocated memory
+     */
+    ~Buffer();
+    
+    /** Add a data element into the buffer
+     *  @param data Something to add to the buffer
+     */
+    void put(T data);
+    
+    /** Remove a data element from the buffer
+     *  @return Pull the oldest element from the buffer
+     */
+    T get(void);
+    
+    /** Get the address to the head of the buffer
+     *  @return The address of element 0 in the buffer
+     */
+    T *head(void);
+    
+    /** Reset the buffer to 0. Useful if using head() to parse packeted data
+     */
+    void clear(void);
+    
+    /** Determine if anything is readable in the buffer
+     *  @return 1 if something can be read, 0 otherwise
+     */
+    uint32_t available(void);
+    
+    /** Overloaded operator for writing to the buffer
+     *  @param data Something to put in the buffer
+     *  @return
+     */
+    Buffer &operator= (T data)
+    {
+        put(data);
+        return *this;
+    }
+    
+    /** Overloaded operator for reading from the buffer
+     *  @return Pull the oldest element from the buffer 
+     */  
+    operator int(void)
+    {
+        return get();
+    }
+    
+     uint32_t peek(char c);
+    
+};
+
+template <class T>
+inline void Buffer<T>::put(T data)
+{
+    _buf[_wloc++] = data;
+    _wloc %= (_size-1);
+    if(_wloc==_rloc){
+        _rloc++;
+        _rloc %= (_size-1);
+    }
+    
+    return;
+}
+
+template <class T>
+inline T Buffer<T>::get(void)
+{
+    T data_pos = _buf[_rloc++];
+    _rloc %= (_size-1);
+    
+    return data_pos;
+}
+
+template <class T>
+inline T *Buffer<T>::head(void)
+{
+    T *data_pos = &_buf[0];
+    
+    return data_pos;
+}
+
+template <class T>
+inline uint32_t Buffer<T>::available(void)
+{
+    return (_wloc == _rloc) ? 0 : 1;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BufferedSerial/BufferedSerial.cpp	Fri Jun 12 04:00:23 2015 +0000
@@ -0,0 +1,165 @@
+/**
+ * @file    BufferedSerial.cpp
+ * @brief   Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX
+ * @author  sam grove
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BufferedSerial.h"
+#include <stdarg.h>
+
+BufferedSerial::BufferedSerial(PinName tx, PinName rx, PinName cts, uint32_t buf_size, uint32_t tx_multiple, const char* name)
+    : SERIAL_BASE(tx, rx) , _cts(cts), _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size))
+{
+    SERIAL_BASE::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq);
+    this->_buf_size = buf_size;
+    this->_tx_multiple = tx_multiple;   
+    
+    _cts.fall(this, &BufferedSerial::ctsInterrupt);
+    return;
+}
+
+BufferedSerial::~BufferedSerial(void)
+{
+    SERIAL_BASE::attach(NULL, SERIAL_BASE::RxIrq);
+    SERIAL_BASE::attach(NULL, SERIAL_BASE::TxIrq);
+
+    return;
+}
+
+int BufferedSerial::readable(void)
+{
+    return _rxbuf.available();  // note: look if things are in the buffer
+}
+
+int BufferedSerial::writeable(void)
+{
+    return 1;   // buffer allows overwriting by design, always true
+}
+
+int BufferedSerial::getc(void)
+{
+    return _rxbuf;
+}
+
+int BufferedSerial::putc(int c)
+{
+    _txbuf = (char)c;
+    BufferedSerial::prime();
+
+    return c;
+}
+
+int BufferedSerial::puts(const char *s)
+{
+    if (s != NULL) {
+        const char* ptr = s;
+    
+        while(*(ptr) != 0) {
+            _txbuf = *(ptr++);
+        }
+        _txbuf = '\n';  // done per puts definition
+        BufferedSerial::prime();
+    
+        return (ptr - s) + 1;
+    }
+    return 0;
+}
+
+int BufferedSerial::printf(const char* format, ...)
+{
+    char buffer[this->_buf_size];
+    memset(buffer,0,this->_buf_size);
+    int r = 0;
+
+    va_list arg;
+    va_start(arg, format);
+    r = vsprintf(buffer, format, arg);
+    // this may not hit the heap but should alert the user anyways
+    if(r > this->_buf_size) {
+        error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__,this->_buf_size,r);
+        va_end(arg);
+        return 0;
+    }
+    va_end(arg);
+    r = BufferedSerial::write(buffer, r);
+
+    return r;
+}
+
+ssize_t BufferedSerial::write(const void *s, size_t length)
+{
+    if (s != NULL && length > 0) {
+        const char* ptr = (const char*)s;
+        const char* end = ptr + length;
+    
+        while (ptr != end) {
+            _txbuf = *(ptr++);
+        }
+        BufferedSerial::prime();
+    
+        return ptr - (const char*)s;
+    }
+    return 0;
+}
+
+
+void BufferedSerial::rxIrq(void)
+{
+    // read from the peripheral and make sure something is available
+    if(serial_readable(&_serial)) {
+        _rxbuf = serial_getc(&_serial); // if so load them into a buffer
+    }
+
+    return;
+}
+
+void BufferedSerial::txIrq(void)
+{
+    // see if there is room in the hardware fifo and if something is in the software fifo
+    while(serial_writable(&_serial) && !_cts) {
+        if(_txbuf.available()) {
+            serial_putc(&_serial, (int)_txbuf.get());
+        } else {
+            // disable the TX interrupt when there is nothing left to send
+            SERIAL_BASE::attach(NULL, SERIAL_BASE::TxIrq);
+            break;
+        }
+    }
+
+    return;
+}
+
+void BufferedSerial::prime(void)
+{
+    // if already busy then the irq will pick this up
+    if(serial_writable(&_serial) && !_cts) {
+        SERIAL_BASE::attach(NULL, SERIAL_BASE::TxIrq);    // make sure not to cause contention in the irq
+        BufferedSerial::txIrq();                // only write to hardware in one place
+        SERIAL_BASE::attach(this, &BufferedSerial::txIrq, SERIAL_BASE::TxIrq);
+    }
+
+    return;
+}
+
+void BufferedSerial::ctsInterrupt(void)
+{
+    BufferedSerial::prime();
+    return;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BufferedSerial/BufferedSerial.h	Fri Jun 12 04:00:23 2015 +0000
@@ -0,0 +1,147 @@
+
+/**
+ * @file    BufferedSerial.h
+ * @brief   Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX
+ * @author  sam grove
+ * @version 1.0
+ * @see     
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BUFFEREDSERIAL_H
+#define BUFFEREDSERIAL_H
+ 
+#include "mbed.h"
+#include "Buffer.h"
+
+// Base Class
+#define SERIAL_BASE  RawSerial
+
+/** A serial port (UART) for communication with other serial devices
+ *
+ * Can be used for Full Duplex communication, or Simplex by specifying
+ * one pin as NC (Not Connected)
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "BufferedSerial.h"
+ *
+ *  BufferedSerial pc(USBTX, USBRX);
+ *
+ *  int main()
+ *  { 
+ *      while(1)
+ *      {
+ *          Timer s;
+ *        
+ *          s.start();
+ *          pc.printf("Hello World - buffered\n");
+ *          int buffered_time = s.read_us();
+ *          wait(0.1f); // give time for the buffer to empty
+ *        
+ *          s.reset();
+ *          printf("Hello World - blocking\n");
+ *          int polled_time = s.read_us();
+ *          s.stop();
+ *          wait(0.1f); // give time for the buffer to empty
+ *        
+ *          pc.printf("printf buffered took %d us\n", buffered_time);
+ *          pc.printf("printf blocking took %d us\n", polled_time);
+ *          wait(0.5f);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/**
+ *  @class BufferedSerial
+ *  @brief Software buffers and interrupt driven tx and rx for Serial
+ */  
+class BufferedSerial : public SERIAL_BASE 
+{
+private:
+    InterruptIn   _cts;
+    Buffer <char> _rxbuf;
+    Buffer <char> _txbuf;
+    uint32_t      _buf_size;
+    uint32_t      _tx_multiple;
+ 
+    void rxIrq(void);
+    void txIrq(void);
+    void prime(void);
+    
+    void ctsInterrupt(void);
+    
+public:
+    /** Create a BufferedSerial port, connected to the specified transmit and receive pins
+     *  @param tx Transmit pin
+     *  @param rx Receive pin
+     *  @param cts CTS pin
+     *  @param buf_size printf() buffer size
+     *  @param tx_multiple amount of max printf() present in the internal ring buffer at one time
+     *  @param name optional name
+     *  @note Either tx or rx may be specified as NC if unused
+     */
+    BufferedSerial(PinName tx, PinName rx, PinName cts, uint32_t buf_size = 256, uint32_t tx_multiple = 4,const char* name=NULL);
+    
+    /** Destroy a BufferedSerial port
+     */
+    virtual ~BufferedSerial(void);
+    
+    /** Check on how many bytes are in the rx buffer
+     *  @return 1 if something exists, 0 otherwise
+     */
+    virtual int readable(void);
+    
+    /** Check to see if the tx buffer has room
+     *  @return 1 always has room and can overwrite previous content if too small / slow
+     */
+    virtual int writeable(void);
+    
+    /** Get a single byte from the BufferedSerial Port.
+     *  Should check readable() before calling this.
+     *  @return A byte that came in on the Serial Port
+     */
+    virtual int getc(void);
+    
+    /** Write a single byte to the BufferedSerial Port.
+     *  @param c The byte to write to the Serial Port
+     *  @return The byte that was written to the Serial Port Buffer
+     */
+    virtual int putc(int c);
+    
+    /** Write a string to the BufferedSerial Port. Must be NULL terminated
+     *  @param s The string to write to the Serial Port
+     *  @return The number of bytes written to the Serial Port Buffer
+     */
+    virtual int puts(const char *s);
+    
+    /** Write a formatted string to the BufferedSerial Port.
+     *  @param format The string + format specifiers to write to the Serial Port
+     *  @return The number of bytes written to the Serial Port Buffer
+     */
+    virtual int printf(const char* format, ...);
+    
+    /** Write data to the Buffered Serial Port
+     *  @param s A pointer to data to send
+     *  @param length The amount of data being pointed to
+     *  @return The number of bytes written to the Serial Port Buffer
+     */
+    virtual ssize_t write(const void *s, std::size_t length);
+};
+
+#endif
--- a/Log/Log.cpp	Thu Jun 11 17:40:39 2015 +0000
+++ b/Log/Log.cpp	Fri Jun 12 04:00:23 2015 +0000
@@ -1,9 +1,8 @@
 #include "Log.h"
 
-Log::Log(PinName tx, PinName rx, PinName cts, PinName mosi, PinName miso, PinName sck, PinName cs) :
-    _sd(mosi, miso, sck, cs, "sd"), _device(tx, rx), ctsPin(cts){
-    buf_send.initialize_buffer();
-    //_device.attach(this, &Log::int_serial_tx, Serial::TxIrq);
+Log::Log(PinName mosi, PinName miso, PinName sck, PinName cs, PinName tx, PinName rx, PinName cts) :
+    _sd(mosi, miso, sck, cs, "sd"), _device(tx, rx, cts){
+    
 }
 
 int Log::initialize_sdlog(const char* str){
@@ -16,10 +15,8 @@
     sprintf(filename, "/sd/log%03d.csv", n+1);
     fp = fopen(filename, "w");
     
+    fprintf(fp, str);
     _device.printf(str);
-    fprintf(fp, str);
-    fflush(fp);
-    
     return 1;
 }
 
@@ -36,7 +33,7 @@
     struct dirent *dirst;
     dp = opendir("/sd/");
     if (!dp){
-        printf("Could not open directry\n");
+        error("Could not open directry.\n");
         return -1;
     }
     while((dirst = readdir(dp)) != NULL) {
@@ -48,87 +45,7 @@
     return n;
 }
 
-void Log::puts(const char* str){
-    fputs(str, fp);
-    fflush(fp);
-    //while(!_device.writeable());
-    for(int i=0; str[i] != '\0'; i++) {
-        while(ctsPin);
-        _device.putc(str[i]);
-    }
-    /*int16_t len=strlen(str);
-    int16_t capa=buf_send.buffer_capacity();
-    bool empty=buf_send.is_buffer_empty();
-    char ch;
-    if(len>capa){
-        len=capa;
-    }
-    buf_send.write_buffer((const uint8_t*)str, 0, len);
-    if((_device.writeable()) && (empty)){
-        ch=buf_send.read_buffer_byte();
-        _device.putc(ch);
-        fputc(ch, fp);
-        fflush(fp);
-    }*/
-}
-
-void Log::putc(char ch){
-    
-    int16_t capa=buf_send.buffer_capacity();
-    if(capa==0) return;
-    buf_send.write_buffer_byte(ch);
-    
-}
-
-void Log::write_data(uint8_t* buf, int16_t size){
-    int capa=buf_send.buffer_capacity();
-    if(size>capa){
-        size=capa;
-    }
-    buf_send.write_buffer(buf, 0, size);
-}
-
-bool Log::is_empty(){
-    return buf_send.is_buffer_empty();
-}
-
-int16_t Log::recieve_buffer_size(){
-    return buf_recieve.buffer_size();
-}
-
-int16_t Log::getc(){
-    if(buf_recieve.is_buffer_empty()){
-        return -1;
-    }
-    return buf_recieve.read_buffer_byte();
-}
-
-int16_t Log::read_data(uint8_t* buf, int16_t size){
-    int len=buf_recieve.buffer_size();
-    if(size>len){
-        size=len;
-    }
-    buf_recieve.read_buffer(buf, 0, size);
-    return size;
-}
-
-char Log::int_tx(){
-    return buf_send.read_buffer_byte();
-}
-
-void Log::int_serial_tx(){
-    /*char ch;
-    while((_device.writeable()) && (buf_send.is_buffer_empty()==false)){
-        ch=buf_send.read_buffer_byte();
-        _device.putc(ch);
-        fputc(ch, fp);
-    }*/
-    
-    uint8_t buf[RING_BUFFER_SIZE] = {};
-    int data_num = buf_send.read_buffer_all(buf);
-    if(data_num != 0) {
-        _device.printf((const char*)buf);
-        fputs((const char*)buf, fp);
-        fflush(fp);
-    }
+void Log::write(const char* str){
+    fprintf(fp, str);
+    _device.printf(str);
 }
\ No newline at end of file
--- a/Log/Log.h	Thu Jun 11 17:40:39 2015 +0000
+++ b/Log/Log.h	Fri Jun 12 04:00:23 2015 +0000
@@ -8,31 +8,20 @@
 
 #include "mbed.h"
 #include "SDFileSystem.h"
-#include "RingBuffer.h"
+#include "BufferedSerial.h"
 
 class Log{
 public:
-    Log(PinName tx, PinName rx, PinName cts, PinName mosi, PinName miso, PinName sck, PinName cs);
+    Log(PinName mosi, PinName miso, PinName sck, PinName cs, PinName tx, PinName rx, PinName cts);
     int initialize_sdlog(const char* str);
     void close();
     int find_last();
-    void puts(const char *str);
-    void putc(char ch);
-    void write_data(uint8_t* buf, int16_t size);
-    bool is_empty();
-    int16_t recieve_buffer_size();
-    int16_t getc();
-    int16_t read_data(uint8_t* buf, int16_t size);
-    char int_tx();
-    void int_serial_tx();
+    void write(const char* str);
 
 protected:
     SDFileSystem _sd;
+    BufferedSerial _device;
     FILE *fp;
-    Serial _device;
-    DigitalIn ctsPin;
-    RingBuffer buf_send;
-    RingBuffer buf_recieve;
 };
 
 #endif /* LOG_H_ */
\ No newline at end of file
--- a/main.cpp	Thu Jun 11 17:40:39 2015 +0000
+++ b/main.cpp	Fri Jun 12 04:00:23 2015 +0000
@@ -27,7 +27,7 @@
 Serial      pc(SERIAL_TX, SERIAL_RX);   // PC通信用シリアルポート
 GMS6_CR6    gms(&gps, &pc);             // GPS
 Ticker      INT_timer;                      // 割り込みタイマー
-Log         logger(PA_9, PA_10, PC_1, PB_5, PB_4, PB_3, PB_10);    // ロガー(microSD、XBee)
+Log         logger(PB_5, PB_4, PB_3, PB_10, PA_9, PA_10, PC_1);    // ロガー(microSD、XBee)
 PwmOut      servoL(PC_7), servoR(PB_6);
 AnalogIn    rf(PC_0);
 AnalogIn    servoVcc(PA_0);
@@ -65,7 +65,7 @@
 
 Timer timer;
 
-char data[1024] = {};
+char data[512] = {};
 
 /********** private functions **********/
 void KalmanInit();                  // カルマンフィルタ初期化
@@ -84,7 +84,7 @@
     if(!hmc.init()) AbortWithMsg("hmc5883l Initialize Error !!");       // hmc5883l初期化
     
     char* title = "log data\r\n";                                       // ログのタイトル行
-    if(!logger.initialize_sdlog(title)) return 0;                       // ログファイル初期設定
+    logger.initialize_sdlog(title);                                     // ログファイル初期設定
     
     KalmanInit();
     
@@ -115,7 +115,7 @@
                 geomag.GetComp(1), geomag.GetComp(2), geomag.GetComp(3), 
                 press, gms.longitude, gms.latitude, 
                 sv, lv, gms.Ns);
-        logger.puts(data);
+        logger.write(data);
         
         INT_flag = TRUE;            // 割り込み許可