閲覧総計:&counter();  (本日:&counter(today);  昨日:&counter(yesterday);)~
*A/D値をI2C接続LCDに表示(16F1827 XC8) [#o98fc4dd]

アナログ値をデジタル値に変換した値(0-1023)をI2C接続の液晶ディスプレイ
(LCD:Liquid Crystal  Display)に表示する。また、その値でLEDの点滅間隔
を0-1023ミリ秒 の間で滑らかに変更する。

PICにLCDが接続できる様になると、PICの変数の内容をLCDに表示することで
PICの動きが視覚的に判断できる様になり、非常に便利である。特にデバッグ
時に。
今回はA/D値をLCDに表示し、その値でLEDの点滅間隔を制御した。
可変抵抗器の操作でA/D値を1000に合わせるとLEDが1秒間隔で点灯・消灯を
繰り返す事が確認出来た。            2014/1/8

|&attachref(TS3V0010.JPG,zoom,200x300,button){新しい写真添付};|&attachref(16F1827ピン配置.JPG,zoom,200x250,button){新しい写真添付};|

 /* A/D値で発光ダイオード(LED)の点滅間隔を変更する
  * A/D値をI2C LCDに表示する
  * PIC16F1827
  * XC8 v1.20
  * LED:RA2,RA3
  * 可変抵抗(10kΩ):RB5
  * I2C SDA:SDA1(RB1) pin7
  * I2C SCL:SCL1(RB4) pin10
  */
 #include <xc.h>
 #define _XTAL_FREQ 8000000 //PICのクロックをHzで設定(8MHz)
 
 #pragma config FOSC = INTOSC, WDTE = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
 #pragma config PLLEN = OFF, STVREN = OFF, LVP = OFF
 
 //関数のプロトタイプ宣言
 extern void itostring(char digit, unsigned int data, char *buffer);
 extern unsigned int read_a2d(unsigned char channel);
 extern void arg_delay_ms(unsigned int x);
 
 void i2cByteWrite(char, char, char);    // i2c byte送信
 void i2cTxData(char);                   // i2c SSPBUF セット
 void LCD_dat(char);                     // 1文字表示
 void LCD_cmd(char);                     // コマンド出力
 void LCD_clr(void);                     // 全消去
 void LCD_int(void);                     // 初期化
 void LCD_str(char *);                   // 文字列表示
 void LCD_ROMstr(const char *);          // ROM文字列表示
 void LCD_posyx(char,char);              // カーソル位置指定
 void LCD_hex(char);                     // 16進文字変換表示
 
 int main(void) {
     //使用変数の定義
     unsigned int ad_val; //ADC値の結果
     unsigned char s_ad_val[6]; //ADC値の文字列表示用
 
     //PICの初期設定
     PORTA = 0b00000000; //PORTAの中身をきれいにする
     PORTB = 0b00000000; //PORTBの中身をきれいにする
     TRISA = 0b00000000; //PORTA全てを0:出力に設定
     TRISB = 0b11111111; //PORTBは全て1:入力に設定
     ANSELA = 0b00000000; //RA4(AN4)-RA0(AN0)は全て0:デジタルI/Oとする
     ANSELB = 0b00100000; //RB5(AN7)のみ1:アナログ、他は0:デジタルI/Oとする
     OSCCON = 0b01110000; //PLL:OFF, 内部クロック8MHzで駆動
     OPTION_REGbits.nWPUEN = 0; // 0:PORTB内部プルアップ利用に設定
     WPUBbits.WPUB1 = 1; // RB1をI2C通信のウィークプルアップ
     WPUBbits.WPUB4 = 1; // RB4をI2C通信のウィークプルアップ
 
     //I2C通信の初期設定
     SSPCON1 = 0b00101000;          // I2Cマスターモード指定
     SSPSTAT = 0b00000000;          // I2C STATUSの設定
     SSPADD  = 19;                  // I2Cクロック周波数100KHz(=(19+1)*4/8MHz)
 
     //A2D変換開始
     ADCON1 = 0b10010000; //select right justify result, ADCS Fosc/8, A/D port configuratio n 0
     ADCON0bits.ADON = 1; //ADON
 
     //メイン処理
     LATAbits.LATA2 = 1; //RA2:パワーオンを示すLED点灯
     LCD_int(); // LCD初期化
     LCD_ROMstr("A/D (0-1023)"); // 1行目に表示
     LCD_posyx(1,3); // 2行目に表示
     LCD_ROMstr("A/D Val=");
 
     while(1) {
         //アナログデータの取得 10bit(0~1023)
         ad_val = read_a2d(7); //RB5(AN7)のアナログ値読み込み
 
         //AD値のLCD表示
         LCD_posyx(1,12); // 2行8文字目にカーソル移動
         itostring(4, ad_val, s_ad_val);
         LCD_str(s_ad_val);
 
         //LED点滅間隔が0-1023msecで滑らかに変更出来る
         LATAbits.LATA3 = 1; //RA3 LED ON
         arg_delay_ms(ad_val); //所定時間待つ
         LATAbits.LATA3 = 0; //RA3 LED OFF
         arg_delay_ms(ad_val); //所定時間待つ
     }
 }
 
 /***************************************
 * int整数からASCII文字に変換
 ****************************************/
 void itostring(char digit, unsigned int data, char *buffer) {
     char i;
 
     buffer += digit;		     // 最後の数字位置
     for(i=digit; i>0; i--) {	     // 変換は下位から上位へ
         buffer--;		     // ポインター1
         *buffer = (data % 10) + '0'; // ASCIIへ
         data = data / 10;	     // 次の桁へ
     }
 }
 
 //引数のアナロポートのA2D変換(10bit仕様) 2014/1/2
 //PICC v9.81のsamplesフォルダ内のa2demo.cのプログラムを参考にアレンジ
 unsigned int read_a2d(unsigned char channel) {
     channel &= 0b00011111; //truncate channel to 5 bits
     ADCON0 &= 0b10000011; //clear current channel select
     ADCON0 |= (channel << 2); //apply the new channel select
     __delay_us(5); // アナログ変換情報が設定されるまで5μ秒待つ
     ADCON0bits.GO_nDONE = 1; // initiate conversion on the selected channel
     while (ADCON0bits.GO_nDONE) continue;
 
     return (ADRESH << 8) | ADRESL;
 }
 
 //待ち時間が変数設定できるarg_delay_ms()関数を定義
 //(__delay_ms()は引数に変数設定が出来ない為)
 void arg_delay_ms(unsigned int x) {
     while(x) {
         __delay_ms(1);
         x--;
     }
 }
 
 //-------- i2cで1byteデータを送信する -----------------------
 //  以下の引数が必要
 //  addr : Slaveのアドレス
 //  cont : Slaveへ制御コード
 //  data : 送信するデータ
 //  NACKやBus衝突などの対応は行っていない
 // -----------------------------------------------------------
 void i2cByteWrite(char addr, char cont, char data){
     SSPCON2bits.SEN = 1;           // Start condition 開始
     while(SSPCON2bits.SEN);        // Start condition 確認
     i2cTxData(addr);               // アドレス送信
     i2cTxData(cont);               // 制御コード送信
     i2cTxData(data);               // データ送信
     SSP1IF = 0;                    // 終了フラグクリア
     SSPCON2bits.PEN = 1;           // Stop condition 開始
     while(SSPCON2bits.PEN);        // Stop condition 確認
 }
 
 //-------- SSPBUFに1文字保存し送信終了を待つ -----------------
 void i2cTxData(char data){
     SSP1IF = 0;                    // 終了フラグクリア
     SSPBUF = data;                 // データセット
     while(!SSP1IF);                // 送信終了待ち
 }
 
 //-------- 1文字表示 --------------------------------------
 void LCD_dat(char chr){
     i2cByteWrite(0xA0, 0x80, chr);
     __delay_us(60);                // 60μsec
 }
 //-------- コマンド出力 --------------------------------------
 void LCD_cmd(char cmd){
     i2cByteWrite(0xA0, 0x00, cmd);
     if(cmd & 0xFC)                 // 上位6ビットに1がある命令
         __delay_us(60);            // 60usec
     else
         __delay_ms(3);             // 3msec ClearおよびHomeコマンド
 }
 //-------- 全消去 ------------------------------------------------
 void LCD_clr(void){
     LCD_cmd(0x01);                 //Clearコマンド出力
 }
 //-------- カーソル位置指定 --------------------------------------
 void LCD_posyx(char ypos, char xpos){
     unsigned char pcode;
     switch(ypos & 0x03){           // 縦位置を取得
         case 0: pcode=0x80;break;  // 1行目
         case 1: pcode=0xC0;break;  // 2行目
         case 2: pcode=0x94;break;  // 3行目
         case 3: pcode=0xD4;break;  // 4行目
     }
     LCD_cmd(pcode += xpos);        // 横位置を加える
 }
 //-------- 文字列出力 -----------------------------------------
 void LCD_str(char *str){
     while(*str)                    //文字列の終わり(00)まで継続
         LCD_dat(*str++);           //文字出力しポインタ+1
 }
 //-------- Rom 文字列出力 ------------------------------------
 void LCD_ROMstr(const char *str){
     while(*str)                    //文字列の終わり(00)まで継続
         LCD_dat(*str++);           //文字出力しポインタ+1
 }
 //-------- 16進文字変換表示 --------------------------------
 void LCD_hex(char c){
     const char hexch[] ="0123456789ABCDEF";
     LCD_dat(hexch[c >> 4]);        //上位4bit表示
     LCD_dat(hexch[c & 0xF]);       //下位4bit表示
 }
 
 //-------- 初期化 --------------------------------------
 void LCD_int(void){
     __delay_ms(100);               // 電源安定するまでの時間
     LCD_cmd(0x38);                 // 8bit 2行 表示命令モード
     LCD_cmd(0x0C);                 // Display on Cursor=0 Blink=0
     LCD_cmd(0x06);                 // Entry Inc/Dec=1 Shift=0
     LCD_cmd(0x01);                 // Clear Display
 }
 
★この情報は役に立ちましたか?
#vote(はい[0],普通[0],いいえ[0])

#comment_nospam