*本設(shè)計:*
仿真圖protues 8.9
程序編譯器:keil 5
編程語言:C語言
*設(shè)計編號:C0041*
*功能描述:*
通過STM32驅(qū)動DHT11溫度傳感器采集溫濕度數(shù)據(jù),將溫濕度信息顯示在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)
{
//調(diào)用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);//設(shè)置第一行 數(shù)據(jù)地址指針
for(index = 0; index < 20; index++)
LcdWriteDate(str[index]); //寫入數(shù)據(jù)
}
else
{
printf("Read DHT11 ERROR!rn");
}
Delay_ms(10);
}
}
LCD顯示函數(shù)
#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);
}
/*******************************************************************************
* 函 數(shù) 名 :write_com
* 函數(shù)功能 :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);
}
/*******************************************************************************
* 函 數(shù) 名 :write_Date
* 函數(shù)功能 :LCD1602 寫數(shù)據(jù)
* 輸 入 :無
* 輸 出 :無
*******************************************************************************/
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);
}
/*******************************************************************************
* 函 數(shù) 名 :LCD1602Init
* 函數(shù)功能 :LCD1602初始化
* 輸 入 :無
* 輸 出 :無
*******************************************************************************/
void LCD1602Init(void)
{
uint8_t index=0;
Delay_ms(10);
LcdWriteCom(0x38); //設(shè)置16*2顯示,8位數(shù)據(jù)接口
LcdWriteCom(0x0c); //開顯示,顯示光標(biāo)且閃爍
LcdWriteCom(0x06);//寫一個指針自動加一
LcdWriteCom(0x01);//清屏
Delay_ms(10);//延時一段時間時間,等待LCD1602穩(wěn)定
LcdWriteCom(0x80);//設(shè)置第一行 數(shù)據(jù)地址指針
for(index=0;index<13;index++)
LcdWriteDate(table1[index]); //寫入數(shù)據(jù)
// LcdWriteCom(0xc0);//設(shè)置第二行 數(shù)據(jù)地址指針
// for(index=0;index<7;index++)
// LcdWriteDate(table2[index]); //寫入數(shù)據(jù)
}
/*******************************************************************************
* 函 數(shù) 名 :LCD1602WriteCommand
* 函數(shù)功能 :顯示指令到屏幕 U D L R S
* 輸 入 :comm 字符格式
* 輸 出 :無
*******************************************************************************/
void LCD1602WriteCommand(uint8_t comm)
{
LcdWriteCom(0xc0 + 14);
LcdWriteDate(comm); //寫入數(shù)據(jù)
}
SHT11底層驅(qū)動代碼
#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 初始化函數(shù)
* @param 無
* @retval 無
*/
void DHT11_Init ( void )
{
DHT11_GPIO_Config ();
DHT11_Dout_1; // 拉高GPIOC15
}
//使用水滴計時器不準(zhǔn),于是 采用粗略計時
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--){
}
}
/*
* 函數(shù)名:DHT11_GPIO_Config
* 描述 :配置DHT11用到的I/O口
* 輸入 :無
* 輸出 :無
*/
static void DHT11_GPIO_Config ( void )
{
/*定義一個GPIO_InitTypeDef類型的結(jié)構(gòu)體*/
GPIO_InitTypeDef GPIO_InitStructure;
/*開啟DHT11_Dout_GPIO_PORT的外設(shè)時鐘*/
DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );
/*選擇要控制的DHT11_Dout_GPIO_PORT引腳*/
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
/*設(shè)置引腳模式為通用推挽輸出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*設(shè)置引腳速率為50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*調(diào)用庫函數(shù),初始化DHT11_Dout_GPIO_PORT*/
GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure );
}
/*
* 函數(shù)名:DHT11_Mode_IPU
* 描述 :使DHT11-DATA引腳變?yōu)樯侠斎肽J?
* 輸入 :無
* 輸出 :無
*/
static void DHT11_Mode_IPU(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*選擇要控制的DHT11_Dout_GPIO_PORT引腳*/
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
/*設(shè)置引腳模式為浮空輸入模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;
/*設(shè)置引腳速率為50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*調(diào)用庫函數(shù),初始化DHT11_Dout_GPIO_PORT*/
GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
}
/*
* 函數(shù)名:DHT11_Mode_Out_PP
* 描述 :使DHT11-DATA引腳變?yōu)橥仆燧敵瞿J?
* 輸入 :無
* 輸出 :無
*/
static void DHT11_Mode_Out_PP(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*選擇要控制的DHT11_Dout_GPIO_PORT引腳*/
GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;
/*設(shè)置引腳模式為通用推挽輸出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*設(shè)置引腳速率為50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*調(diào)用庫函數(shù),初始化DHT11_Dout_GPIO_PORT*/
GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);
}
/*
* 從DHT11讀取一個字節(jié)
*/
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數(shù)據(jù)開始傳輸
while((DHT11_Dout_IN()==Bit_SET)&& try_num<100 ){
try_num++;
dht11_delay_us(1);
}
//等待從機拉高,開始1Bit數(shù)據(jù)值
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;
}
/*
* 一次完整的數(shù)據(jù)傳輸為40bit,高位先出
* 8bit 濕度整數(shù) + 8bit 濕度小數(shù) + 8bit 溫度整數(shù) + 8bit 溫度小數(shù) + 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");
/*主機設(shè)為輸入 判斷從機響應(yīng)信號*/
DHT11_Mode_IPU();
/*判斷從機是否有低電平響應(yīng)信號 如不響應(yīng)則跳出,響應(yīng)則向下運行*/
if(DHT11_Dout_IN()==Bit_RESET)
{
/*輪詢直到從機發(fā)出 的80us 低電平 響應(yīng)信號結(jié)束*/
while(DHT11_Dout_IN()==Bit_RESET);
/*輪詢直到從機發(fā)出的 80us 高電平 標(biāo)置信號結(jié)束*/
while(DHT11_Dout_IN()==Bit_SET);
/*開始接收數(shù)據(jù)*/
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");
/*讀取結(jié)束,引腳改為輸出模式*/
DHT11_Mode_Out_PP();
/*主機拉高*/
DHT11_Dout_1;
/*檢查讀取的數(shù)據(jù)是否正確*/
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******************************/
*仿真圖(提供源文件):*
閱讀全文