//-------------------------------------------------------------------- // thermologger.c by easycraft-TA 2007-01-27 // This is for the thermologger that uses the AKI-3694F H8 board. // http://easycraft.seesaa.net/ //-------------------------------------------------------------------- #include <3694.h> void init_timer(void); void init_adc(void); void init_lcd(void); void wait (long num); unsigned char read_lcd(unsigned char rs); void write_lcd(unsigned char data, unsigned char rs); void puts_lcd(char *str); void move_lcd_xy(unsigned char x, unsigned char y); void putd_lcd(int d, int num); //-------------------------------------- // タイマV設定 (最小分解能1msウェイト用) //-------------------------------------- void init_timer(void) { TV.TCRV0.BIT.CCLR = 1; // コンペアマッチAでTCNVクリア TV.TCRV0.BIT.CKS = 0; // 停止 TV.TCRV1.BIT.ICKS = 1; // 上記CKS=3と併用で φ/128=156.25kHz TV.TCSRV.BIT.CMFA = 0; // フラグクリア TV.TCNTV = 0; // タイマカウンタクリア TV.TCORA = 156-1; // タイムコンスタントレジスタA設定 156.25kHz/156≒=1ms } //-------------------------------------- // ADCポート初期化 //-------------------------------------- typedef struct { // A/Dコンバータのデータレジスタ読み出しのための構造体 union { struct { _WORD DATA: 10; _WORD DUMMY: 6; } WORD10; struct { _BYTE HI; _BYTE LO; } BYTE; } DR[4]; } TADDR; void init_adc(void) { AD.ADCSR.BYTE = 0; // A/D変換停止 AD.ADCSR.BIT.ADIE = 0; // A/D変換割り込み禁止 AD.ADCSR.BIT.SCAN = 1; // スキャンモード AD.ADCSR.BIT.CKS = 1; // 高速変換 AD.ADCSR.BIT.CH = 5; // AN4〜AN5 AD.ADCSR.BIT.ADST = 1; // A/D変換スタート } //-------------------------------------- // P10-12 P50-53(LCD制御用)初期化 //-------------------------------------- #define LCD_RS IO.PDR1.BIT.B0 #define LCD_E IO.PDR1.BIT.B1 #define LCD_RW IO.PDR1.BIT.B2 #define LCD_DATA_PORT IO.PDR5.BYTE #define LCD_CMD_MODE 0 // LCD コマンドモード #define LCD_DAT_MODE 1 // LCD データモード #define LCD_WRITE_MODE 0 // LCD 書き込みモード #define LCD_READ_MODE 1 // LCD 読み出しモード #define LCD_E_LOW 0 // LCD Enable Bit Low #define LCD_E_HIGH 1 // LCD Enable BIt High #define LCD_CLEAR 0x01 #define LCD_HOME 0x02 #define LCD_ENTMODE 0x06 void init_lcd(void) { IO.PCR1 = 0x07; // PORT10,11,12を出力に設定 IO.PCR5 = 0x0F; // PORT50-53を出力に設定 LCD_RS = LCD_CMD_MODE; // LCDをコマンドモードに LCD_RW = LCD_WRITE_MODE; // LCDのデータポートを書き込みモードに LCD_E = LCD_E_LOW; // LCDのイネーブル信号をLOWに wait(15); // LCDの立ち上がり待ち LCD_E = LCD_E_HIGH; // Enable信号をHIGHに LCD_DATA_PORT = 0x03; // データポートに8ビットモードコマンドをセット LCD_E = LCD_E_LOW; // Enable信号LOWでLCDがデータ読み込み wait(5); LCD_E = LCD_E_HIGH; // 上記コマンドを計3回送ると確実に8ビットモード LCD_DATA_PORT = 0x03; LCD_E = LCD_E_LOW; wait(5); LCD_E = LCD_E_HIGH; // 3回め LCD_DATA_PORT = 0x03; LCD_E = LCD_E_LOW; wait(5); LCD_E = LCD_E_HIGH; // 8ビットモードになったところで確実に4ビットモードにする LCD_DATA_PORT = 0x02; LCD_E = LCD_E_LOW; write_lcd(0x28, LCD_CMD_MODE); // データ長4ビット、デューティー1/16、キャラクタ5x7 write_lcd(0x08, LCD_CMD_MODE); // 表示シフト、右シフト write_lcd(0x01, LCD_CMD_MODE); // 表示クリア write_lcd(0x06, LCD_CMD_MODE); // エントリモードではシフトしない write_lcd(0x0d, LCD_CMD_MODE); // 表示オン、カーソルオフ、ブリンクオフ } //-------------------------------------- // LCD read関数 //-------------------------------------- unsigned char read_lcd(unsigned char rs) { unsigned char rdata, upperch, lowerch; IO.PCR5 = 0x00; // ポート50〜53を入力モードに LCD_RS = rs; // LCD command/data モード選択 LCD_RW = LCD_READ_MODE; // LCD readモード LCD_E = LCD_E_HIGH; upperch = LCD_DATA_PORT << 4; // LCD 上位ビット取得 LCD_E = LCD_E_LOW; // wait(5); LCD_E = LCD_E_HIGH; lowerch = LCD_DATA_PORT & 0x0F; // LCD 下位ビット取得 LCD_E = LCD_E_LOW; rdata = upperch | lowerch; // 上位下位ビットマージ return rdata; } //-------------------------------------- // LCD write関数 //-------------------------------------- void write_lcd(unsigned char data, unsigned char rs) { while ( (read_lcd(LCD_CMD_MODE) & 0x80) != 0 ); IO.PCR5 = 0x0F; // ポート50〜53を出力モードに LCD_RS = rs; // LCD command/data モード選択 LCD_RW = LCD_WRITE_MODE; // LCD writeモード LCD_E = LCD_E_HIGH; LCD_DATA_PORT = data >> 4; // LCD 上位ビット書き込み LCD_E = LCD_E_LOW; // wait(5); LCD_E = LCD_E_HIGH; LCD_DATA_PORT = data & 0x0F; // LCD 下位ビット書き込み LCD_E = LCD_E_LOW; } //-------------------------------------- // LCD 表示位置指定 //-------------------------------------- void move_lcd_xy(unsigned char x, unsigned char y) { unsigned char pos; pos = ((x -1) + (y - 1) * 0x40) | 0x80; write_lcd(pos, LCD_CMD_MODE); } //-------------------------------------- // LCD puts関数 //-------------------------------------- void lcd_puts(char *str) { while (*str) { write_lcd(*str, LCD_DAT_MODE); str++; } } //-------------------------------------- // LCD 数値書き出し d:数値 num:桁数 //-------------------------------------- void lcd_putd(int d, int num) { int i, dtemp, numd; char dig; for (i=1, numd=1; i0; i=i/10) { dig = (char)((d - dtemp) / i); write_lcd(dig+0x30, LCD_DAT_MODE); dtemp = dtemp + (int)dig * i; } } /*-----------------------------------------------*/ /* 1msウェイト */ /*-----------------------------------------------*/ void wait(long num) { long i; TV.TCRV0.BIT.CKS = 3; // カウント開始 for (i = 0; i < num; i++) { while (!TV.TCSRV.BIT.CMFA) ; // TCNTV=TCORAフラグ待ち TV.TCSRV.BIT.CMFA = 0; // フラグクリア } TV.TCRV0.BIT.CKS = 0; // カウント停止 } //-------------------------------------- // メイン //-------------------------------------- void main(void) { char txb[10], rxb[10]; // シリアルポート送受信用バッファ char rc; // 受信文字 int ch; // ADCチャネル指定 int adv; // ADC読み取り値 unsigned long intp[4]; // ADCチャネルごとの変換値 TADDR *ADBuf = (TADDR *)&AD.ADDRA; // ADCデータレジスタを構造体にアサイン init_timer (); // タイマー初期化 init_adc(); // ADCポート初期化 init_lcd(); // LCD初期化 SCI3_INIT(br57600, txb, sizeof(txb), rxb, sizeof(rxb)); // シリアルポート初期化 EI; lcd_puts("Easy Thermometer"); while (1) { move_lcd_xy(1, 2); for (ch=0; ch<4; ch++) { adv = ADBuf->DR[ch].WORD10.DATA; // A/D値を取得 intp[ch] = (unsigned long)adv * 100 / 1023; // 温度に換算 } for (ch=0; ch<4; ch++) { lcd_putd(intp[ch], 3); // LCDに温度を表示 write_lcd(' ', LCD_DAT_MODE); } if (SCI3_IN_DATA_CHECK() > 0) { // 通信ポートにデータが来ていたら・・ rc = SCI3_IN_DATA(); // 1文字読み込む switch (rc) { // 読み込んだ文字がコマンドだとして・・ case 'T': // Tは温度データ送信命令。たとえば"T1100"のような形 SCI3_OUT_DATA('A'); // まず、命令を受け取ったことを返す for (ch=0; ch<4; ch++) { // 温度センサーの数だけループ rc = SCI3_IN_DATA(); // 1文字読み込む if (rc == '1') { // 1なら・・ SCI3_PRINTF("%04lu", intp[ch]); // 変数ch番目の温度データを4桁の数字にして送信 } else { SCI3_PRINTF("9999"); // 1以外なら、9999を送信 } } break; case 'P': //なんらかの操作をさせるつもり break; default: SCI3_PRINTF("xxxx"); // コマンド以外はxxxxを送信 } SCI3_IN_DATA_CLEAR(); // 受信データをクリア } wait (50); //ちょっとだけ待つ } }