今回のキーパッドi2cスレーブ試作において、結果的に苦労したのはmssp割り込みハンドラのところでした。
以前作ったスレーブに判断分岐追加で始めましたが、結局はマイクロチップ社AN-734のASMサンプルを参考にMSSP_HANDLERを作って、MSSP割り込みを5つのイベントで分岐するようにしました。
// ssp int handling function void ssp_handler(void) { unsigned char s_state,dummy; s_state=SSP1STAT&0b00101101; // SMP,CKE,-D/A,P,-S,-R/W,UA,-BF switch(s_state){ case 0b00001001: // State1 address,S,write,buffer full dummy=SSP1BUF; // if address, read SSPBUF as dummy rcv_count=0; break; case 0b00101001: // State2 data,write,buffer full buffer[rcv_count]=SSP1BUF ; // if((rcv_count&0x1)==0){ // receiving RS byte and DATA byte as pair lcd_rs_rcv=((buffer[rcv_count]>>6)&0x1); // Set lcd_rs bit } else if((buffer[rcv_count]==0x10)&(lcd_rs_rcv==0)) cnt_stop(); else if((buffer[rcv_count]==0x11)&(lcd_rs_rcv==0)) cnt_setup(); else if(DEBUG==0) lcd_write_rs(buffer[rcv_count],lcd_rs_rcv); // Data byte stat[rcv_count]=SSP1STAT; // status buffering rcv_count++; // next buufer break; case 0b00001100: // State3 address,S, read,buffer empty case 0b00001101: // State3 address,S, read,buffer full SSP1CON1bits.CKP=0; // CKP clear dummy=SSP1BUF; // dummy address read SSP1BUF=key_in_p; // key in data transmitting SSP1CON1bits.CKP=1; // CKP releas break; case 0b00101100 // State4 data,S, read,buffer empty SSP1CON1bits.CKP=0; // CKP clear SSP1BUF=key_in_cnt; // key in counter transmitting SSP1CON1bits.CKP=1; // CKP releas break; case 0b00101000: // State5 data,S, read,buffer empty &full case 0b00101101: SSP1CON1bits.CKP=1; // CKP release break; default: lcd_puts("ERR"); break; } }
この関数は割り込み関数の中でMSSP要因判定後(MSSP1IFが有ったら)に入れて各処理に分岐します。
WRITEとREADに別れ、LCD表示の方もすっきりと収容しました。デバッグ用の表示が入ってましたが、割り禁で自前のLCD表示に行くため、次の割り込みが追突します。取っ掛かりの実験で使いましたが、その後は邪魔になりました。最後のバグだと思っていたのはデバッグ用表示の割り込み禁止が原因でした。
MSSPの制御で注意点は、スレーブ受信ではアドレス一致、BUF空きでCKPが自動で0(クロックストレッチモード)になるので、MSSPBUF書き込み後にソフトでCKPを1にすること、送信では、受信したアドレスが入ったMSSPBUFを空読みしてやら無いと次のデータ受信で、オーバーフローになることなどぐらいでしょうか。
それからMSSP以前に良く間違う点は、ackは0でnackが1だというところです。ソースコードに関しては追ってwebに掲載していく予定です。