AM2302温湿度センサー
通信タイミング

湿度、温度ともに16ビットデータ。小数点1桁を含む値が実データ。送信データは10倍されて、すべて整数になっている。

シリアルバスは、5Vでプルアップされている。マイコンがバスラインをLowにさげると通信開始。条件は、1ms以上、Lowを保持すること。そのあとは、即座に、IOディレクションを入力に変更して、バスラインを開放する。

レスポンスタイミングの80usは、計測していない。データの整合性は、すべてパリティチェックで行う。ここでは、
LOWからHighに移行することだけを確認するにとどめても、問題ない。


データ取得部で、ビットデータを受信するには、ビットデータのHigh時間を計測する。Low時間は、”0”と”1”でおなじ、50usなので、LowからHigh変わった瞬間から計測開始し、Lowに落ちたら計測を終了する。計測時間が一定以上の長さなら、そのビットデータは”1”。それ以外は、”0”としてデータを格納していく。Whileループの中で、カウンタをインクリメントして計測する。
<略>
while(!AM2302_SDA_BIT);//Lowであれば待機
while(AM2302_SDA_BIT)//Highであるならば、計測カウント中。
{//High時間の計測
__delay_us(3);
timeUpCnt++;
if(timeUpCnt >=20) return AM2302_EROOR_NG2;//長すぎるとエラー
}
//一定時間以上Highを持続していた場合はビットデータは1
if(timeUpCnt>=10)//要:オシロスコープで確認調整。
{
AM2302.Data[num]|=0x01;
}
<略>
AM2302ドライバーコード
IOピンのdefine定義を変えれば、他のピックマイコンにすぐに移植できます。
AM2302.h
//-------------------
//AM2302 Temperature and humidity module driver
//AM2302.h
//2025.11.07
//-------------------
#define High 1 //pin level
#define Low 0 //pin level
//error code
#define AM2302_EROOR_TUP0 0x40
#define AM2302_EROOR_TUP1 0x41
#define AM2302_EROOR_TUP2 0x42
#define AM2302_EROOR_NG0 0x30
#define AM2302_EROOR_NG1 0x31
#define AM2302_EROOR_NG2 0x32
#define AM2302_EROOR_NG3 0x33
//ack code
#define AM2302_ACK 0x11
//IO direction setting
#define AM2302_SET_TRISX TRISA
//IOpin assignment IOpin指定
#define AM2302_SDA_BIT RA3 //RA3
//AM2302 receiving bit maximum number
#define AM2302_MAXBITNUM 40
//AM2302構造体メンバ宣言
typedef struct
{
unsigned char Data[5];//受信生データreceived data
unsigned int val[4]; //計算バッファcalculation buffer
unsigned char humi[2];//湿度データhumidity data
signed char temp[2]; //温度データtemparature data
unsigned char sign[2];//氷点下表示below 0C sign
}_ams2302;
extern _ams2302 AM2302;//AM2302データ計算格納
//AM2302初期化処理関数
void initAM2302(void);
//AM2302 データ取得関数
unsigned char AM2302_GetData(void);
AM2302.c
//-------------------
//AM2302 driver
//AM2302.c
//2025.11.07
//-------------------
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "Peripheral.h"
#include "AM2302.h"
//AM2302データ構造体のメモリ確保
_ams2302 AM2302;//AM2302データ計算格納
/**
* 関数名:initAM2302
* AM2302初期化関数
*/
void initAM2302(void)
{
AM2302_SET_TRISX=0x00;//割り当てポートピンディレクション:出力
AM2302_SDA_BIT = High;//割り当てポートピンの初期化
__delay_ms(100);
}
/**
* 関数名:AM2302_GetData
* 温湿度データの取得
* 受信データはグローバル変数に格納。
* @return 成功:ACK(0x11) 失敗:エラーコード
*/
unsigned char AM2302_GetData(void)
{
char num;
unsigned char timeUpCnt;//for Time UP Counter
unsigned char bitCnt;//bit counter
unsigned char checkSum;//checkSum fifth byte
//rocal values clear
bitCnt=0;
checkSum=0;
timeUpCnt=0;
//receiving buffer value clear
AM2302.Data[0]=0x00;
AM2302.Data[1]=0x00;
AM2302.Data[2]=0x00;
AM2302.Data[3]=0x00;
AM2302.Data[4]=0x00;
//ピン設定:出力 Pin Direction OUTPUT
AM2302_SET_TRISX=0x00;
//スタート発令 MCU sends out Start Transaction--------------------
AM2302_SDA_BIT = Low;
__delay_ms(10);
//ピン設定:入力PIN Direction Change Input RC3:input mode
AM2302_SET_TRISX=0x08;
//IOpin is pulled up for high level.
__delay_us(30);//waiting for slope up and terminate start state
/*timeUpCnt=0;
while(High==AM2302_SDA_BIT)
{
timeUpCnt++;
if(timeUpCnt>=255) return AM2302_EROOR_TUP0;
}//<====2018.11.16 omitted*/
//AM2302 sends out Response signal-------------------------------
timeUpCnt=0;
while(Low==AM2302_SDA_BIT)//Low->High loop 80us
{
timeUpCnt++;
__delay_us(3);
if(timeUpCnt>=255) return AM2302_EROOR_TUP1;
}
timeUpCnt=0;
while(High==AM2302_SDA_BIT)//High->Low loop 80us
{
timeUpCnt++;
__delay_us(3);
if(timeUpCnt>=255){
return AM2302_EROOR_TUP2;
}
//bit0は、必ずLowに落ちて、ループ離脱。
}
//AM2302 begins sending Data------------------------------------
timeUpCnt=0;
num=0;//格納先配列番号
do
{
while(!AM2302_SDA_BIT);
while(AM2302_SDA_BIT)
{//High時間の計測
__delay_us(3);
timeUpCnt++;
if(timeUpCnt >=20) return AM2302_EROOR_NG2;
}
//一定時間以上Highを持続していた場合はビットデータは1
if(timeUpCnt>=10)//要:オシロスコープで確認調整。
{
AM2302.Data[num]|=0x01;
}
bitCnt++;
if(bitCnt%8==0)
{//8bitごとに格納先を変える
num++;
}
else
{
AM2302.Data[num]<<=1;
}
timeUpCnt=0;
}while(bitCnt < AM2302_MAXBITNUM);//40bit格納で終了。
//AM2302データ受信完了 IOピンを再初期化--------------------------------
AM2302_SET_TRISX=0x00;
AM2302_SDA_BIT =High;
//CheckSum-----------------------------------------------------------
checkSum = (AM2302.Data[0] + AM2302.Data[1] +AM2302.Data[2] + AM2302.Data[3] & 0xFF);
if(checkSum==AM2302.Data[4])
{//チェックサム合格
//humidity calculation.
AM2302.val[0]= AM2302.Data[0]*256;
AM2302.val[1]= AM2302.Data[1];
AM2302.humi[0]=(AM2302.val[0]+AM2302.val[1])/10;//湿度整数部
AM2302.humi[1]=(AM2302.val[0]+AM2302.val[1])%10;//湿度小数部
AM2302.val[2]=(AM2302.Data[2] & 0x7F)*256;
AM2302.val[3]=AM2302.Data[3];
//temperature below zero checking マイナス温度
if((AM2302.Data[2]&0x80) ==0x80)
{
AM2302.sign[0]=-1;
AM2302.sign[1]='-';
}
else
{
AM2302.sign[0]=1;
AM2302.sign[1]=' ';
}
//temperature calculation.
AM2302.temp[0]=AM2302.sign[0]*((AM2302.val[2]+AM2302.val[3])/10);//温度整数部
AM2302.temp[1]=(AM2302.val[2]+AM2302.val[3])%10;//温度小数部
return AM2302_ACK;
}
else
{//チェックサムエラー
return checkSum;
}
}
main.c
// PIC16F1827 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
//#pragma config FOSC = HS // Oscillator Selection (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP =ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdlib.h>
#include <stdio.h>
#include "Interrupt.h"
#include "Peripheral.h"
#include "I2C_MSSP1.h"
#include "LCDdriver.h"
#include "AM2302.h"
#define _XTAL_FREQ 16000000
void Oscillator_Init(void);
void Port_Init(void);
char txt[20];//LCD文字列表示格納配列
void main(void)
{
uint8_t length=0;
uint8_t ret;
//Basic Hard Initialize
Oscillator_Init();
Port_Init();
//Peripheral初期化
Timer0_INIT();
USART_INIT();
I2C1_Reg_Init();//I2C初期化
//LCD SC1602 初期化
LCD_Init(LcdDeviceAdd);//Fclock=100kHzで初期化。
SSP1ADD=0x09;//Fosc=16MHz Fclock=400kHz
LCD_Printf(LcdDeviceAdd,"PIC16F1827",10,0x80);
//AM2302初期化
initAM2302();
//割り込み許可
Interrupt_START();
while(1)
{
//USART 割り込み処理
if(usart.rxCompleted)
{
usart.rxCompleted=false;
printf("%s\n",usart.rxBuf);
usart.length=0;
PIE1bits.RCIE=1;
}
//Timer0 割り込み処理
if(tm0.up)
{
tm0.up=false;
LATBbits.LATB0=1;
//AM2302温湿度データの取得と表示
ret=AM2302_GetData();
if(ret == AM2302_ACK)
{
printf("%2x,%2x,%2x,%2x\n\r",AM2302.Data[0],AM2302.Data[1],AM2302.Data[2],AM2302.Data[3]);
printf("%d.%d %d.%d\n\r",AM2302.humi[0],AM2302.humi[1],AM2302.temp[0],AM2302.temp[1]);
length = sprintf(txt,"%d.%d%% %d.%dC",AM2302.humi[0],AM2302.humi[1],AM2302.temp[0],AM2302.temp[1]);
LCD_Printf(LcdDeviceAdd,txt,length,0xC0);
}
LATBbits.LATB0=0;
INTCONbits.TMR0IE=1;
}
}
return;
}
void Oscillator_Init(void)
{
OSCCONbits.SPLLEN=0;
OSCCONbits.IRCF=0b1111;//16Mhz
OSCCONbits.SCS=0b10;//InternalOscillator
}
void Port_Init(void)
{
TRISA=0x00;
ANSELA=0x00;
TRISB=0x04; //RX:RB2
ANSELB=0x00;
PORTA=0x00;
PORTB=0x00;
//Altanative Pin Selective
APFCON0bits.RXDTSEL=1; //RX:RB2
APFCON1bits.TXCKSEL=1; //TX:RB5
//I2Cpin
TRISBbits.TRISB1=1;//I2C1:SDA1
TRISBbits.TRISB4=1;//I2C1:SCL1
}




