こんにちは、ENGかぴです。
PIC16F1827はI2C(MSSP)通信機能を持っており温湿度センサーであるSHT35-DISから測定データを取得することができます。MCCによるI2C通信の実装例としてSHT35-DISからデータを取得しLCDに温湿度を表示しました。
温湿度センサーはSHT35-DISモジュール(秋月電子)を使用し、LCDはAQM1602XA-RN-GBW(秋月電子)を使用しています。
PIC16F1827で動作確認したことについてリンクをまとめています。
PICマイコン(PIC16F1827)で実現できる機能と解説リンクまとめ
SHT35-DISのデータを取得する
SHT35-DISはSENSIRION社の高精度温湿度センサーです。マイコンとの通信方式はI2Cであり測定レンジが-40℃から+125℃と広いのが特徴です。PICマイコンからコマンドを送信しSHT35-DISからデータを取得する方法をまとめます。
PIC16F1827の設定はMCCを使っています。MCCの使い方については下記記事にまとめています。
MPLAB Code Configurator(MCC)の追加と使い方
今回はMCCを使用してMSSP1、MSSP2及びTMR0の設定を行っています。
System Moduleの設定
最初に共通事項であるSystem Moduleの設定を行います。MPLAB X IDEを起動しMCCのアイコンをクリックしてMCCを有効にします。

内部クロックを使用するためINTOSCを選択しています。クロック周波数は任意でもよいですが4MHz_HFを選択しています。クロックを高速にするほど消費電流が増えてしまいます。他にも設定項目はありますがクロックの設定のみとしています。
PR:スキマ時間で自己啓発!スマホで学べる人気のオンライン資格講座【スタディング】まずは気になる講座を無料で体験しよう!
I2C通信を実装する
I2C通信をMCCで実装しLCDに表示する方法については下記記事を参考にしてください。今回はMSSP2にSHT35-DIS用のI2Cを追加します。
PICマイコン(PIC16F1827)のI2C通信を実装する
PICマイコンのI2C通信はMSSP機能に含まれています。Device Resources内のPeripherals欄のMSSP2を選択して追加します。

MSSP2を選択しSerial ProtocolをI2Cを選択するとModeやClockの設定画面が表示されます。PICマイコンがSHT35-DISに対してコマンドを送信するためMasterとなります。通信速度は初期値の100kHzとします。
PR:(即戦力のスキルを身に着ける:DMM WEBCAMP 学習コース(はじめてのプログラミングコース))
TMR0で測定タイミングを設定
TMR0はDevice Resources内のPeripherals欄のTimerを選択しTMR0をクリックして追加します。

Timer Clock内でクロックに関する設定を行います。Clock Sourceは内部クロックを使用しているためFOSC(FOSC/4)を指定します。PrescalerはClock Sourceに対してTMR0のカウントアップする分周比を指定します。
Timer PeriodはTMR0がオーバーフローするタイミングを設定します。1ms毎にオーバーフロー割り込みが発生しますがCallback Function Rateを0x0A(10)を指定しているため10ms毎にコールバック関数が呼び出されます。
void mainTimer(void); //タイマー0割り込みのコールバック関数
//コールバック関数の使用例
TMR0_SetInterruptHandler(mainTimer); //コールバック関数を指定
上記例ではmainTimer()が10ms毎にコールされます。
コマンドを送信する

SHT35-DISはコマンドを16ビット長になるように送信(Write)する必要があります。MCCの関数I2C2WriteNByte()を使用してコマンドを送信します。
#define SLAVE_ADRS 0x45 //ADRオープン時のアドレス
uint8_t singleshot[2] = { 0x2C, 0x06}; //シングルショットモードでクロックストレッチ有効
I2C2_WriteNBytes(SLAVE_ADRS, &singleshot[0], sizeof(singleshot)); //コマンドを送信
シングルショットモード(繰り返し精度レベル:高)をクロックストレッチを有効にする場合は0x2c06がコマンドになります。
クロックストレッチを有効にすると測定中にSCLの信号レベルがLOWに維持されるためSCLがHighに復帰するタイミングで測定が完了したことが確認できます。
I2C2_WriteNBytes()の第1引数にスレーブのアドレス、第2引数に送信する値を格納しているアドレス、第3引数に送信するサイズを指定します。
測定データを取得する
uint8_t rxdata[6];
I2C2_ReadNBytes(SLAVE_ADRS, &rxdata[0], sizeof(rxdata) ); //測定データをリードする
MCCの関数I2C2_ReadNBytes()を使用して測定データを取得します。I2C2_ReadNBytes()の第1引数にスレーブのアドレス、第2引数に受信した測定データを格納するアドレス、第3引数に受信したいデータサイズを指定します。
温度データ16ビットと温度データのCRC、湿度データ16ビットと湿度データのCRCの合計6バイトを受信します。CRC計算の条件がデータシートに記載されています。

/* CRC8計算関数 */
uint8_t Crc8Calc(uint8_t *data, uint8_t sz ){
uint8_t crc = 0xFF;
uint8_t i,j;
for( i = 0; i < sz; i++){
crc ^= *data;
for( j = 0; j < 8; j++ ){
if( crc & 0x80 ){
crc = ( crc << 1 ) ^ POLYNOMIAL;
}
else{
crc = crc << 1;
}
}
++data;
}
return crc;
}
CRC8の計算方法は初期値と1バイト目のバイトデータのXORを計算します。この値を8ビット分左にシフトしていきますが、最上位ビットが立った時に1ビット分シフトしてからPolynomialとXORをとります。
2バイト目以降は前のバイトの結果を初期値として8ビット分シフトとXORを繰り返していき対象のデータのバイト数だけ繰り返します。
SHT35-DISから受信した測定データのCRCの計算結果と取得したCRCの結果を比較して一致したとき有効なデータとして採用します。
PR:
わからないを放置せず、あなたにあったスキルを身に着けるコツを教える テックジムPython入門講座の申込
測定データの換算
SHT35-DISから受信した測定データは16ビットの符号なしの整数型の数値ですが温湿度に換算する必要があります。測定データの換算方法はデータシートに記載されています。

換算式を見ると小数点以下が発生するためfloatを使用したり小数点以下を商で表すために100倍値を使用したりすることが必要です。例ではFLOATを使用する場合と100倍値を使用した場合の2通りを示しています。
uint16_t tempHex;
uint16_t humiHex;
tempHex = ((uint16_t)rxdata[0] << 8) | rxdata[1];
humiHex =((uint16_t)rxdata[3] << 8) | rxdata[4];
#ifdef FLOAT_ENABLE
temp = (tempHex / 65535.00) * 175 - 45;
humi = (humiHex / 65535.0) * 100.0;
#else
//floatの場合処理が重たいので以下で代用
//65535でなく65536で割っているため誤差がでるが
//処理速度優先のためシフト演算とした。
temp = ((uint32_t)tempHex*175*100 >> 16 ) - 45*100;
humi = ((uint32_t)humiHex*100*100 >> 16 );
#endif
PIC16F1827は演算器を持っていないためfloatの処理を行うとプログラム領域を多く使用してしまい処理が重たくなってしまいます。処理を軽くするためにシフト演算による計算を行っています。また小数点以下の2桁以下がシフトしたときに桁落ちしたいようにあらかじめ100倍値を取っています。
正確な温湿度を取得したい場合はお勧めできませんが室温を測定する場合は微々たる誤差であるため問題ないと思います。
【クリエイターズファクトリー】卒業がない!挫折する心配なし!Webスクール説明会申し込み
動作確認
PIC16F1827とLCD、SHT35-DISをI2C通信接続して動作確認を行います。SHT35-DISからデータを取得したデータをLCDに表示します。
動作確認用の回路

I2C通信にはプルアップ抵抗が必要ですがLCDやSHT35モジュールにはプルアップ抵抗が実装されています。電源を投入すると初期値として温度と湿度の値として00.00を表示します。5秒毎にSHT35-DISからデータを取得しLCDに温湿度を表示します。
電源投入時にLCDの動作が安定しないことがあるためLCDの初期化を行う前に安定時間確保のためウェイトを置いています。ピン設定は以下の通りです。

今回はIC2を2つ使用していますが、スレーブアドレスが異なればお互いに干渉しないため配線を共通化しても問題ありません。共通化する際にはプルアップ抵抗について一方を使用しないようにするかなど検討が必要です。
動作結果

電源を投入から測定開始するまでに00.00を表示していますが、5秒後に温度と湿度がLCDに表示できていることを確認しました。
ソースコード全体
ソースコードは記事作成時点において動作確認できていますが、使用しているライブラリの更新により動作が保証できなくなる可能性があります。また、ソースコードを使用したことによって生じた不利益などの一切の責任を負いかねます。参考資料としてお使いください。
リンクからZIPファイル形式のファイルをダウンロードし、任意の場所に展開していただくとテキストファイルが生成されます。
main.cをコピーすると使用できます。本ソースコードはMPLAB X IDEにMCCのプラグインをインストールしていることが前提となります。MCCをインストールする方法は下記記事を参考にしてください。
MPLAB Code Configurator(MCC)の追加と使い方
関連リンク
PICマイコンを使ってマイコンのレジスタの設定やMPLAB X IDEのプラグインであるMCCを使用して動作確認したことについてまとめています。
PICマイコン(PIC12F675)で実現できる機能と解説リンクまとめ
PICマイコン(PIC16F1827)で実現できる機能と解説リンクまとめ
PR:無料トライアル実施中【PC専用】AIスライド資料作成ツールの利用:イルシル
最後まで、読んでいただきありがとうございました。
温度は室温計とほぼ同じであり湿度は雨天だったので妥当かなと感じています。換算式はシフト演算で行っているため誤差がありますが室温計とほぼ同じ値であったため問題にならない誤差だと感じています。