としぶぅ~の「工作部屋」...毎日少しのお勉強

趣味・関心事を書いていこうと思います。

PIC16F690を動かす。。。その14(I2C-PCA9536)

2013-04-18 05:58:26 | PIC16F690

おはようございます。

としぶぅ~です。

 

ねむい・・・(笑)

週末が近づくと朝がつらくなる・・・・

 

さて本日は、PCA9536へのI2Cのデータ波形を一応確認しておこうと思います。

といっても取ったデータを貼り付けるだけですが・・・

上記は、1秒ごとにPIC16F690 → PCA9536に転送しているデータの状況です。

上位1バイト目は、アドレス0x82+R/Wnです。

2バイト目は、コマンド情報で0x01=outdata command

3バイト目は、出力用のデータ 0x01 → 0x02 → 0x04 → 0x08 (4bitなので)

となっています。

IC2のフォーマット

スタートビット - データ - ACK(入力) - データ - ACK(入力) -・・・・ACK(入力) - ストップビット

という感じになっています。(問題なさそうです。)

とりあえずソース貼り付けておきましょうか・・・

I2C用の関数

こちらはポートでI2Cのデータを作っています。

(PIC16F690にはI2Cのマスター用のペリフェラルはないので・・・手作業です(笑))

#include <htc.h>
#include "delay.h"

void I2C_DELAY();
void I2C_DELAY_DT();
void i2c_stop();
//void i2c_out(unsigned char out_data);


//i2cの初期化
void i2cinit(unsigned char i2cmode)
{

/*************************************************
SPIモード
spimode = 0000 :spi-master-mode OSC/4
spimode = 0001 :spi-master-mode OSC/16
spimode = 0010 :spi-master-mode OSC/64
spimode = 0011 :spi-master-mode TMR2 output/2
spimode = 0010 :spi-slave-mode SSpin Disable
spimode = 0010 :spi-slave-mode SSpin Enable
**************************************************/

unsigned char i2cmode0;

i2cmode0=(SSPCON & 0xf0) | i2cmode;
SSPCON=i2cmode0;
// SSPM=i2cmode; //I2Cモードの設定
CKP=1; //送信up-受信down
SMP=0; //I2C mode:clear
CKE=0; //I2C mode:clear
D_nA=0; //I2C mode:(0:ADDRESS/1:DATA)
R_nW=0; //I2C mode:(0:write/1:read)
P=0; //I2C mode:STOP bit(0:not detected/1:detect)
S=0; //I2C mode:START bit(0:not detected/1:detect)

TRISB4=0; //RB4/SDA:output select
TRISB6=0; //RB1/SCL:output select

//initialize Start bit
RB4=1; //RB4/SDA
RB6=1; //RB1/SCL

SSPEN=1; //SPI port enable
SSPIE=1; //SSP Interrupt enable
SSPIF=0; //SSP Interrupt status

}

//I2C start bit output
void i2c_start()
{
TRISB4=1; //RB4/SDA _|
DelayUs(10);
TRISB6=1; //RB1/SCL _|

DelayUs(10);

TRISB4=0; //RB4/SDA |_
DelayUs(10);
TRISB6=0; //RB1/SCL |_
DelayUs(10);
}

//I2C stop bit output
void i2c_stop()
{
TRISB6=0; //RB4/SDA _|
DelayUs(10);
TRISB6=0; //RB1/SCL _|

DelayUs(10);

TRISB6=1; //RB4/SDA |_
DelayUs(10);
TRISB4=1; //RB1/SCL |_
DelayUs(10);
}


//I2C data 1バイト送信
void i2c_8bit_out(unsigned char out_data)
{
unsigned char dtcnt,point;
unsigned char data;
unsigned char outdata;

outdata=out_data;
point=0x80;
data=0;
dtcnt=8;

while(dtcnt!=0)
{
dtcnt--;
if(outdata & point){
data=1;
}else data=0;
point=point >> 1;

//bit7
TRISB4=data; //RB4/SDA **
DelayUs(10);
//CLOCK
TRISB6=1; //RB1/SCL _|
DelayUs(20);
TRISB6=0; //RB1/SCL |_
DelayUs(10);
}
//ACC CLOCK
DelayUs(20);
TRISB6=1; //RB1/SCL _|
DelayUs(20);
TRISB6=0; //RB1/SCL |_
DelayUs(10);
}

そしてmainでつかっている。。。。PCA9536用の関数

ここはPCA9536ように上記のI2C関数をまとめています。

void i2c_data_o(unsigned char out_data)
{
i2c_start();
i2c_8bit_out(0x82);
while(!I2C_ACK){I2C_ACK=0;}
i2c_8bit_out(0x01);
while(!I2C_ACK){I2C_ACK=0;}
i2c_8bit_out(out_data);
i2c_stop();
}

void i2c_pol_o(unsigned char out_data)
{
i2c_start();
i2c_8bit_out(0x82);
while(!I2C_ACK){I2C_ACK=0;}
i2c_8bit_out(0x02);
while(!I2C_ACK){I2C_ACK=0;}
i2c_8bit_out(out_data);
i2c_stop();
}

void i2c_comfig_o(unsigned char out_data)
{
i2c_start();
i2c_8bit_out(0x82);
while(!I2C_ACK){I2C_ACK=0;}
i2c_8bit_out(0x03);
while(!I2C_ACK){I2C_ACK=0;}
i2c_8bit_out(out_data);
i2c_stop();
}

そして、本プログラム

void main( void )
{
unsigned char i;
unsigned char time_H,time_L;
unsigned char time_cnt;
unsigned char time_cnt_H;
unsigned char plus,tst;
unsigned char cnt_LED;

IoInit(); // I/Oポートの初期化
Tmr1Init(); // タイマ1の初期化

//タイマ周期が1/100秒になるように、初期化する
TMR1H=TMR1H_INIT;
TMR1L=TMR1L_INIT;
//時間のカウンタの初期化
tmr_100ms = 0;
tmr_1s = 0;
shift_tmr_l=0;
LED1=0;
//タイマ1を開始する
TMR1ON=1;
cnt_LED=1;

SSPIF=0;
I2C_ACK=0;
//I2Cモードイニシャライズ
i2cinit(i2cmode);
i2c_comfig_o(0xf0); //全out設定
i2c_pol_o(0x00); //plarity:nomal


//無限ループ
while(1){

if(tmr_1s==1){
tmr_1s = 0;
cnt_LED = cnt_LED << 1;
if(cnt_LED>9){
cnt_LED = 1;
}
i2c_data_o(cnt_LED);
}
}

}

ま、たいした事してないんですが、これで動いてますよ・・・・という参考に・・・

タイマー部分は以前のソースを探してみてください。。。。変えてませんので。。。

でも、あれですね。。。割り込みの部分かえてるか・・・^^;

はっときます。

//割り込み関数
//1/100秒の、タイマのオーバーフロー割り込みで、計測値のインクリメントと、スイッチの確認を行う
void interrupt f_int( void )
{

// plus0 = 0;

//タイマ割り込みかどうかをチェックして、タイマ割り込み以外の場合は、処理をしない
if(TMR1IF) {
//タイマの値を再設定し、次の割り込みが1/100秒後に発生するように設定する
TMR1H = TMR1H_INIT;
TMR1L = TMR1L_INIT;
TMR1IF=0; //タイマ1の割り込みフラグをクリアする


shift_tmr_l++; //1/100秒ごとのカウンタをインクリメント
if(shift_tmr_l>=100){
shift_tmr_l=0;
tmr_100ms=1;
}
tmr_100ms++; //0.1秒ごとのカウンタをインクリメント
if(tmr_100ms>=100){
tmr_100ms=0;
tmr_1s=1;
if(test_bit(PORTA,2)){
clear_bit(PORTA,2);
LED1=1;
}else{
set_bit(PORTA,2);
LED1=0;
}
}

}
if(SSPIF) {
SSPIF=0;
I2C_ACK=1;
}
}

上記の赤い文字の部分が追加になった部分。

ACKの取り込み部分ですね・・・・

ま、とりあえずこんな感じです。

(あくまでも参考ということで・・・・)

 

今日も時間になりました・・・・早い・・・

 

では今日はこの辺で。。。みなさまよい一日を(^o^)/

 


最新の画像もっと見る