*本设计:*
仿真图protues 8.9
程序编译器:keil 5
编程语言:C语言
*设计编号:C0041*
*功能描述:*
通过STM32驱动DHT11温度传感器采集温湿度数据,将温湿度信息显示在LCD1602显示屏上及虚拟串口上。
资料下载链接(可点击)
*源程序(提供源文件)**:*
int main(void)
{
DHT11_Data_TypeDef DHT11_Data;
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
/* 配置SysTick 为1us中断一次 */
SysTick_Init();
LED_GPIO_Config();
//LED1_ON;
LED2_ON;
LED3_ON;
//NVIC_Configuration();
LcdGpioInit();
LCD1602Init();
USART_Config();//初始化串口1
NVIC_Configuration();
printf("rn***dht11 温湿度传感器实验***rn");
/*初始化DTT11的引脚*/
DHT11_Init();
//printf("22n");
dht11_delay_ms(10);
while(1)
{
//调用DHT11_Read_TempAndHumidity读取温湿度,若成功则输出该信息
if( DHT11_Read_TempAndHumidity ( & DHT11_Data ) == SUCCESS)
{
uint8_t index = 0;
char str[20];
printf("rn读取DHT11成功!rnrn湿度为%d.%d %RH ,温度为 %d.%d℃ rn", DHT11_Data.humi_int, DHT11_Data.humi_deci, DHT11_Data.temp_int, DHT11_Data.temp_deci);
sprintf(str, "H:%d.%d T:%d.%d", DHT11_Data.humi_int, DHT11_Data.humi_deci, DHT11_Data.temp_int, DHT11_Data.temp_deci);
LcdWriteCom(0x80);//设置第一行 数据地址指针
for(index = 0; index < 20; index++)
LcdWriteDate(str[index]); //写入数据
}
else
{
printf("Read DHT11 ERROR!rn");
}
Delay_ms(10);
}
}
LCD显示函数
#include "./LCD/bsp_lcd.h"
#include "./systick/bsp_SysTick.h"
uint8_t const table1[]="hello";
/*初始化用到的引脚*/
void LcdGpioInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_WriteBit(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12,Bit_RESET);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init ( GPIOC, &GPIO_InitStruct);
}
/*******************************************************************************
* 函 数 名 :write_com
* 函数功能 :LCD1602 写指令
* 输 入 :无
* 输 出 :无
*******************************************************************************/
void LcdWriteCom(uint8_t com)
{
Delay_us(20);
GPIOC->BSRR = 0x00ff0000;
GPIOC->BSRR = (com);
GPIO_WriteBit(GPIOC,GPIO_Pin_10,Bit_RESET); //LCDRS
GPIO_WriteBit(GPIOC,GPIO_Pin_11,Bit_RESET); //LCDRW
GPIO_WriteBit(GPIOC,GPIO_Pin_12,Bit_RESET); //LCDEN
Delay_us(10);
GPIO_WriteBit(GPIOC,GPIO_Pin_12,Bit_SET); //LCDEN
Delay_us(10);
GPIO_WriteBit(GPIOC,GPIO_Pin_12,Bit_RESET); //LCDEN
Delay_us(10);
}
/*******************************************************************************
* 函 数 名 :write_Date
* 函数功能 :LCD1602 写数据
* 输 入 :无
* 输 出 :无
*******************************************************************************/
void LcdWriteDate(uint8_t date)
{
Delay_us(20);
GPIOC->BSRR = 0x00ff0000;
GPIOC->BSRR = (date);
GPIO_WriteBit(GPIOC,GPIO_Pin_10,Bit_SET); //LCDRS
GPIO_WriteBit(GPIOC,GPIO_Pin_11,Bit_RESET); //LCDRW
GPIO_WriteBit(GPIOC,GPIO_Pin_12,Bit_RESET); //LCDEN
Delay_us(10);
GPIO_WriteBit(GPIOC,GPIO_Pin_12,Bit_SET); //LCDEN
Delay_us(10);
GPIO_WriteBit(GPIOC,GPIO_Pin_12,Bit_RESET); //LCDEN
Delay_us(10);
}
/*******************************************************************************
* 函 数 名 :LCD1602Init
* 函数功能 :LCD1602初始化
* 输 入 :无
* 输 出 :无
*******************************************************************************/
void LCD1602Init(void)
{
uint8_t index=0;
Delay_ms(10);
LcdWriteCom(0x38); //设置16*2显示,8位数据接口
LcdWriteCom(0x0c); //开显示,显示光标且闪烁
LcdWriteCom(0x06);//写一个指针自动加一
LcdWriteCom(0x01);//清屏
Delay_ms(10);//延时一段时间时间,等待LCD1602稳定
LcdWriteCom(0x80);//设置第一行 数据地址指针
for(index=0;index<13;index++)
LcdWriteDate(table1[index]); //写入数据
// LcdWriteCom(0xc0);//设置第二行 数据地址指针
// for(index=0;index<7;index++)
// LcdWriteDate(table2[index]); //写入数据
}
/*******************************************************************************
* 函 数 名 :LCD1602WriteCommand
* 函数功能 :显示指令到屏幕 U D L R S
* 输 入 :comm 字符格式
* 输 出 :无
*******************************************************************************/
void LCD1602WriteCommand(uint8_t comm)
{
LcdWriteCom(0xc0 + 14);
LcdWriteDate(comm); //写入数据
}
SHT11底层驱动代码
#include "./dht11/bsp_dht11.h"
#include "./systick/bsp_SysTick.h"
static void DHT11_GPIO_Config ( void );
static void DHT11_Mode_IPU ( void );
static void DHT11_Mode_Out_PP ( void );
static uint8_t DHT11_ReadByte ( void );
/**
* @brief DHT11 初始化函数
* @param 无
* @retval 无
*/
void DHT11_Init ( void )
{
DHT11_GPIO_Config ();
DHT11_Dout_1; // 拉高GPIOC15
}
//使用水滴计时器不准,于是 采用粗略计时
void dht11_delay_us(int32_t time){
while(time--){
}
}
void dht11_delay_ms(int32_t time){
uint32_t i = 0;
i = time*1400;
while(i--){
}
}
/*
* 函数名:DHT11_GPIO_Config
* 描述 :配置DHT11用到的I/O口
* 输入 :无
* 输出 :无
*/
static void DHT11_GPIO_Config ( void )
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启DHT11_Dout_GPIO_PORT的外设时钟*/
DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );
/*选择要控制的DHT11_Dout_GPIO_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure );
}
/*
* 函数名:DHT11_Mode_IPU
* 描述 :使DHT11-DATA引脚变为上拉输入模式
* 输入 :无
* 输出 :无
*/
static void DHT11_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*选择要控制的DHT11_Dout_GPIO_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
/*设置引脚模式为浮空输入模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
}
/*
* 函数名:DHT11_Mode_Out_PP
* 描述 :使DHT11-DATA引脚变为推挽输出模式
* 输入 :无
* 输出 :无
*/
static void DHT11_Mode_Out_PP(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*选择要控制的DHT11_Dout_GPIO_PORT引脚*/
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化DHT11_Dout_GPIO_PORT*/
GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
}
/*
* 从DHT11读取一个字节
*/
static uint8_t DHT11_ReadByte ( void )
{
uint8_t i, temp=0;
uint8_t try_num = 0;
for(i=0;i<8;i++)
{
temp <<= 1;
//等待从机拉低,表示1Bit数据开始传输
while((DHT11_Dout_IN()==Bit_SET)&& try_num<100 ){
try_num++;
dht11_delay_us(1);
}
//等待从机拉高,开始1Bit数据值
try_num = 0;
while((DHT11_Dout_IN()==Bit_RESET)&& try_num<100){
try_num++;
dht11_delay_us(1);
}
dht11_delay_us(30); //高电平超过28us表示1
if((DHT11_Dout_IN()==Bit_SET))
{
temp |= 1;
} else {
temp |= 0;
}
}
return temp;
}
/*
* 一次完整的数据传输为40bit,高位先出
* 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和
*/
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
/*输出模式*/
DHT11_Mode_Out_PP();
/*主机拉低*/
//printf("rn computer high rn");
DHT11_Dout_0;
/*延时20ms*/
// Delay_ms(18);
dht11_delay_ms(18);
//printf("rn computer low rn");
/*总线拉高 主机延时18us*/
DHT11_Dout_1;
//Delay_us(30); //延时20us
dht11_delay_us(35);
//printf("rn accept rn");
/*主机设为输入 判断从机响应信号*/
DHT11_Mode_IPU();
/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
if(DHT11_Dout_IN()==Bit_RESET)
{
/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while(DHT11_Dout_IN()==Bit_RESET);
/*轮询直到从机发出的 80us 高电平 标置信号结束*/
while(DHT11_Dout_IN()==Bit_SET);
/*开始接收数据*/
DHT11_Data->humi_int= DHT11_ReadByte();
DHT11_Data->humi_deci= DHT11_ReadByte();
DHT11_Data->temp_int= DHT11_ReadByte();
DHT11_Data->temp_deci= DHT11_ReadByte();
DHT11_Data->check_sum= DHT11_ReadByte();
//printf("rnreceiven");
/*读取结束,引脚改为输出模式*/
DHT11_Mode_Out_PP();
/*主机拉高*/
DHT11_Dout_1;
/*检查读取的数据是否正确*/
if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
return SUCCESS;
else
return ERROR;
}
else
return ERROR;
}
/*************************************END OF FILE******************************/
*仿真图(提供源文件):*
阅读全文