# STM32F103C8T6 **Repository Path**: an_zhiyang/stm32-f103-c8-t6 ## Basic Information - **Project Name**: STM32F103C8T6 - **Description**: No description available - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 8 - **Forks**: 1 - **Created**: 2021-06-19 - **Last Updated**: 2025-07-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README | DHT11温湿度传感器 | **STM32F103C8T6** | | :---------------: | :---------------: | | VCC | 3.3V | | DATA | PA11 | | GND | GND | ## DHT11温湿度传感器 ### 硬件连接 | DHT11温湿度传感器 | **STM32F103C8T6** | | :---------------: | :---------------: | | VCC | 3.3V | | DATA | PA11 | | GND | GND | | **GY-30 光照传感器** | **STM32F103C8T6** | | :------------------: | :---------------: | | VCC | 3.3V | | SCL | PA5 | | SDA | PA7 | | GND | GND | | MQ-2烟雾传感器 | STM32F103C8T6 | | :------------: | :-----------: | | VCC | 5V | | GND | GND | | AD | PA0 | | 人体红外传感器 | STM32F103C8T6 | | :------------: | :-----------: | | VCC | 5V | | OUT | PA6 | | GND | GND | | 光敏电阻传感器 | STM32F103C8T6 | | :------------: | :-----------: | | VCC | 5V | | GND | GND | | DO | PA4 | | MPU6050 | STM32F103C8T6 | | :-----: | :-----------: | | GND | GND | | VCC | 3.3V | | SCL | PB6 | | SDA | PB7 | | 霍尔传感器 | STM32F103C8T6 | | :--------: | :-----------: | | GND | GND | | VCC | 3.3V | | DO | PA3 | | US-100 | STM32F103C8T6 | | :----: | :-----------: | | GND | GND | | VCC | 3.3V | | Trig | PB10 | | Echo | PB11 | | GND | GND | ### 通信方式 ### 代码 #### main.c ```c #include "stm32f10x.h" #include "delay.h" #include "uart1.h" #include "dht11.h" u8 temp; u8 humi; int main(void) { SystemInit();//配置系统时钟为72M Uart1_Init(115200); //串口初始化 if(DHT11_Init()) { printf("DHT11 Error \r\n"); delay_ms(1000); } //主循环 while(1) { DHT11_Read_Data(&temp,&humi); printf("温度:%d℃ 湿度:%d ",temp,humi); delay_ms(1000); //延时1秒 } } ``` #### dht11.c ```c #include "dht11.h" #include "delay.h" #include "stm32f10x.h" #define DT GPIO_Pin_11 //复位DHT11 void DHT11_Rst(void) { DHT11_IO_OUT(); //SET OUTPUT 设置IO为输出 DHT11_DQ_OUT=0; //拉低DQ总线 delay_ms(20); //拉低至少18ms DHT11_DQ_OUT=1; //DQ=1 拉高总线 delay_us(30); //主机拉高20~40us } //等待DHT11的回应 //返回1:未检测到DHT11的存在 //返回0:存在 u8 DHT11_Check(void) { u8 retry=0; DHT11_IO_IN();//SET INPUT 设置IO为输入 //正常响应情况下DHT11会拉低总线40~50us //当IO被拉低或者计时时间到时会跳出while循环 while(DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; delay_us(1); } //跳出while 超时未检测到DHT11应答 则返回1 //未超时即正常收到低电平信号 继续判断 if(retry>=100) return 1; else retry=0; //DHT11拉低总线后会再次拉高总线40~50us while(!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); } if(retry>=100) return 1; //正确检测到了高电平且未超时 返回0 return 0; } //从DHT11读取一个位 //返回值:1/0 u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; delay_us(1); } delay_us(40);//等待40us if(DHT11_DQ_IN)return 1; else return 0; } //从DHT11读取一个字节 //返回值:读到的数据 u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0;i<8;i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat; } //从DHT11读取一次数据 //temp:温度值(范围:0~50°) //humi:湿度值(范围:20%~90%) //返回值:0,正常;1,读取失败 u8 DHT11_Read_Data(u8 *temp,u8 *humi) { u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=buf[0]; *temp=buf[2]; } } else return 1; return 0; } //初始化DHT11的IO口 DQ 同时检测DHT11的存在 //返回1:不存在 //返回0:存在 u8 DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PG端口时钟 GPIO_InitStructure.GPIO_Pin = DT; //PG11端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO口 GPIO_SetBits(GPIOA,DT); //PG11 输出高 DHT11_Rst(); //复位DHT11 return DHT11_Check();//等待DHT11的回应 } ``` #### dht11.h ```c #ifndef DHT11_H #define DHT11_H #include "sys.h" //PA11 #define DHT11_IO_IN() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=8<<12;} //PA11输入模式 #define DHT11_IO_OUT() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=3<<12;} //PA11输出模式 //IO操作函数 #define DHT11_DQ_OUT PAout(11) //数据端口 PA11 #define DHT11_DQ_IN PAin(11) //数据端口 PA11 u8 DHT11_Init(void); //初始化DHT11 u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取数据 u8 DHT11_Read_Byte(void); //读取一个字节 u8 DHT11_Read_Bit(void); //读取一位 u8 DHT11_Check(void); //检测DHT11是否存在 void DHT11_Rst(void); //复位DHT11 #endif ``` ## GY-30 光照传感器 [基于STM32_HAL库GY-30(BH1750FLV)驱动_Hsy的博客-CSDN博客](https://blog.csdn.net/weixin_40774605/article/details/89479539#1.1GY-30原理图) ![image-20210517163240847](https://i.loli.net/2021/05/17/59waHLxzrMNDUIF.png) ### 硬件连接 | **GY-30 光照传感器** | **STM32F103C8T6** | | :------------------: | :---------------: | | VCC | 3.3V | | SCL | PA5 | | SDA | PA7 | | GND | GND | ### 通信方式 使用IIC通信,**STM32F103C8T6**作为主机,**GY-30 光照传感器**作为从机。 **STM32F103C8T6**使用串口1与PC机通信. ### 代码 #### main.c ```c #include "stm32f10x.h" #include "delay.h" #include "uart1.h" #include "myiic.h" #include "bh_gy30.h" int main(void) { u16 bh_temp; //中间变量 Uart1_Init(115200); //串口初始化 MY_IIC_Init(); //模块IIC初始化 BH_Init(); //光强传感器初始化,GY30模块 //串口初始化输出 printf("\r\n-----THE INIT OK-------\r\n"); //主循环 while(1) { bh_temp=BH_Read(); //获取光照强度 printf("The light:%d Lux\r\n",bh_temp); //输出 delay_ms(1000); //延时1秒 } } ``` #### bh_gy30.c ```c #include "bh_gy30.h" #include "myiic.h" //IIC的地址默认为写地址,读地址需要进行加1操作 //默认ADD脚已经接地 //ADD脚接GND时地址为0x46 //ADD脚接VCC时地址为0xB8 #define BH_ADDR 0x46 //全局变量宏定义 #define BH_OFF 0x00 //模块关闭 #define BH_ON 0x01 //模块开启 #define BH_RST 0x07 //模块开启时重启或重置模块 #define BH_MODE1 0x10 //模式1 单位 1 1X 测量时间 120ms //读取光照强度数据 //返回 0-65535 lx u16 BH_Read(void) { u16 bh_value=0; IIC_Start(); //IIC起始信号 IIC_Send_Byte(BH_ADDR+1); //发送读器件地址 IIC_Wait_Ack(); //等待响应 //读数据 bh_value=IIC_Read_Byte(1); //读取数据 bh_value=bh_value<<8; //读取并保存高八位数据 bh_value+=0x00ff&IIC_Read_Byte(0); //读取并保存低八位数据 IIC_Stop(); //IIC停止信号 return bh_value; } //写器件数据 void BH_Write(u8 REG_Address) { //发送器件地址 do { IIC_Start(); //IIC起始信号 IIC_Send_Byte(BH_ADDR); //写地址 } while(IIC_Wait_Ack()); //等待响应,如果器件未接触好将在此死等 IIC_Send_Byte(REG_Address);//发送数据 IIC_Wait_Ack(); //等待响应 IIC_Stop(); //IIC停止信号 } //初始化BH1750 GY30模块 void BH_Init() { BH_Write(BH_ON); //发送启动信号 BH_Write(BH_RST); //清除寄存器 BH_Write(BH_MODE1); //设置为模式1 } ``` #### bh_gy30.h ```c #ifndef __BH_GY30_H #define __BH_GY30_H #include "sys.h" //读取光照强度数据 //返回 0-65535 lx u16 BH_Read(void); //写器件数据 void BH_Write(u8 REG_Address); //初始化BH1750 GY30模块 void BH_Init(void); #endif ``` #### myiic.c ```c #include "myiic.h" #include "delay.h" /******************************************* IIC总线 SCL:PA1 SDA:PA0 ********************************************/ //初始化IIC void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); //使能GPIOB时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //开漏输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1); //PB6,PB7 输出高 } void SDA_OUT(void) { /*定义I2C_SDA的方向为输出*/ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;//开漏输出 GPIO_Init(GPIOA,&GPIO_InitStructure); } void SDA_IN(void) { /*定义I2C_SDA的方向为输入*/ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//PCB有上拉 GPIO_Init(GPIOA,&GPIO_InitStructure); } //产生IIC起始信号 void IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA=1; IIC_SCL=1; delay_us(4); IIC_SDA=0; //START:when CLK is high,DATA change form high to low delay_us(4); IIC_SCL=0; //钳住I2C总线,准备发送或接收数据 } //产生IIC停止信号 void IIC_Stop(void) { SDA_OUT(); //sda线输出 IIC_SCL=0; IIC_SDA=0; //STOP:when CLK is high DATA change form low to high delay_us(4); IIC_SCL=1; IIC_SDA=1; //发送I2C总线结束信号 delay_us(4); } //等待应答信号到来 //返回值:1,接收应答失败 // 0,接收应答成功 u8 IIC_Wait_Ack(void) { u8 ucErrTime=0; SDA_IN(); //SDA设置为输入 IIC_SDA=1;delay_us(1); IIC_SCL=1;delay_us(1); while(READ_SDA) { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL=0; //时钟输出0 return 0; } //产生ACK应答 void IIC_Ack(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=0; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } //不产生ACK应答 void IIC_NAck(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } /******************************************* void IIC_Send_Byte(u8 txd) IIC发送一个字节 返回从机有无应答 1,有应答 0,无应答 ********************************************/ void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); IIC_SCL=0; //拉低时钟开始数据传输 for(t=0;t<8;t++) { IIC_SDA=(txd&0x80)>>7; txd<<=1; delay_us(2); //对TEA5767这三个延时都是必须的 IIC_SCL=1; delay_us(2); IIC_SCL=0; delay_us(2); } } /******************************************* //读1个字节,ack=1时,发送ACK,ack=0,发送nACK ********************************************/ u8 IIC_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN(); //SDA设置为输入 for(i=0;i<8;i++ ) {t6 IIC_SCL=0; delay_us(2); IIC_SCL=1; receive<<=1; if(READ_SDA)receive++; delay_us(1); } if (!ack) IIC_NAck(); //发送nACK else IIC_Ack(); //发送ACK return receive; } /******************************************* //从指定地址读出一个数据 //ReadAddr:开始读数的地址 //返回值 :读到的数据 ********************************************/ u8 iicDevReadByte(u8 devaddr,u8 addr) { u8 temp=0; IIC_Start(); IIC_Send_Byte(devaddr); //发送器件写命令 IIC_Wait_Ack(); IIC_Send_Byte(addr); //发送低地址 IIC_Wait_Ack(); IIC_Start(); IIC_Send_Byte(devaddr|1); //发送器件读命令 IIC_Wait_Ack(); temp=IIC_Read_Byte(0); IIC_Stop(); //产生一个停止条件 return temp; } /******************************************* //连续读多个字节 //addr:起始地址 //rbuf:读数据缓存 //len:数据长度 ********************************************/ void iicDevRead(u8 devaddr,u8 addr,u8 len,u8 *rbuf) { int i=0; IIC_Start(); IIC_Send_Byte(devaddr); IIC_Wait_Ack(); IIC_Send_Byte(addr); //地址自增 IIC_Wait_Ack(); IIC_Start(); IIC_Send_Byte(devaddr|1); IIC_Wait_Ack(); for(i=0; i