おはようございます。
としぶぅ~です。
ねむい・・・(笑)
週末が近づくと朝がつらくなる・・・・
さて本日は、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^)/