Quantcast
Channel: JH7UBCブログ
Viewing all articles
Browse latest Browse all 440

PIC12F675 I2C address scanner

$
0
0
 PIC12F675は、I2Cの信号を発生する機能を持っていません。そこで、ソフト的にI2Cを行うことになります。

 あちこちのWebサイトを参考にして、start condition, 1 bye 送信,stop conditionのプログラムを組み、0b10101010を送って、波形を観察してみました。

イメージ 1

 SCLのパルス幅は10usです。速度は約20kHzです。

 ACKは、スレーブから応答があった時は、SDAが0になります。

 大丈夫そうなので、このソフトI2Cと以前に試したシリアル通信を組み合わせて、I2C アドレス スキャナを作ってみました。表示の仕方は、Travel and softwareというサイトを参考にさせていただきました。

 今回は、秋月電子のI2C LCDモジュールAQM0802Aのアドレスを調べてみます。

 回路図です。

イメージ 4

 I2Cバスのプルアップ抵抗は、AQM0802Aモジュールに内蔵されていますので、つけていません。

 AQM0802AのVDDは3.3Vなので、単3電池2本で電源としています。

 SWを押すとscanが始まります。

 ブレッドボードです。

イメージ 2

 スキャン結果は、TeraTermに表示されます。Baudrateは1200bpsです。

 ACKが0の時、アドレスに[ ]がつきます。なお、アドレス00~07と78~7Fはシステムで予約されたアドレスですので、スキャンしません。

イメージ 3

 3Eに[ ]がついています。AQM0802Aのスレーブアドレスは、3Eです。

 実際にアドレスとして送るときには、3Eを左に1ビットシフトし LSBに0 をセットして、7Cを送ります。

 プログラムです。シリアル通信は、送信だけにしています。

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
// CONFIG
#pragma config FOSC = INTRCIO  // 内蔵クロック4MHz
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#define _XTAL_FREQ 4000000

#define TX GPIO0
#define RX GPIO1
#define SW GPIO2
#define SDA GPIO4
#define SCL GPIO5
#define SDA_ON GPIO4 = 1
#define SDA_OFF GPIO4 = 0
#define SCL_ON GPIO5 = 1
#define SCL_OFF GPIO5 = 0
#define SDA_OUT TRISIO4 = 0
#define SDA_IN TRISIO4 = 1
#define SCL_OUT TRISIO5 = 0
#define SCL_IN TRISIO5 = 1
#define wait __delay_us(10)
#define Baudrate 1200
#define OneBitDelay (1000000 / Baudrate)
#define HalfBitDelay (1000000 / Baudrate / 2)
#define start_addr 0b00000111
#define end_addr 0b01111000

void serial_init(){
    TRISIO0 = 0;    //GP0 output
    TRISIO1 = 1;    //GP1 input
    TX = 1;         //アイドル状態でTXpin High
}
void putch(unsigned char byte){
    // Send start bit
    TX = 0;
    __delay_us(OneBitDelay);
    for(unsigned char i=0;i<8;i++){
        if(byte & 0x1){
            TX = 1;
        }else{
            TX = 0;
        }
        __delay_us(OneBitDelay);
        byte >>=1;
    }
    //Send stop bit
    TX = 1;
    __delay_us(OneBitDelay);
}

void I2C_init(){
    SDA_IN;
    SCL_IN;
    SDA_ON;       
    SCL_ON;
    }

void I2C_start(){
    SDA_OUT;
    SCL_OUT;
    SDA_ON;       
    SCL_ON;
    wait;
    SDA_OFF;
    wait;
    SCL_OFF;
}

void I2C_stop(){
    SDA_OFF;
    SCL_OFF;
    wait;
    SCL_ON;
    wait;
    SDA_ON;
    SDA_IN;
    SCL_IN;
}

unsigned char I2C_write(unsigned char byte){
    unsigned char ACK = 0;
    for(unsigned char i=0;i<8;i++){
        SCL_OFF;
        wait;
        if(byte & 0x80){
            SDA_ON;
        }else{
            SDA_OFF;
        }
        byte <<=1;
        wait;
        SCL_ON;
        wait;
        SCL_OFF;
    }
    //Get ACK
    SDA_IN;
    wait;
    SCL_ON;
    wait;
    ACK = SDA;
    SCL_OFF;
    SDA_OUT;
    return ACK;
}

void main() {
    CMCON = 0x07;   //コンパレータを使わない
    ANSEL = 0x00;   //アナログポートを使わない
    TRISIO = 0b00110110;    //GP1,GP2,GP4,GP5 input GP0,GP3 output
    I2C_init();     //I2C初期化
    serial_init();  //シリアル通信初期化
   
    while(SW);  //SWが押されたらscan start
   
    printf("I2C Address Scan\r\n");
   
    for(unsigned char i=0;i<0x7f;i+=0x10){
        for(unsigned char j=0;j<=0xf;j++){
            unsigned char i2c_adr = i+j;
            if(i2c_adr <= start_addr || i2c_adr >= end_addr){
                printf(" -- ");
            }else{
                I2C_start();
                unsigned char acknowledge = I2C_write(i2c_adr<<1);
                I2C_stop();
                if(acknowledge == 0){
                printf("[%02X]",i2c_adr);
                }else{
                printf(" %02X ",i2c_adr);
                }
            }
        }
            printf("\r\n");
    }
   
    while(1){
        }
}


Viewing all articles
Browse latest Browse all 440

Trending Articles