goo blog サービス終了のお知らせ 

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

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

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^)/

 


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

2013-04-17 05:56:30 | PIC16F690

おはようございます。

としぶぅ~です。

 

今日も昨日のつづき!

一応1msごとにIO出力をシフトさせて動作チェックしました。

昨日はオシロで見ると1ch以外振らない・・・・・(振幅が出ていない・・・)確認しました。

どうもプローブの設定がおかしかった・・・

ちゃんと振るようになりました。

大丈夫なようです。(下記参照)

とりあえずチェック用に作った回路を添付しておきます。

最初、SDAとSCKのラインにプルアップがついていなくて全く動かなくて・・・・・・(^^;

ここは必要ですのでしっかり覚えておかねば(笑)

 

このPCA9536というI2Cエクスパンダーは、4bitの小型ですが、以前使用したPCF8574とは少し違っています。

ちゃんと

IOをどういう使い方をするのか?という設定がレジスタで設定するようになっています。

だから、アドレス+コマンド+データという3バイト構成で出力します。

PCF8574を少しさわれば簡単に応用が効きました。。。少しずついままでやったてきたことが実を実らせていましたか?

PCA9536でLEDをつけられるように基板化しようかな。。。。

でLCDユニットと共存させてみよう!

 

さて、時間が来ました。。。。

明日はコード(ソフト)を見直して添付しようかな。。。

 

I2Cのユニットは数珠繋ぎにできるので、アドレスさえぶつからなければどんどんふやせるかな・・・・・

PCA9536はLED・・・・・その後は、PCF8574でキー入力ユニットでも入れますかね。。。

ま、どんどん拡張できそうです。

 

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

 

 

 

 

 

 

 


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

2013-04-16 06:06:50 | PIC16F690

おはようございます。

としぶぅ~です。

 

暖かくなりましたね~

ふとんけって寝てしまってます(笑)

 

今日はちょう久しぶりにPIC16F690をさわりました。。。。

朝からPCA9536を半田ずけしてプレッドボードで使えるようにして。。。。依然作りましたPCF8574を使った

I2CインターフェースのLCDユニットコントロール用のプログラムをちょこっといじってI2Cプログラムを作ってみました。

PCA9536は4ポートあるので、1秒おきにビットをシフトさせて出力すれば簡単に動いているかは見れるかな??

ということでちょっと出力さわってやってみました。

一応プログラムは動いているようです。

ポートを見ると。。。。プログラムどおり4msごとにちゃんとポートがずれていっています。

ただ。。。。1個のポート以外は”H"まで持ち上がらない・・・・なぜだ・・・といっている間に時間がなくなってしまった。。。。残念!

つづきはまた明日にするかな・・・・

 

時間が足りないですね。。。。ま、じょじょに!

 

それでは今日はこの辺で・・・・・

今日もよい一日を~(-o-)/

 

 

 


PIC16F690を動かす。。。その11(I2C-LCDモジュール)

2013-03-15 05:15:31 | PIC16F690

おはようございます。

としぶぅ~です。

 

今日は少し冷えますね・・・風邪引かないように気つけないと・・・・

さて本日は。。。。

 

昨日、一度LCDに表示が出たけどまたでなくなった・・・・という状況をみて、Delayはちゃんと動いているのか?

外部クロックにしたし。。。。時間がずれている?

とか疑いがわいたのでとりあえず、Delayの関数を使って時間がちゃんと合うように調整しました。

main.cで

    //無限ループ
    while(1){
        clear_bit(PORTB,5);
    DelayMs(15);
        set_bit(PORTB,5);
    DelayMs(15);
        }

こんな感じで”DelayMs()”関数を仕込んでポートをオシロであたりました。

DelayUs()を使用した場合、50を入力すると、大体75uSくらいになります。。。。uSだとかなり誤差でます。。。

Msだとどうか・・・・

DelayMs(1)で1msを見込みますが・・・・1.5mSくらいになってしまう。。。。ずれが大きい!

で、Delay.c内を少しさわって調整!!

DelayMs(unsigned char cnt)
{
#if    XTAL_FREQ
    do {
        DelayUs(996);
    } while(--cnt);
#endif

#if    XTAL_FREQ > 2MHZ    
    unsigned char    i;
    do {
        i = 4;
        do {
            DelayUs(175);   ←ここを変更して調整!!250←175に
        } while(--i);
    } while(--cnt);
#endif
}

上記を修正しました。

10,15といれてみましたが、とりあえず10msと15msが出ているようです。

 

時間調整はとりあえずOKです。

 

さて。。。。いよいよ本題!

LCDをさわります。

 

何をさわったかというと、LCDのマニュアルをよんでいると。。。。!?

ん???

このやりかた?

今までよく動作していたな??

というところを発見!

イニシャライズの手順がプログラムと違う(^^;

早速変更。。。。。結構違っているので手間がかかりました。。。。

修正すると!

「でたっ!」

なんと・・・・初期化の手順が違っていた・・・・・でも今まで違ったまま表示がでていたのか(笑)

ま、これで現状のプログラムを基本プログラムにします。

いいですね。。。。I2C制御のLCDモジュールが完成です!!

ちょっと表示が遅いかな。。。。I2Cの関数をもう少し調整しなければ・・・・

 

ま、モジュール化完了!!

 

かな~り時間がかかってしまいましたが。。。。なんとかこぎつけました!

さて。。。次は。。。。ジャイロモジュールでもさわってみますかね

 

今日はこの辺で・・・・それではまた(^o^)

みなさま本日もよい一日を~

 

 


PIC16F690を動かす。。。その10(I2C-LCDモジュール)

2013-03-14 06:11:27 | PIC16F690

おはようございます。

としぶぅ~です。

 

昨日は暑かった・・・・今日はまた寒くなるようです^^;

 

さて・・・本日は、

LCDの表示をやっています。

昨日の夜、LCDモジュールに表示が「でた!」

でーきーたー!!

と喜んでROM化したら表示が出なくなった・・・・^^;

デバッグ中は出たんですけどね・・・

いろいろさわりましたが。。。未だ復帰せず。

なんかが不安定ですね・・・・・・

現在こんな感じ

LCDの”E"と”RS"信号はこんな感じ・・・

I2Cエクスパンダはちゃんと動いていそうですね。。。。

(ポートが変化している・・・・)

やったことは、DELAY時間をいろいろさわってみました。

 

いまいちですね。。。。変な文字が表示されることも・・・・

外部クロックを使っているのでDELAY関数が全然あっていないのかな・・・

今晩?明日の朝?・・・・

その辺さわってみようと思います・・・・今日ももうこんな時間。。。仕事行く準備しないと。。。

今日はこの辺にします。

 

それでは皆さま今日も一日よい一日を~(^o^)