PIC12F1822でi2cアドレススキャン         nobcha@2012,2013

                        2013.8.4修正

  AQUQTALKというシリアルIOやi2cで制御できるという音声エンジンをi2cバスにつなぎましたが、うんともすんともいいません。アドレスが間違っているんだろうかと、i2cの7ビットアドレス127種を発生し、ack応答を確認するテストプログラムを作ってみました。(実はi2cアドレス7ビットの読み方がMSB詰めで読むか、LSB詰めで読むかでヘキサデシマル表記が1ディジット分違うのでした)

 AQUATALKのアドレス探しの時は丁度デジットで買ったサンライク社のSCG002というi2c接続LCDをつないで実験しておりました。そのため公開したソフトはSCG002対応です。しかし国内で流通しているi2c接続LCDはストロベリーリナックス社LCDと同じインターフェイスが主流のようです。最近秋月から出た8文字×2行のミニLCDもそうです。そちらとの組み合わせでアドレススキャンするチャンスがその後多くなったので追記させていただきます。

 

 マスターとしてはPIC12F1822を使います。スキャン結果をLCDに表示します。i2cインターフェイスのLCDなので、アドレススキャンすると表示用のi2cLCDのアドレスで引っかかります。ソフトがちゃんと動いているのか確認できます。        

 

  回路図は次になります。 AQUATALK(ATP3011F4PU)のアドレスを探したときの回路図です

 その後ストロベリーリナックス社のLCDとか、秋月のAQM0802をつないだ回路で使うチャンスが増えましたので、そちらの場合も紹介しておきます。

 

           

 MAINとi2c接続のLCD制御(デジットで買ったサンライク社SCG002Bを使ってます)とMSSP制御プログラムです。ストロベリーリナックス社のLCDや秋月AQM0802を使う場合のプログラムは備考欄にpdfへのリンクで示しました。

種類 ソースコード 備考
MAINプログラム /*************************************************
MSSP i2c SCAN TEST of PIC12F1822
By nobcha all right reserved
Ver 1. 07/08/2012 for i2c peripheral TEST
PIC12F1822 
PIN Assign #7 RA0:monitor LED
#6 RA1:SCL
#5 RA2:SDA
#3 RA4:SW

OSC INT 8MHz
Development Circumstance
MPLAB IDE V8.73 HiTECH C V9.83
************************************************* */
#define _LEGACY_HEADERS
#define _XTAL_FREQ 8000000
#include <htc.h>
#include "lcd_i2c_mssp.h"
#include "mssp_i2c.h"

__CONFIG( 
FOSC_INTOSC & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF 
& CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF
);
__CONFIG(
WRT_OFF & PLLEN_OFF & STVREN_ON & LVP_OFF
);

// proto
void itostring(char digit, unsigned int data, char *buffer);
void mssp_init(void);
unsigned char i2c_scan(unsigned char);
// display data
unsigned char Msg1[17] = "i2c SCAN test ";
unsigned char Msg2[6] = "ADDR ";
unsigned char Msg3[5] = "ack ";
unsigned char Msg4[4] = " ";

void main(void)
{
unsigned int Count;
unsigned char i;
/* INITIALIZE REGISTER */
OSCCON = 0b01110000; // Set 8MHz
PORTA = 0b00000000; // Clear
TRISA = 0b00011110; // RA1,RA2,RA3,RA4 INPUT
ANSELA = 0b00000000; // All digital
CM1CON0 = 0b00000111; // No using compalator
mssp_init(); // MSSP initialize
Count = 0;
RA0 = 1;
// lcd_init(); // LCD initialize continue
// lcd_init1(); // LCD initialize continue
lcd_init2(); // LCD initialize continue
while(1)
{
__delay_ms(100);
LATA0 ^= 1; // Heart beat
lcd_cmd(0x80); // Move cursor 1st line
lcd_str(Msg1); // Display test message
i=2;
while(i){
lcd_cmd(0xC0); // Move cursor to 2nd line
lcd_str(Msg2); // i2c addr message
itostring(2,i,Msg4);
lcd_str(Msg4); 
if(i2c_scan(i)==0){
lcd_str(Msg3); 
itostring(2,i,Msg4);
lcd_str(Msg4);
while(RA4) ;
__delay_ms(200);
}
i=i+2;
}
for(i=10;i>0;i--){ // 1s waiting
__delay_ms(100);
}
}
}
/***************************************
* Converting 2/4 hex to ASCII
****************************************/
void itostring(char digit, unsigned int data, char *buffer)
{
char i; // digit:2 or 4
buffer += digit; // last data
for(i=digit; i>0; i--) { // 
buffer--; // 
*buffer = (data & 0xF) + '0'; // ASCII code
if(*buffer>0x39) *buffer=*buffer+7;
data = data >> 4; // next hex
}
}
/***************************************
* MSSP initialize
****************************************/
void mssp_init(void){ 
/* SSP1CON1 REGISTERS */
SSPEN = 1; //Enables Serial Port Mode
SSPM3 = 1; /////////
SSPM2 = 0; //I2C Master Mode
SSPM1 = 0; // clock= Fosc/(4*(SSP1ADD+1))
SSPM0 = 0; ////////
/* SSPCON2 REGISTERS */
SSP1CON2 = 0x00;
/* SSPCON3 REGISTERS */
SSP1CON3 = 0x00;

/* SSP1STAT REGISTERS */
SMP = 1; //SPI MASTER MODE
CKE = 1; //SMBus Specific Inputs Enabled
//SSP1ADD = 0x19; //~75kHz
//SSP1ADD = 0x13; //~100kHz
//SSP1ADD = 0x07; //~400kHz
SSP1ADD = 0x50;
}
/***************************************
* i2c address scanning test
****************************************/
unsigned char i2c_scan(unsigned char data){
unsigned char ack_data;
i2c_start(); // start condition
i2c_write(data); // addr & wite mode
ack_data=i2c_readack(); // if ack:0
i2c_stop();
return (ack_data);
}
 ストロベリーリナックス社LCDや秋月AQM0802をつなぐ場合のメイン関数はpdfを見てください。
MSSPでi2c接続するLCD制御 /***********************************************
* LCD表示関数:I2Cインターフェースを呼出し使用
* By nobcha (c)2011
*
* revised for MSSP MASTER mode 06/04/2012 
*
* SUNLIKE社LCD アドレス 0x74
* NXP PCF2119xデータシート参照
*
* パラレル8ビット接続のときの関数に合わせる
* lcd_init(void) ----- 初期化
* lcd_cmd(command) ----- コマンド出力
* lcd_data(byte) ----- 1文字表示
* 文字コードの関係空間で0x80をオアして出力する
* lcd_str(string) ----- 文字列表示
* lcd_clear(void) ----- LCD画面全消去
* lcd_goto(cursor_pos)--- カーソル位置指定
* lcd_cgram(addr,font)--- CGRAMへフォント格納
*
* LCD初期化について試行錯誤したので、不要な関数が
* ついていますが、使うのはlcd_int2()です。
**********************************************/
#define _LEGACY_HEADERS
#include <htc.h>
#include "mssp_i2c.h"
#define LCD_AD 0x74
#define _XTAL_FREQ 8000000
/*******************************
* V LCD 設定
*******************************/
//#define VLCD 8 // Vlcd for 2.46V
//#define VLCD 15 // Vlcd for 3.02V
//#define VLCD 27 // Vlcd for 3.98V
#define VLCD 39 // Vlcd for 4.94V
/*******************************
* LCDへ表示データ1文字出力
*******************************/
void lcd_data(unsigned char data){
i2c_writeto(LCD_AD); // LCDアドレスをOPEN 
i2c_putbyte(0x40); // CO:0(STOP),RS:1 データなので
i2c_putbyte(data | 0x80); // 表示バイトを送る(文字コードは0x80以上)
i2c_stop(); // stop コンディション
}
/*******************************
* 液晶へ1コマンド出力 
*******************************/
void lcd_cmd(unsigned char cmd){
i2c_writeto(LCD_AD); // LCDアドレスをOPEN
i2c_putbyte(0x00); // CO:0(STOP),RS:0 コマンドです
i2c_putbyte(cmd); // コマンドバイトを送る
i2c_stop(); // stop
if((cmd == 0x01)||(cmd == 0x02)) // ClearかHomeかで待ち時間調整 
__delay_ms(2); // Clearなら応答時間は2msec待ち
else
__delay_us(40); // それ以外コマンドなら50μsec待ち 
}

/*******************************
* 液晶画面出力カーソル位置指定
*******************************/
void lcd_goto(unsigned char cursor){ // カーソルアドレスは00〜0F,40〜4F
lcd_cmd(0x80 | cursor ); // DRAMアドレス設定#7:1にして7ビット
}
/*******************************
* LCD初期化処理
*******************************/
void lcd_init(void) { // PCF2119マニュアル掲載お約束
__delay_ms(100); // 100mS delay 電源安定まで待つ
lcd_cmd(0x30); // 8bit 2line Normal mode
__delay_ms(100); // 100mS delay 安定まで待つ
lcd_cmd(0x30); // 8bit mode 
__delay_ms(40); // 40mS delay 安定まで待つ
lcd_cmd(0x30); // 8bit mode
lcd_cmd(0x08); // display off
lcd_cmd(0x35); // 8 bits mode 2 lines 16 chs 拡張コマンド
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち

// lcd_cmd(0x42); // voltage multi
// lcd_cmd(0x80|VLCD); // Vlcd Va Set
// lcd_cmd(0xC0|VLCD); // Vlcd Vb Set
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
lcd_cmd(0x34); // increment,shift
lcd_cmd(0x01); // display clear
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
lcd_cmd(0x34); // increment,shift
lcd_cmd(0x0E); // DISP on, Cursor on
lcd_cmd(0x06); // Entry 
}
/*******************************
* LCD初期化処理 Vlcd未対応
*******************************/
void lcd_init1(void) { // PCF2119マニュアル掲載お約束
__delay_ms(100); // 100mS delay 電源安定まで待つ
lcd_cmd(0x30); // 8bit 2line Normal mode
__delay_ms(100); // 100mS delay 安定まで待つ
lcd_cmd(0x30); // 8bit mode 
__delay_ms(40); // 40mS delay 安定まで待つ
lcd_cmd(0x30); // 8bit mode
lcd_cmd(0x34); // 8 bits mode 2 lines 16 characters
lcd_cmd(0x01); // display clear
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
lcd_cmd(0x34); // increment,shift
lcd_cmd(0x0E); // DISP on, Cursor on
lcd_cmd(0x06); // Entry 
}
/*******************************
* LCD初期化処理 連続バイト
*******************************/
void lcd_init2(void) { // PCF2119マニュアル掲載お約束 
__delay_ms(100); // 100mS delay 電源安定まで待つ 
lcd_cmd(0x30); // 8bit long IF
__delay_ms(5); // 5mS delay
lcd_cmd(0x30); // 8bit
__delay_ms(5); // 5mS delay
lcd_cmd(0x30); // 8bit
__delay_us(40); // 40uS delay
i2c_writeto(LCD_AD); // LCDアドレスをOPEN
i2c_putbyte(0x00); // CO:0(STOP),RS:0 コマンドです
i2c_putbyte(0x35); // FUNCTION_set 8bit M:1:2line H:0
i2c_putbyte(0x41); // voltage multi
i2c_putbyte(0x80|VLCD); // Vlcd Va Set
i2c_putbyte(0xC0|VLCD); // Vlcd Vb Set
i2c_putbyte(0x34); // FUNCTION_set 8bit M:1:2line H:0
i2c_stop(); // stop
lcd_cmd(0x01); // Clear display
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
__delay_ms(100); // 100mS待ち
lcd_cmd(0x0F); // DISP on, Cursor on
lcd_cmd(0x06); // Entry mode I_D:1 S:0
}
/******************************
* LCD画面全消去
******************************/
void lcd_clear(void) {
lcd_cmd(0x01); //初期化コマンド0x01出力

/******************************
* 文字列出力
******************************/
void lcd_str(char* ptr) {
while(*ptr != 0){ // 0x00があるまで文字取り出し 
lcd_data(*ptr++); } // 文字表示して、次の文字へ
}
/******************************
* CGRAMへ外部フォントを格納
******************************/
lcd_cgram(unsigned char addr, char* font){
unsigned char i;
i2c_start(); // i2c start
i2c_write(0x74); // i2c addr
i2c_write(0); // Function set CO:0,RS:0,
i2c_write(0x24); // 2 lines 16 chars 1/18 duty ext com
i2c_write(addr); // set cgram addr
i2c_start(); // Restart condition
i2c_write(0x74); // i2c addr
i2c_write(0x40); // next byte is data
for (i=0;i<8;i++){ // 5 bits 8 rows
i2c_write(*font++); // set cgram addr
}
i2c_stop();
}
  ストロベリーリナックス社LCDや秋月AQM0802をつなぐ場合のLCD制御関数はpdfを見てください。ヘッダファイルはこちらです。
 i2c液晶制御だけでなく、キー入力サポートをオプション追加した改造試作で使用した関数を流用しておりますので、不要なキー入力制御部がくっついています。
MSSP使用i2c制御マスター #define _LEGACY_HEADERS
#include <htc.h>
#include "mssp_i2c.h"
#define TRUE 0x0;
#define FALSE 0x1;
/**************************************************
* MSSP使用マスターモード専用I2C関数 
* 教育・ホビー用、営利目的・商用への利用は禁止
* 詳しいタイミングはNXPの資料やPICドキュメント
* 参照のこと
**************************************************
*/
/*
* msspはSDAとSCL信号をスタート状態にします
* 衝突有るとMSSPはリセットされる
*/
void i2c_start(void){
SEN = 1; // SSPCON2:0 initiate I2C START condition
while (SEN == 1); // wait until START bit finishes
}
/*
* msspはSDAとSCL信号をRESTART状態にします
* 衝突有るとBCL1IFが立つ
*/
void i2c_restart( void) {
RSEN = 1; // SSP1CON2:1 Repeated Start
while (RSEN==1);
}
/* 関数の説明
* DATAをSSP1BUFに書きスレーブに転送かける
* 転送中はR_nWが1になっている
*/
void i2c_write( unsigned char DataByte ){
SSP1BUF = DataByte;
while (R_nW == 1);
}
/* 関数の説明
* 受信可にしてDATAを待つ。
* RSEN0になったら、SSP1BUFのデータを読み持って返る
*/
unsigned char i2c_read( void) {
RCEN = 1; // SSP1CON2:3 Receive enable
while (RCEN == 1);
return SSP1BUF;
}
/* 関数の説明
* msspはSDAとSCL信号をstop状態にします
* PENが0になったら、かえる。衝突あるとBCL1IFが立つ
*/
void i2c_stop( void) {
PEN = 1; // SSP1CON2:2 initiate I2C STOP condition
while (PEN);
}
/* 関数の説明
* ACK(ACKDT:0)かNACK(ACKDR:1)を送る
* ACKENしたらかえる。
*/
void i2c_sendack(unsigned char status) {
ACKDT = status; // SSPCON2:5 set to ACK:0,NACK:1
ACKEN = 1; // SSPCON2:4 initiate I2C ACK condition
while ( ACKEN); // wait until ACK sequence is over
}
/* 関数の説明
* ACK(ACKDT:0)かNACK(ACKDR:1)をチェックする
* ACK(ACKSTAT:0)かNACK(ACKSTAT:1)でかえる。
*/
unsigned char i2c_readack(void) {
if (ACKSTAT == 0) {
return 0; // ACK detected
} else {
return 1; // ACK not detected
}
}
/* 関数の説明
* 指定アドレスにWRITEモードでアドレスを書く
* ACK有ればTRUEで、無ければFALSEでかえる
*/
unsigned char i2c_writeto(unsigned char address){
i2c_start();
i2c_write(address | 0x0);
if(i2c_readack()) return TRUE;
return FALSE;
}
/* 関数の説明
* 指定アドレスにREADモードでアドレスを書く
* ACK有ればTRUEで、無ければFALSEでかえる
*/
unsigned char i2c_readfrom(unsigned char address){
i2c_start();
i2c_write(address | 0x1);
if(i2c_readack()) return TRUE;
return FALSE;
}
  ストロベリーリナックス社LCDや秋月AQM0802をつなぐ場合のi2c関数はpdfを見てください。
ヘッダファイル #define _LEGACY_HEADERS
#define _I2C_H_
#define i2c_putbyte(data) i2c_write(data)
/***************************************
* Simple i2c master using MSSP
* for new extended PIC12/16 series
* 09/25/2011
* by nobcha all right reserved
***************************************   
*/
void i2c_init(void);
void i2c_start(void);
void i2c_restart(void);
void i2c_write(char);
void i2c_stop(void);
void i2c_wait(void);
unsigned char i2c_writeto(unsigned char);
unsigned char i2c_readfrom(unsigned char);
void i2c_sendack(unsigned char status);
unsigned char i2c_readack(void);
  ストロベリーリナックス社LCDや秋月AQM0802をつなぐ場合のヘッダはpdfを見てください。

 

 まずはLCDだけを接続して実験。当然ながら、LCDのアドレス0x74を検知します。

  

 続いてアドレス不詳のAQUATALKを接続しました。

  

 0x5Cとでました。説明書には0x2Eとあります。1ビットずれてる。アルディーノの方では7ビットアドレスということで、0x2Eと表記するそうです。PICの世界ではデータバッファに入れる時のビット配列でLSBがR/Wビットなので、0x5Cと表記してます。うーーん、何かだまされた感じでした。とはいえ、このアドレススキャンプログラムはお役に立ちました。

 

   開発はMicrochip社の開発環境を利用しました。MPLAB V8.73a, HI-TEC C PRO LITE V9.83(9.82以前はバグあります),PICKIT3を使っております。回路図は水魚堂のBSchを利用しました。提供元、開発者の方に感謝します。

 本試作実験はnobchaの趣味の活動で実施しております。再現性や安全性に関して保障はできません。また本資料を初めとしてプログラムなどの創作物には著作権が有りますので、丸のままコピー引用は認められません。

 

 ホームページ目次 i2c一覧へ nobchaの電子回路日記ブログ

inserted by FC2 system