STM32F051 模拟IIC
/** ****************************************************************************** * @file HTU20.x * @brief HTU20 function * @cpu STM32F051 * @compiler Keil uVision V4.74 * @author MetalSeed * @copyright WSHHB * @version V1.0.0 * @date 18-Sept-2014 * @modifydate20-Sept-2014 ****************************************************************************** * @attention */ #include "boardAPI.h" #include "stm32f0xx.h" #include "HTU20.h" #include "uart.h" #include "delay.h" GPIO_InitTypeDef GPIO_InitStructure; /** * @brief Start HTU GPIO port CLK * @retval None */ void HTUInit() { RCC_AHBPeriphClockCmd(HTU20_CLK, ENABLE); } /*================================================================ IIC address ================================================================*/ #define SHT20ADDR 0x80 /*================================================================ ACK and NACK defination ================================================================*/ #define ACK 0 #define NACK 1 /*================================================================ HTU20D Command Code ================================================================*/ /* Command Code Comment Trigger Temperature Measurement 0xe3 Hold master Trigger Humidity Measurement 0xe5 Hold master Trigger Temperature Measuremeng 0xf3 No Hold master Trigger Humidity Measurement 0xf5 No Hold master Write user register 0xe6 Read user register 0xe7 Soft Reset 0xfe */ #define SOFT_RESET 0xfe #define READ_REGISTER 0xe7 #define WRITE_REGISTER 0xe6 #define TRIGGER_TEMP 0xf3 #define TRIGGER_HUMI 0xf5 /*================================================================ HTU20 operate interface ================================================================*/ #define HTU20_SDA GPIO_ReadInputDataBit(HTU20_SCL_PORT,HTU20_SCL_PIN) #define HTU20_SCL GPIO_ReadInputDataBit(HTU20_SDA_PORT,HTU20_SDA_PIN) /** * @brief Set SDA pin dircate as output * @retval None */ void HTU20_SDA_OUT() { GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = HTU20_SDA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(HTU20_SDA_PORT, &GPIO_InitStructure); } /** * @brief Set SDA pin dircate as intput * @retval None */ void HTU20_SDA_IN() { GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = HTU20_SDA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(HTU20_SDA_PORT, &GPIO_InitStructure); } /** * @brief Set SDA pin as high * @retval None */ void HTU20_SDA_1() { GPIO_SetBits(HTU20_SDA_PORT,HTU20_SDA_PIN) ; } /** * @brief Set SDA pin as low * @retval None */ void HTU20_SDA_0() { GPIO_ResetBits(HTU20_SDA_PORT,HTU20_SDA_PIN) ; } /** * @brief Set SCL pin dircate as output * @retval None */ void HTU20_SCL_OUT() { GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = HTU20_SCL_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(HTU20_SCL_PORT, &GPIO_InitStructure); } /** * @brief Set SCL pin as high * @retval None */ void HTU20_SCL_1() { GPIO_SetBits(HTU20_SCL_PORT,HTU20_SCL_PIN) ; } /** * @brief Set SCL pin as low * @retval None */ void HTU20_SCL_0() { GPIO_ResetBits(HTU20_SCL_PORT,HTU20_SCL_PIN) ; } /*================================================================ Simulation I2C Function ================================================================*/ /** * @brief A short delay for iic synchronization * @param t us * @retval None */ void I2CDelay (BYTE t) { while(t--) { __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); } } /** * @brief I2C init * @retval None */ void I2CInit(void) { HTU20_SDA_OUT(); HTU20_SCL_OUT(); HTU20_SDA_1(); I2CDelay(1); HTU20_SCL_1(); I2CDelay(1); } /** * @brief IIC start signal * @comment SCL、SDA同为高,SDA跳变成低之后,SCL跳变成低 * @retval None */ void I2CStart(void) { HTU20_SDA_OUT(); HTU20_SDA_1(); HTU20_SCL_1(); I2CDelay(5); //大于4.7us HTU20_SDA_0(); I2CDelay(5); //大于4us HTU20_SCL_0(); I2CDelay(5); } /** * @brief IIC Stop Signal * @commet SCL、SDA同为低,SCL跳变成高之后,SDA跳变成高 * @retval None */ void I2CStop(void) { HTU20_SDA_OUT(); HTU20_SDA_0(); HTU20_SCL_0(); I2CDelay(5); HTU20_SCL_1(); I2CDelay(5); HTU20_SDA_1(); I2CDelay(5); } /** * @brief simu IIC write byte * @param Write_Byte: data * @retval None */ BYTE I2C_Write_Byte(BYTE Write_Byte) { BYTE i; HTU20_SDA_OUT(); for(i = 0; i < 8; ++i) { if(Write_Byte & SHT20ADDR) { HTU20_SDA_1(); } else { HTU20_SDA_0(); } I2CDelay(1); HTU20_SCL_1(); //输出SDA稳定后拉高SCL,从机检测到后采样 I2CDelay(5); //保证足够长锁定时间,确保从机采样成功 HTU20_SCL_0(); I2CDelay(1); Write_Byte <<= 1; } I2CDelay(4); HTU20_SDA_1(); //8位发送完后释放数据线,准备接受应答信号 HTU20_SCL_1(); //再次拉高SCL,告诉从机发送完毕,等待应答 I2CDelay(5); HTU20_SDA_IN(); if(HTU20_SDA == 1) //SDA为高,收到NACK return NACK; else //SDA为低,收到ACK return ACK; // HTU20_SCL_0(); // I2CDelay(15); } /** * @brief simu read byte form IIC * @param * @retval None */ BYTE I2C_Read_Byte(BYTE AckValue)//receivebyte { BYTE i, RDByte = 0; HTU20_SDA_OUT(); HTU20_SCL_0(); HTU20_SDA_1(); //释放总线,并置数据线为输入 HTU20_SDA_IN(); for (i = 0; i < 8; ++i) { HTU20_SCL_1(); //拉高SCL期间,采样 I2CDelay(2); RDByte <<= 1; if(HTU20_SDA == 1) { RDByte |= 0x01; } else { RDByte &= 0xfe; } I2CDelay(1); HTU20_SCL_0(); //下降沿告知从机发送下一位 I2CDelay(6); } HTU20_SDA_OUT(); //接受完一个字节,发送ACK or NACK if(AckValue == 1) { HTU20_SDA_1(); } else { HTU20_SDA_0(); } I2CDelay(3); HTU20_SCL_1(); I2CDelay(5); HTU20_SCL_0(); //清时钟线 I2CDelay(15); //HTU20_SDA_1(); return RDByte; } /** * @brief soft reset by transmit reset command * @retval None */ void SoftReset(void) { I2CInit(); I2CStart(); I2C_Write_Byte(SHT20ADDR & 0xfe); //I2C address + write I2C_Write_Byte(SOFT_RESET); //soft reset I2CStop(); } /** * @brief SET HTU20D resolution by write register * @retval None */ void SET_Resolution(void) { I2CStart(); if(I2C_Write_Byte(SHT20ADDR & 0xfe) == ACK) //I2C address + write + ACK { if(I2C_Write_Byte(WRITE_REGISTER)==ACK) //写用户寄存器 { if(I2C_Write_Byte(0x83)==ACK); //设置分辨率 11bit RH% 测量时间:12ms(typ.) } // 11bit T℃ 测量时间:9ms(typ.) } I2CStop(); } /** * @brief read sht20's converted result * @param TempOrHumiCMD: operation command for temperature or humidity * @retval None */ float ReadSht20(char TempOrHumiCMD) { float temp; BYTE MSB,LSB; float Humidity, Temperature; SET_Resolution(); I2CStart(); if(I2C_Write_Byte(SHT20ADDR & 0xfe) == ACK) //I2C address + write + ACK { if(I2C_Write_Byte(TempOrHumiCMD) == ACK) //command { do { delayms(6); I2CStart(); } while(I2C_Write_Byte(SHT20ADDR | 0x01) == NACK); //I2C address + read + NACK MSB = I2C_Read_Byte(ACK); LSB = I2C_Read_Byte(ACK); I2C_Read_Byte(NACK); //Checksum + NACK I2CStop(); LSB &= 0xfc; //Data (LSB) 的后两位在进行物理计算前前须置0 temp = (MSB << 8) + LSB; if (TempOrHumiCMD == ((char)TRIGGER_HUMI)) { /*-- calculate relative humidity [%RH] --*/ //equation: RH% = -6 + 125 * SRH/2^16 Humidity = (temp * 125) / 65536 - 6; return Humidity; } else { /*-- calculate temperature [°C] --*/ //equation:T = -46.85 + 175.72 * ST/2^16 Temperature = (temp * 175.72) / 65536 - 46.85; return Temperature; } } } return 0; }
SHT20 SHT21 HTU20 温湿度传感器驱动 STM32F051,布布扣,bubuko.com
SHT20 SHT21 HTU20 温湿度传感器驱动 STM32F051
原文地址:http://blog.csdn.net/metalseed/article/details/38021193