使用STM32F030C8T6普通IO口模拟IIC程序,已经实验验证可以使用。使用时请修改相应的管脚和延时函数即可。各个函数在程序中有备注就不一一说明了。还有一个是使用IIC读SI7020的示例程序。大家可以去使用。
si7020_iic.h
- #ifndef __SI7020_IIC_H
- #define __SI7020_IIC_H
- #include <stdio.h>
- #include <stdint.h>
- #include <stm32f1xx.h>
- //////////////////////////////////////////////////////////////////////////////////
- //本程序只供学习使用,未经作者许可,不得用于其它任何用途
- //IIC 驱动函数头文件
- //使用普通IO口模拟IIC
- //////////////////////////////////////////////////////////////////////////////////
- typedef enum
- {
- NACK = 0,
- ACK =! NACK,
- } AckStatus;
- #define SI7020_IIC_SDA_CLK RCC_APB2Periph_GPIOB
- #define SI7020_IIC_SDA_PORT GPIOB
- #define SI7020_IIC_SDA_PIN GPIO_PIN_5
- #define SI7020_IIC_SCL_CLK RCC_APB2Periph_GPIOB
- #define SI7020_IIC_SCL_PORT GPIOB
- #define SI7020_IIC_SCL_PIN GPIO_PIN_6
-
- //IO方向设置
- #define SET_SI7020_IIC_SDA_PIN() HAL_GPIO_WritePin(SI7020_IIC_SDA_PORT,SI7020_IIC_SDA_PIN,GPIO_PIN_SET)
- #define RESET_SI7020_IIC_SDA_PIN() HAL_GPIO_WritePin(SI7020_IIC_SDA_PORT,SI7020_IIC_SDA_PIN,GPIO_PIN_RESET)
- #define SET_SI7020_IIC_SCL_PIN() HAL_GPIO_WritePin(SI7020_IIC_SCL_PORT,SI7020_IIC_SCL_PIN,GPIO_PIN_SET)
- #define RESET_SI7020_IIC_SCL_PIN() HAL_GPIO_WritePin(SI7020_IIC_SCL_PORT,SI7020_IIC_SCL_PIN,GPIO_PIN_RESET)
-
- //IIC所有操作函数
- void delay(unsigned int j);
- void SI7020_IIC_Init(void); //初始化IIC的IO口
- void SI7020_IIC_Start(void); //发送IIC开始信号
- void SI7020_IIC_Stop(void); //发送IIC停止信号
- void SI7020_IIC_Send_Byte(uint8_t txd); //IIC发送一个字节
- uint8_t SI7020_IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
- uint8_t SI7020_IIC_Wait_Ack(void); //IIC等待ACK信号
- void SI7020_IIC_Ack(void); //IIC发送ACK信号
- void SI7020_IIC_NAck(void); //IIC不发送ACK信号
- #endif
复制代码 si7020_iic.c
- #include "Hal_SI7020_IIC/si7020_iic.h"
- #include "delay/delay.h"
- #include "common.h"
- //////////////////////////////////////////////////////////////////////////////////
- //本程序只供学习使用,未经作者许可,不得用于其它任何用途
- //IIC 驱动函数
- //使用普通IO口模拟IIC
- //请根据程序修改相应头文件和延时函数。
- //////////////////////////////////////////////////////////////////////////////////
- //延时函数如果需要修改请修改此处:us
- void _delay_us(uint32_t us)
- {
- delay_us(us);
- }
- void SI7020_IIC_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- __HAL_RCC_GPIOB_CLK_ENABLE();
-
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
- GPIO_InitStructure.Pin = SI7020_IIC_SDA_PIN;
- HAL_GPIO_Init(SI7020_IIC_SDA_PORT, &GPIO_InitStructure);
-
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
- GPIO_InitStructure.Pin = SI7020_IIC_SCL_PIN;
- HAL_GPIO_Init(SI7020_IIC_SCL_PORT, &GPIO_InitStructure);
-
- HAL_GPIO_WritePin(SI7020_IIC_SDA_PORT,SI7020_IIC_SDA_PIN,GPIO_PIN_SET);
- HAL_GPIO_WritePin(SI7020_IIC_SCL_PORT,SI7020_IIC_SCL_PIN,GPIO_PIN_SET);
- }
- void SI7020_SDA_IN()
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- __HAL_RCC_GPIOB_CLK_ENABLE();
- GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
- GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
- GPIO_InitStructure.Pin = SI7020_IIC_SDA_PIN;
- HAL_GPIO_Init(SI7020_IIC_SDA_PORT, &GPIO_InitStructure);
- }
- void SI7020_SDA_OUT()
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- __HAL_RCC_GPIOB_CLK_ENABLE();
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
- GPIO_InitStructure.Pin = SI7020_IIC_SDA_PIN;
- HAL_GPIO_Init(SI7020_IIC_SDA_PORT, &GPIO_InitStructure);
- }
- //产生IIC起始信号
- void SI7020_IIC_Start(void)
- {
- SI7020_SDA_OUT(); //sda线输出
- SET_SI7020_IIC_SCL_PIN();
- SET_SI7020_IIC_SDA_PIN();
- _delay_us(3);
- RESET_SI7020_IIC_SDA_PIN();
- _delay_us(3);
- RESET_SI7020_IIC_SCL_PIN(); //钳住I2C总线,准备发送或接收数据
- _delay_us(3);
- }
- //产生IIC停止信号
- void SI7020_IIC_Stop(void)
- {
- SI7020_SDA_OUT();//sda线输出
- RESET_SI7020_IIC_SDA_PIN();
- SET_SI7020_IIC_SCL_PIN();
- _delay_us(4);
- SET_SI7020_IIC_SDA_PIN();
- _delay_us(4);
- }
- //等待应答信号到来
- //返回值:ACK,接收到应答
- // NACK,未接收到应答
- uint8_t SI7020_IIC_Wait_Ack(void)
- {
- uint8_t ucErrTime=0;
- SI7020_SDA_IN(); //SDA设置为输入
- SET_SI7020_IIC_SCL_PIN();
- _delay_us(5);
- // while(HAL_GPIO_ReadPin((GPIO_TypeDef*)SI7020_IIC_SDA_PORT,SI7020_IIC_SDA_PIN))
- // {
- // ucErrTime++;
- // if(ucErrTime>250)
- // {
- // SI7020_IIC_Stop();
- // return 1;//接收应答失败
- // }
- // }
- if(HAL_GPIO_ReadPin((GPIO_TypeDef*)SI7020_IIC_SDA_PORT,SI7020_IIC_SDA_PIN))
- return ACK;
- RESET_SI7020_IIC_SCL_PIN();
- _delay_us(5);
- return NACK;
- }
- //产生ACK应答
- void SI7020_IIC_Ack(void)
- {
- RESET_SI7020_IIC_SCL_PIN();
- SI7020_SDA_OUT();
- RESET_SI7020_IIC_SDA_PIN();
- _delay_us(2);
- SET_SI7020_IIC_SCL_PIN();
- _delay_us(2);
- RESET_SI7020_IIC_SCL_PIN();
- }
- //不产生ACK应答
- void SI7020_IIC_NAck(void)
- {
- RESET_SI7020_IIC_SCL_PIN();
- SI7020_SDA_OUT();
- SET_SI7020_IIC_SDA_PIN();
- _delay_us(2);
- SET_SI7020_IIC_SCL_PIN();
- _delay_us(2);
- RESET_SI7020_IIC_SCL_PIN();
- }
- //IIC发送一个字节
- void SI7020_IIC_Send_Byte(uint8_t txd)
- {
- uint8_t t;
- SI7020_SDA_OUT();
- SET_SI7020_IIC_SDA_PIN();
- for(t=0;t<8;t++)
- {
- if(txd&0x80)
- SET_SI7020_IIC_SDA_PIN();
- else
- RESET_SI7020_IIC_SDA_PIN();
- txd<<=1;
- _delay_us(2); //对TEA5767这三个延时都是必须的
- SET_SI7020_IIC_SCL_PIN();
- _delay_us(2);
- RESET_SI7020_IIC_SCL_PIN();
- _delay_us(2);
- }
- }
- //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
- uint8_t SI7020_IIC_Read_Byte(unsigned char ack)
- {
- unsigned char i,receive=0;
- SI7020_SDA_IN();//SDA设置为输入
- for(i=0;i<8;i++ )
- {
- RESET_SI7020_IIC_SCL_PIN();
- _delay_us(2);
- SET_SI7020_IIC_SCL_PIN();
- receive<<=1;
- if(HAL_GPIO_ReadPin(SI7020_IIC_SDA_PORT,SI7020_IIC_SDA_PIN))receive++;
- _delay_us(2);
- }
- if (!ack)
- SI7020_IIC_NAck();//发送nACK
- else
- SI7020_IIC_Ack(); //发送ACK
- return receive;
- }
复制代码 si7020.h
- #ifndef __SI7020_H
- #define __SI7020_H
- #include <stdio.h>
- #include <stdint.h>
- #include <stm32f1xx.h>
- typedef uint8_t u8;
- typedef uint16_t u16;
- typedef uint32_t u32;
- #define SI7020_ADDRESS 0X80 //SI7020器件地址
- #define SI7020_READ 0X01 //读数据
- #define SI7020_TEMPERATURE 0xE3
- #define SI7020_HUMIDITY 0xE5
- #define SI7020_SOFT_RESET 0xFE
- void SI7020_Init(void); //初始化IIC
- uint16_t SI7020_ReadOneByte(uint8_t ReadAddr);
- int16_t SI7020_Read_Humidity(void);
- int16_t SI7020_Read_Temperture(void);
- #endif
复制代码 si7020.c
- #include "Hal_SI7020/si7020.h"
- #include "Hal_SI7020_IIC/si7020_iic.h"
- //#include "delay.h"
- //#include "delay.h"
- #include "Hal_OLED/oled.h"
- #include "delay/delay.h"
- #include "common.h"
- //SI7020串口初始化
- void SI7020_Init(void)
- {
- SI7020_IIC_Init();
- }
- //在SI7020指定地址读出一个数据
- //ReadAddr:读取温度或温度
- //返回值 :读到的数据
- uint16_t SI7020_ReadOneByte(uint8_t ReadAddr)
- {
- uint8_t error=1;
- uint8_t temp[2];
- uint16_t value=0;
- SI7020_IIC_Start();
- SI7020_IIC_Send_Byte(SI7020_ADDRESS);
- SI7020_IIC_Wait_Ack();
- SI7020_IIC_Send_Byte(ReadAddr);
- SI7020_IIC_Wait_Ack();
- SI7020_IIC_Start();
- SI7020_IIC_Send_Byte(SI7020_ADDRESS|SI7020_READ);
- SI7020_IIC_Wait_Ack();
- delay_ms(20); //延时一段时间,不可少。
- // SI7020_IIC_Start(); //若使用No Hold Master Mode模式请使用此3行程序
- // SI7020_IIC_Send_Byte(SI7020_ADDRESS|SI7020_READ);
- // SI7020_IIC_Wait_Ack();
- temp[1]=SI7020_IIC_Read_Byte(1);
- temp[0]=SI7020_IIC_Read_Byte(0);
- SI7020_IIC_Stop();//产生一个停止条件
- value=temp[0]|(temp[1]<<8);
- return value;
- }
- //读取湿度
- //返回值为湿度
- int16_t SI7020_Read_Humidity(void)
- {
- uint16_t value=0;
- double temp;
- value=SI7020_ReadOneByte(SI7020_HUMIDITY);
- temp=(double)value;
- temp=(temp/65536.0f)*125.0f-6.0f;
- GIZWITS_LOG("Humidity = %.2lf \n", temp);//机智云的串口打印
- return (int16_t)(temp*10); //返回湿度值,此处放大了10倍
- }
- //读取湿度
- //返回值为湿度
- int16_t SI7020_Read_Temperture(void)
- {
- uint16_t value=0;
- double temp;
- value=SI7020_ReadOneByte(SI7020_TEMPERATURE);
- temp=(double)value;
- temp=(temp/65536.0f) * 175.72f - 46.85f;
- GIZWITS_LOG("Temperature = %.2lf \n", temp);//机智云的串口打印
- return (int16_t)(temp*10); //返回温度值,此处放大了10倍
-
- }
-
复制代码 下面附上附件
Hal_SI7020.zip
(1.27 KB, 下载次数: 36)
|