硬件配置
stm32f103c8t6
DHT11(温湿度传感器)
BH1750(光照度传感器)
OLED
micro USB数据传输线
软件配置
sys->Debug->Serial Wrie
RCC->HSE->Crystal/Cerarnic Resonator
PC13->GPIO_Out
TIM1->Clock Source->Internal Clock
Parameter Settings
为后面DHT11的延时us起作用
TIM2->Clock Source->Internal Clock
Parameter Settings
NVIC Settings->TIM2 global interrupt
USB->Device(FS) USB_DEVICE->Class For FS IP->Communication Device Class (Virtual Port Com)
Clock Configuration :48 To USB(MHz)
DHT11代码编写 DHT11是一款温湿度一体化的数字传感器,该传感器包括一个电阻式测湿元件和一个NTC测温元件,并与一个高性能8位单片机连接。通过单片机微处理器简单的电路连接就能够实时的采集湿度和温度。DHT11与STM32之间能采用简单的单总线进行通讯,仅需一个IO口。
本次IO口使用的是PA8
dht11.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #ifndef __DHT11_H #define __DHT11_H #include "stm32f1xx_hal.h" #define DHT11_IO_IN() {GPIOA->CRH&=0XFFFFFFF0;GPIOA->CRH|=8;} #define DHT11_IO_OUT() {GPIOA->CRH&=0XFFFFFFF0;GPIOA->CRH|=3;} #define DHT11_DQ_IN HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8) uint8_t DHT11_Init (void ) ;uint8_t DHT11_Read_Data (uint8_t *humiH,uint8_t *humiL,uint8_t *tempH,uint8_t *tempL) ;uint8_t DHT11_Read_Byte (void ) ;uint8_t DHT11_Read_Bit (void ) ;uint8_t DHT11_Check (void ) ;void DHT11_Rst (void ) ; #endif
dht11.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 #include "dht11.h" #include "tim.h" void delay_us (uint16_t us) { uint16_t differ = 0xffff -us-5 ; __HAL_TIM_SET_COUNTER(&htim1,differ); HAL_TIM_Base_Start(&htim1); while (differ < 0xffff -5 ){ differ = __HAL_TIM_GET_COUNTER(&htim1); } HAL_TIM_Base_Stop(&htim1); } void DHT11_Rst (void ) { DHT11_IO_OUT(); HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET); HAL_Delay(20 ); HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_SET); delay_us(30 ); } uint8_t DHT11_Check (void ) { uint8_t retry=0 ; DHT11_IO_IN(); while (DHT11_DQ_IN&&retry<100 ) { retry++; delay_us(1 ); }; if (retry>=100 )return 1 ; else retry=0 ; while (!DHT11_DQ_IN&&retry<100 ) { retry++; delay_us(1 ); }; if (retry>=100 )return 1 ; return 0 ; } uint8_t DHT11_Read_Bit (void ) { uint8_t 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 ); if (DHT11_DQ_IN)return 1 ; else return 0 ; } uint8_t DHT11_Read_Byte (void ) { uint8_t i,dat; dat=0 ; for (i=0 ;i<8 ;i++) { dat<<=1 ; dat|=DHT11_Read_Bit(); } return dat; } uint8_t DHT11_Read_Data (uint8_t *humiH,uint8_t *humiL,uint8_t *tempH,uint8_t *tempL) { uint8_t buf[5 ]; uint8_t i; DHT11_Rst(); if (DHT11_Check()==0 ) { for (i=0 ;i<5 ;i++) { buf[i]=DHT11_Read_Byte(); } if ((buf[0 ]+buf[1 ]+buf[2 ]+buf[3 ])==buf[4 ]) { *humiH=buf[0 ]; *humiL=buf[1 ]; *tempH=buf[2 ]; *tempL=buf[3 ]; } }else return 1 ; return 0 ; } uint8_t DHT11_Init (void ) { GPIO_InitTypeDef GPIO_InitStruct = {0 }; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_SET); DHT11_Rst(); return DHT11_Check(); }
在main.c中的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include "dht11.h" uint8_t humidityH; uint8_t humidityL; uint8_t temperatureH; uint8_t temperatureL; int main (void ) { DHT11_Init(); while (1 ) { DHT11_Read_Data(&humidityH,&humidityL,&temperatureH,&temperatureL) } }
BH1750代码编写 BH1750是一种用于两线式串行总线接口的数字型光强度传感器集成电路。这种集成电路可以根据收集的光线强度数据来调整液晶或者键盘背景灯的亮度。
BH1750引出了时钟线和数据线,单片机通过I2C协议可以与BH1750模块通讯。
前面我们配置了I2C1,PB6接SCL,PB7接SDA
bh1750.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #ifndef __BH1750_H #define __BH1750_H #include "main.h" uint16_t Get_BH1750_Value (void ) ;#define BH1750_ADDR_WRITE 0x46 #define BH1750_ADDR_READ 0x47 typedef enum { POWER_OFF_CMD = 0x00 , POWER_ON_CMD = 0x01 , RESET_REGISTER = 0x07 , CONT_H_MODE = 0x10 , CONT_H_MODE2 = 0x11 , CONT_L_MODE = 0x13 , ONCE_H_MODE = 0x20 , ONCE_H_MODE2 = 0x21 , ONCE_L_MODE = 0x23 } BH1750_MODE; #endif
bh1750.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 #include "bh1750.h" #include "i2c.h" #define bh1750_i2c hi2c1 static uint8_t BH1750_Send_Cmd (BH1750_MODE cmd) ;static uint8_t BH1750_Read_Dat (uint8_t * dat) ;static uint16_t BH1750_Dat_To_Lux (uint8_t * dat) ;static uint8_t BH1750_Send_Cmd (BH1750_MODE cmd) { return HAL_I2C_Master_Transmit(&bh1750_i2c, BH1750_ADDR_WRITE, (uint8_t *)&cmd, 1 , 0xFFFF ); } static uint8_t BH1750_Read_Dat (uint8_t * dat) { return HAL_I2C_Master_Receive(&bh1750_i2c, BH1750_ADDR_READ, dat, 2 , 0xFFFF ); } static uint16_t BH1750_Dat_To_Lux (uint8_t * dat) { uint16_t lux = 0 ; lux = dat[0 ]; lux <<= 8 ; lux |= dat[1 ]; lux = (int )(lux / 1.2 ); return lux; } uint16_t Get_BH1750_Value (void ) { uint8_t dat[2 ] = {0 }; uint16_t lux; if (HAL_OK != BH1750_Send_Cmd(ONCE_H_MODE)) { return 0 ; } HAL_Delay(120 ); if (HAL_OK != BH1750_Read_Dat(dat)) { return 0 ; } lux = BH1750_Dat_To_Lux(dat); return lux; }
在main.c中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "bh1750.h" uint16_t Light; int main (void ) { while (1 ) { Light=Get_BH1750_Value(); } }
虚拟串口输出和OLED显示 在主函数中我们使用VCP虚拟串口输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 #include "main.h" #include "i2c.h" #include "tim.h" #include "usb_device.h" #include "gpio.h" #include "stdio.h" #include "oled.h" #include "dht11.h" #include "bh1750.h" #include "usbd_cdc_if.h" char oledBuf[20 ];uint8_t humidityH; uint8_t humidityL; uint8_t temperatureH; uint8_t temperatureL; uint16_t Light;void SystemClock_Config (void ) ;int main (void ) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USB_DEVICE_Init(); MX_TIM2_Init(); MX_TIM1_Init(); MX_I2C1_Init(); OLED_Init(); OLED_ColorTurn(0 ); OLED_DisplayTurn(0 ); OLED_Clear(); DHT11_Init(); HAL_TIM_Base_Start_IT(&htim2); while (1 ) { Light=Get_BH1750_Value(); DHT11_Read_Data(&humidityH,&humidityL,&temperatureH,&temperatureL); usb_printf("Light:%d Lx\r\n" ,Light); usb_printf("Hum:%d.%d %% Temp:%d.%d C\r\n" ,humidityH,humidityL,temperatureH,temperatureL); HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13); HAL_Delay(1000 ); } }
编写TIM2中断回调函数实现oled的显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void HAL_TIM_PeriodElapsedCallback (TIM_HandleTypeDef *htim) { if (htim==&htim2) { sprintf (oledBuf,"Light:%dLx" ,Light); OLED_ShowString(0 ,0 ,(uint8_t *)oledBuf,16 ); sprintf (oledBuf,"Hum:%d.%d %%" ,humidityH,humidityL); OLED_ShowString(0 ,16 ,(uint8_t *)oledBuf,16 ); sprintf (oledBuf,"Temp:%d.%d C" ,temperatureH,temperatureL); OLED_ShowString(0 ,32 ,(uint8_t *)oledBuf,16 ); OLED_Refresh(); } }
程序资源