1089 views|1 replies

101

Posts

1

Resources
The OP
 

[Jihai APM32F4xx Tiny] Jihai APM32F407__IIC_STH30 (2) [Copy link]

 This post was last edited by Yin Xiaozhou on 2023-7-7 11:43

Preface

In this post, we will introduce how to use the common IO port of APM32F407 to simulate IIC timing and realize communication with STH30. In this post, we will use the common IO port of APM32F407 to simulate IIC timing to realize the reading and writing of SHT30 registers, and read the temperature and humidity data collected by SHT30 and print it on the computer through the serial port. This article is divided into the following parts:

  • SHT30 Introduction
  • IIC Protocol Introduction
  • Data printing software design
  • Download Verification

SHT30 Introduction

SHT30 is a temperature and humidity sensor produced by the Swiss company Shengshi Ruien. From SHT10 to SHT31, Shengshi Ruien's sensors are quite good.

Utilizes I2C for data transmission, has two selectable addresses, and a wide power supply voltage from 2.4V to 5.5V.

SHT30 supports a maximum transmission rate of 1000k, so the communication time is very short.

There are two ways to read the value of sht30. I will introduce the status query and value query methods using iic.

  • 1: Status query

Send command: 0xF32D.

  • 2: Numerical query.

Send command 0x2C06

In this mode, issuing a measurement command triggers the acquisition of a data pair. Each data pair consists of a 16-bit temperature and a 16-bit humidity value (in that order).

The data value is always followed by a CRC checksum during transmission.

After sending through iic, the value returned by sht30 is an array of 6 bytes.

1[high eight digits of temperature] 2[eighth digit of temperature] 3[temperature crc check]

4[humidity high eight digits] 5[humidity eighth digit] 6[humidity CRC check]

IIC Protocol Introduction

  • I2C Physical Layer

Physical layer characteristics:

  1. A bus that supports multiple devices (signal lines shared by multiple devices). In the I2C communication bus, multiple communication hosts and communication slaves can be connected.
  2. An I2C bus uses only two bus lines, a bidirectional serial data line (SDA) and a serial clock line (SCL). The data line is used to send data, and the clock line is used for data transmission and reception synchronization.
  3. Each device connected to the bus has an independent address (seven bits or ten bits), and the host accesses the slave device based on the device address.
  4. The bus needs to be connected to a pull-up resistor to the power supply. When the I2C bus is idle, the output is high-impedance. When all devices are idle, they all output high-impedance. The pull-up resistor pulls the bus to a high level.
  5. Three communication modes: Standard mode (up to 100KHz) Fast mode (up to 400KHz)
  6. Fast-mode Plus (up to 1MHz).
  7. When multiple hosts use the bus at the same time, data conflicts can be prevented by using bus arbitration to decide which device occupies the bus.
  8. Programmable setup and hold time, can program the high level time and low level time of SCL in I2C.

Protocol layer features:

  • Data is sent in the form of frames, each frame consists of 1 byte (8 bits).
  • During the rising edge of SCL, SDA needs to remain stable, and SDA changes during the low period of SCL.
  • In addition to data frames, the I2C bus also has start signals, stop signals, and response signals.
    • Start bit: When SCL is at a stable high level, a falling edge of SDA starts transmission.
    • Stop bit: When SCL is at a stable high level, a rising edge of SDA stops sending.
    • Acknowledge bit: used to indicate that a byte has been sent successfully. Bus transmitter (whether master or slave),
  • After sending 8 bits of data, SDA will be released (changed from output to input). During the ninth clock pulse, the receiver pulls SDA low to acknowledge receipt of the data.

IIC communication process

(1) Gray: This data is sent from the host to the slave.

(2) S: start signal

(3) SLAVE ADDRESS: slave address

(4) White: This data is sent from the slave to the master

(5) R/W: Transmission direction selection bit 1 for reading 0 for writing

(6) P: Stop signal

Data printing software design

Software Delay


#include "apm32f4xx.h"
#include "SysTick_Delay.h"

/**@} end of group SysTick_TimeBase_Macros*/

static __IO u32 TimingDelay;

/*!
 * @brief        Start SysTick
 *
 * @param       None
 *
 * @retval      None
 */
void SysTick_Init(void)
{
    /** SystemFrequency / 1000 = 1ms */
    if (SysTick_Config(SystemCoreClock / 1000))
    {
        /** Capture error */
        while (1);
    }
}

/*!
 * @brief       Precise Delay
 *
 * @param       nTime in milliseconds
 *
 * @retval      None
 */
void SysTick_Delay_ms(__IO u32 nTime)
{
    TimingDelay = nTime;
    while(TimingDelay != 0);
}



/*!
 * @brief       Precise Delay
 *
 * @param       nTime in milliseconds
 *
 * @retval      None
 */
void SysTick_Delay_us(__IO u32 nTime)
{
	  SysTick_Config(SystemCoreClock / 1000000);
    TimingDelay = nTime;
    while(TimingDelay != 0);
	  SysTick_Config(SystemCoreClock / 1000);
}

/*!
 * @brief       Decrements the TimingDelay
 *
 * @param       None
 *
 * @retval      None
 */
void TimingDelay_Decrement(void)
{
    if(TimingDelay != 0)
    {
        TimingDelay--;
    }
}

SysTick_Config (SystemCoreClock/1000); This function turns on the SysTick interrupt and also sets the Systick reload register. SystemCoreClock/1000 is one thousandth of the system clock frequency. That is, every second, the Systick register will be reloaded 1000 times, 1ms each time. If the SystemCoreClock / 1000000每次就是1us,1usSystick interrupt is too frequent, it will be restored after a delay of 1ms.

GPIO emulation IIC

#ifndef __I2C_H
#define __I2C_H			 



#include "apm32f4xx.h"
#include "SysTick_Delay.h"
#include "apm32f4xx_gpio.h"

#include "apm32f4xx_rcm.h"
/**********************
引脚别名定义
***********************/			




#define I2C_PageSize  8  


#define I2C_SCL_GPIO_PIN            GPIO_PIN_6
#define I2C_SCL_GPIO_PORT           GPIOB
#define I2C_SCL_GPIO_CLK            RCM_AHB1_PERIPH_GPIOB
#define I2C_SCL_SOURCE              GPIO_PIN_SOURCE_6

#define I2C_SDA_GPIO_PIN            GPIO_PIN_7
#define I2C_SDA_GPIO_PORT           GPIOB
#define I2C_SDA_GPIO_CLK            RCM_AHB1_PERIPH_GPIOB
#define I2C_SDA_SOURCE              GPIO_PIN_SOURCE_7




#define I2C_SDA_IN()               { I2C_SDA_GPIO_PORT->MODE &= ~(7 << (3 * 2)); I2C_SDA_GPIO_PORT->MODE |= 0 << 7 * 2; }
#define I2C_SDA_OUT()              { I2C_SDA_GPIO_PORT->MODE &= ~(7 << (3 * 2)); I2C_SDA_GPIO_PORT->MODE |= 1 << 7 * 2; }

#define I2C_SCL_1                   GPIO_SetBit(I2C_SCL_GPIO_PORT,I2C_SCL_GPIO_PIN)
#define I2C_SCL_0                   GPIO_ResetBit(I2C_SCL_GPIO_PORT,I2C_SCL_GPIO_PIN)

#define I2C_SDA_1                   GPIO_SetBit(I2C_SDA_GPIO_PORT,I2C_SDA_GPIO_PIN)
#define I2C_SDA_0                   GPIO_ResetBit(I2C_SDA_GPIO_PORT,I2C_SDA_GPIO_PIN)

#define I2C_SDA_INPUT               GPIO_ReadInputBit(I2C_SDA_GPIO_PORT,I2C_SDA_GPIO_PIN)



/* Private function prototypes -----------------------------------------------*/

void GPIO_Simulation_IIC_Config(void);
void I2C_delay(void);
unsigned char I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NoAck(void);
unsigned char I2C_WaitAck(void) ;
void I2C_SendByte(unsigned char SendByte) ;
unsigned char I2C_ReceiveByte(void)  ;


#endif 
/*********************************************************************************************************
      END FILE
*********************************************************************************************************/


//头文件

#include "i2c.h"


void GPIO_Simulation_IIC_Config(void)
{
	  GPIO_Config_T     gpioConfigStruct;
    
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
   
    
    gpioConfigStruct.pin = GPIO_PIN_6|GPIO_PIN_7;
    gpioConfigStruct.mode = GPIO_MODE_OUT;
    gpioConfigStruct.speed = GPIO_SPEED_50MHz;
    gpioConfigStruct.otype = GPIO_OTYPE_OD;
    gpioConfigStruct.pupd = GPIO_PUPD_NOPULL;
    GPIO_Config(GPIOB, &gpioConfigStruct);
    
    
    I2C_SCL_1;
    I2C_SDA_1;
		

}

 /**
  * @File    I2C_delay
  * @brief  延迟时间
  * @param  无
  * @retval 无
  */
void I2C_delay(void)  //for 1T  STC	delay 
{	
	SysTick_Delay_us(5);
}

 /**
  * @file   I2C_Start
  * @brief  起始信号
  * @param  无
  * @retval 无
  */
unsigned char I2C_Start(void)
{
	I2C_SDA_1;
	I2C_SCL_1; 
	I2C_delay();
	
	I2C_SDA_IN();
	if(!I2C_SDA_INPUT)return 0;	/* SDA线为低电平则总线忙,退出 */
	I2C_SDA_OUT();
	
	I2C_SDA_0;
	I2C_delay();
	
	I2C_SDA_IN();
	if(I2C_SDA_INPUT) return 0;	/* SDA线为高电平则总线出错,退出 */
	I2C_SDA_OUT();
	
	I2C_SDA_0;
	I2C_delay();
	return 1;
}

 /**
  * @file   I2C_Stop
  * @brief  停止信号
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SCL_0;
	I2C_delay();
	I2C_SDA_0;
	I2C_delay();
	I2C_SCL_1; 
	I2C_delay();
	I2C_SDA_1;
	I2C_delay();
}

 /**
  * @file   I2C_Ack
  * @brief  应答信号
  * @param  无
  * @retval 无
  */
void I2C_Ack(void)
{	
	I2C_SCL_0;
	I2C_delay();
	I2C_SDA_0;
	I2C_delay();
	I2C_SCL_1; 
	I2C_delay();
	I2C_SCL_0;
	I2C_delay();
}

 /**
  * @file   I2C_NoAck
  * @brief  无应答信号
  * @param  无
  * @retval 无
  */
void I2C_NoAck(void)
{	
	I2C_SCL_0;
	I2C_delay();
	I2C_SDA_1;
	I2C_delay();
	I2C_SCL_1; 
	I2C_delay();
	I2C_SCL_0;
	I2C_delay();
}

 /**
  * @file   I2C_WaitAck
  * @brief  等待Ack
  * @param  无
  * @retval 返回为:=1有ACK,=0无ACK
  */
unsigned char I2C_WaitAck(void) 	
{
	I2C_SCL_0;
	I2C_delay();
	I2C_SDA_1;			
	I2C_delay();
	I2C_SCL_1; 
	I2C_delay();
	
	I2C_SDA_IN();
	if(I2C_SDA_INPUT)
	{
      I2C_SCL_0;
      return 0;
	}
	I2C_SDA_OUT();
	
	I2C_SCL_0;
	return 1;
}

 /**
  * @file   I2C_SendByte
  * @brief  数据从高位到低位
  * @param  - SendByte: 发送的数据
  * @retval 无
  */
void I2C_SendByte(unsigned char SendByte) 
{
    unsigned char i=8;
    while(i--)
    {
			I2C_SCL_0;
			I2C_delay();
			if(SendByte&0x80)
			I2C_SDA_1;  
			else 
			I2C_SDA_0;   
			SendByte<<=1;
			I2C_delay();
			I2C_SCL_1; 
			I2C_delay();
    }
    I2C_SCL_0;
}


 /**
  * @file   I2C_ReceiveByte
  * @brief  数据从高位到低位
  * @param  无
  * @retval I2C总线返回的数据
  */
unsigned char I2C_ReceiveByte(void)  
{ 
    unsigned char i=8;
    unsigned char ReceiveByte=0;

    I2C_SDA_1;
		
		I2C_SDA_IN();
    while(i--)
    {
      ReceiveByte<<=1;      
      I2C_SCL_0;
      I2C_delay();
	    I2C_SCL_1; 
      I2C_delay();	
      if(I2C_SDA_INPUT)
      {
        ReceiveByte|=0x01;
      }
    }
		I2C_SDA_OUT();
		
    I2C_SCL_0;
    return ReceiveByte;
} 
   
 


/*********************************************************************************************************
      END FILE
*********************************************************************************************************/

Main function implementation

/*!
 * @file        main.c
 *
 * @brief       Main program body
 *
 * @version      V1.0.2
 *
 * @date         2023-03-01
 *
 * @attention
 *
 *  Copyright (C) 2021-2023 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

/* Includes */

#include "main.h"
#include "Board.h"
#include "SysTick_Delay.h"
#include "stdio.h"
#include "stdarg.h"
#include "SHT30.h"

/* printf function configs to USART1*/
#define DEBUG_USART  USART1

#define LED2(x)        GPIO_WriteBitValue(GPIOE, GPIO_PIN_5,x)
#define LED3(x)        GPIO_WriteBitValue(GPIOE, GPIO_PIN_6,x)

#define KEY1           GPIO_ReadInputBit(GPIOC,GPIO_PIN_10)
#define KEY2           GPIO_ReadInputBit(GPIOC,GPIO_PIN_11)

 USART_Config_T usartConfigStruct;    //串口配置结构体




void  LED_GPIO_Config(void)
{
    GPIO_Config_T  configStruct;

    /** 开启GPIO_LED时钟 */
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOE);

    /** 配置GPIO_LED引脚 */
    GPIO_ConfigStructInit(&configStruct);
    configStruct.pin = GPIO_PIN_5;    //不支持或
    configStruct.mode = GPIO_MODE_OUT;
    configStruct.speed = GPIO_SPEED_50MHz;
    GPIO_Config(GPIOE, &configStruct);
	
    configStruct.pin = GPIO_PIN_6;    //不支持或
    GPIO_Config(GPIOE, &configStruct);
	
	  //设置GPIO为低电平,不点亮LED
    GPIO_SetBit(GPIOE, GPIO_PIN_5);
    GPIO_SetBit(GPIOE, GPIO_PIN_6);
}



void  KEY_GPIO_Config(void)
{
    GPIO_Config_T  configStruct;

    /** 开启GPIO_LED时钟 */
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOC);

    /** 配置GPIO_LED引脚 */
    GPIO_ConfigStructInit(&configStruct);
    configStruct.pin = GPIO_PIN_10;    //不支持或
    configStruct.mode = GPIO_MODE_IN;
    configStruct.speed = GPIO_SPEED_50MHz;
    GPIO_Config(GPIOC, &configStruct);
	
    configStruct.pin = GPIO_PIN_11;    //不支持或
    GPIO_Config(GPIOC, &configStruct);
}


void UART_init_Config(void)
{
	    /* USART configuration */
    USART_ConfigStructInit(&usartConfigStruct);
    usartConfigStruct.baudRate = 115200;
    usartConfigStruct.mode = USART_MODE_TX_RX;
    usartConfigStruct.parity = USART_PARITY_NONE;
    usartConfigStruct.stopBits = USART_STOP_BIT_1;
    usartConfigStruct.wordLength = USART_WORD_LEN_8B;
    usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;

    /* COM1 init*/
    APM_MINI_COMInit(COM1, &usartConfigStruct);
}


/*!
 * @brief     Main program
 *
 * @param     None
 *
 * @retval    None
 */
void Delay(void)
{
    volatile uint32_t delay = 0x2FFFFF;

    while (delay--);
}

/*!
 * @brief     USART write
 *
 * @param     dat:    data
 *
 * @param     len:    Data length
 *
 * @retval    None
 */
void USART_Write(uint8_t* dat, uint8_t len)
{
    uint8_t i;

    for (i = 0; i < len; i++)
    {
        while (USART_ReadStatusFlag(USART1, USART_FLAG_TXBE) == RESET);

        USART_TxData(USART1, dat[i]);
    }
}

//void KEY_Input(void)
//{
//	   LED2(KEY1);
//     LED3(KEY2);
//}


unsigned char key_read(void)
{
	static unsigned char key_up  = 1;
	if(key_up &&( (KEY1 == BIT_RESET) || (KEY2 == BIT_RESET) ) )
	{
     	SysTick_Delay_ms(10);
		  key_up = 0; 
		  if(KEY1 == BIT_RESET)   return  1;
		  else if(KEY2 == BIT_RESET)  return  2;
	
	}
	if(KEY1&&KEY2) key_up  = 1;
	return 0;
}


/*!
 * @brief     Main program
 *
 * @param     None
 *
 * @retval    None
 */
int main(void)
{
	  unsigned char key = 0;
	  
	  LED_GPIO_Config();
	  KEY_GPIO_Config();
	  SysTick_Init();
	  UART_init_Config();
    SHT3X_Init();
	
	 
	  printf("MCU init OK!\r\n");
	
   while (1)
   {
		 key = key_read();
		 switch (key)
		 {
			 case  1 :
				    LED2(0);
			      SysTick_Delay_ms(100);
			      SHT3X_TEST();  
			      LED2(1);
			     break;
				 
			 case  2 :
				    LED3(0);
			      SysTick_Delay_ms(100);
			      LED3(1);
			     break;
//        KEY_Input();
			 
     }
	 }
}


/*!
* @brief       Redirect C Library function printf to serial port.
*              After Redirection, you can use printf function.
*
* @param       ch:  The characters that need to be send.
*
* @param       *f:  pointer to a FILE that can recording all information
*              needed to control a stream
*
* @retval      The characters that need to be send.
*
* @note
*/
int fputc(int ch, FILE* f)
{
    /* send a byte of data to the serial port */
    USART_TxData(DEBUG_USART, (uint8_t)ch);

    /* wait for the data to be send */
    while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);

    return (ch);
}

Download Verification

Press a button and the data will be printed.

Simulation_IIC_SHT30.zip

6.11 MB, downloads: 8

This post is from Domestic Chip Exchange

Latest reply

SHT30 supports a maximum transmission rate of 1000k, so the communication time is very short. Why is the communication time so short?   Details Published on 2023-7-8 08:56
 
 

6580

Posts

0

Resources
2
 

SHT30 supports a maximum transmission rate of 1000k, so the communication time is very short.

Why is the communication time so short?

This post is from Domestic Chip Exchange
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list