0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AM2302 温湿度センサーの使い方 ドライバー作成

Last updated at Posted at 2025-11-07

AM2302温湿度センサー

PIC16F1827を使用で、ドライバー作成。
IMG_5297.JPG

ピン配
IMG_5300.JPG
1:VDD 3.3Vから5.5V(5V推奨)
2:SDA シリアルデータ線(双方向通信)
3:NC なにも繋げない
4:GND
※SDAにはプルアップ抵抗でHighにする。通常、5KΩの抵抗を使用。

データフォーマット、プロトコル
(AM2302データシートより)
プロトコル.png
スタート:マイコンが1ms以上Lowにすることで、通信開始。
レスポンス:センサーが、マイコンに送信。これで通信接続完了。
湿度:上位バイト
湿度:下位バイト
温度:上位バイト(最上位バイトは、符号。マイナス温度)
温度:下位バイト
パリティービット(前述4バイトを加算したもの)

通信タイミング
IMG_5305.JPG
湿度、温度ともに16ビットデータ。小数点1桁を含む値が実データ。送信データは10倍されて、すべて整数になっている。
IMG_5306.JPG
シリアルバスは、5Vでプルアップされている。マイコンがバスラインをLowにさげると通信開始。条件は、1ms以上、Lowを保持すること。そのあとは、即座に、IOディレクションを入力に変更して、バスラインを開放する。
IMG_5307.JPG
レスポンスタイミングの80usは、計測していない。データの整合性は、すべてパリティチェックで行う。ここでは、
LOWからHighに移行することだけを確認するにとどめても、問題ない。
IMG_5308.JPG

IMG_5309.JPG
データ取得部で、ビットデータを受信するには、ビットデータの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データシートより)
計算.png

AM2302ドライバーコード

PIC16F1827ピン割付表
IMG_5304.JPG

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
}


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?