通过STM32F411微控制器芯片设计一个带温湿度显示的电子钟。该电子钟可以通过DHT11温湿度传感器采集并显示测量到的温湿度。同时该电子钟具有时钟和闹钟功能可以将温湿度、时间和闹钟信息送PC机显示
设计思路:
- 硬件部分:
(1)主控芯片:选择STM32F411微控制器芯片。
(2)温湿度传感器:选择DHT11温湿度传感器。
(3)时钟芯片:选择DS3231时钟芯片。
(4)显示模块:选择OLED显示模块。
(5)按键模块:选择4个按键模块。
- 软件部分:
(1)温湿度采集:通过DHT11传感器采集温湿度数据,并通过串口发送给PC机。
(2)时钟功能:使用DS3231时钟芯片实现时钟功能,包括时间显示、时间设置、闹钟功能等。
(3)显示功能:使用OLED显示模块显示温湿度、时间、闹钟等信息。
(4)按键功能:通过按键模块实现对时钟、闹钟、温湿度等功能的设置和控制。
(5)串口通信:通过串口与PC机进行通信,将温湿度数据发送给PC机。
设计步骤:
- 硬件连接
将DHT11传感器、DS3231时钟芯片、OLED显示模块和按键模块连接到STM32F411微控制器芯片上,具体连接方式可参考各模块的数据手册。
- 软件设计
(1)温湿度采集
使用STM32F411的GPIO口读取DHT11传感器的数据,计算得到温湿度值,然后使用串口将温湿度数据发送给PC机。具体代码如下:
//DHT11读取数据函数
void DHT11_ReadData(void)
{
uint8_t i=0;
uint8_t buf[5]={0};
uint8_t check_sum=0;
DHT11_Data_Out(); //数据线输出
DHT11_Data_Low(); //数据线拉低
delay_ms(20); //延时20ms
DHT11_Data_High(); //数据线拉高
delay_us(30); //延时30us
DHT11_Data_In(); //数据线输入
while(DHT11_Data_Read());//等待DHT11响应
while(!DHT11_Data_Read());//等待DHT11响应结束
while(DHT11_Data_Read());//等待DHT11数据传输开始
for(i=0;i<5;i++) //读取5个字节的数据
{
buf[i]=0;
for(uint8_t j=0;j<8;j++) //读取每个字节的8位数据
{
while(!DHT11_Data_Read());//等待DHT11数据位变化
delay_us(40); //延时40us
if(DHT11_Data_Read()) //如果数据位为1
{
buf[i]|=(1<<(7-j)); //将数据位写入buf数组
}
while(DHT11_Data_Read());//等待数据位变化
}
}
check_sum=buf[0]+buf[1]+buf[2]+buf[3]; //计算校验和
if(check_sum==buf[4]) //校验和正确
{
temperature=buf[2]; //温度值存储在buf[2]中
humidity=buf[0]; //湿度值存储在buf[0]中
}
}
//串口发送温湿度数据函数
void Send_Temp_Hum(void)
{
uint8_t temp_buf[10]={0};
sprintf((char *)temp_buf,"Temp:%d,Hum:%d\r\n",temperature,humidity);
HAL_UART_Transmit(&huart1,temp_buf,strlen((char *)temp_buf),0xff);
}
(2)时钟功能
使用DS3231时钟芯片实现时钟功能,包括时间显示、时间设置、闹钟功能等。具体代码如下:
//时钟初始化函数
void RTC_Init(void)
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
//开启PWR以及BKP备份区域
__HAL_RCC_PWR_CLK_ENABLE();
HAL_PWR_EnableBkUpAccess();
//检查是否第一次上电
if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR0)!=0x32F2) //第一次上电
{
//初始化时钟时间
RTC_TimeStruct.Hours=0x12;
RTC_TimeStruct.Minutes=0x00;
RTC_TimeStruct.Seconds=0x00;
RTC_TimeStruct.TimeFormat=RTC_HOURFORMAT12_PM;
RTC_TimeStruct.DayLightSaving=RTC_DAYLIGHTSAVING_NONE;
RTC_TimeStruct.StoreOperation=RTC_STOREOPERATION_RESET;
HAL_RTC_SetTime(&hrtc,&RTC_TimeStruct,RTC_FORMAT_BIN);
//初始化时钟日期
RTC_DateStruct.Date=0x01;
RTC_DateStruct.Month=0x01;
RTC_DateStruct.Year=0x00;
RTC_DateStruct.WeekDay=RTC_WEEKDAY_MONDAY;
HAL_RTC_SetDate(&hrtc,&RTC_DateStruct,RTC_FORMAT_BIN);
//备份区域写入标志
HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);
}
}
//时钟显示函数
void RTC_ShowTime(void)
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
char time_buf[20]={0};
HAL_RTC_GetTime(&hrtc,&RTC_TimeStruct,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&RTC_DateStruct,RTC_FORMAT_BIN);
sprintf(time_buf,"%02d:%02d:%02d %s",RTC_TimeStruct.Hours,RTC_TimeStruct.Minutes,RTC_TimeStruct.Seconds,RTC_TimeStruct.TimeFormat?"PM":"AM");
OLED_ShowString(0,0,(uint8_t *)time_buf);
sprintf(time_buf,"20%02d-%02d-%02d %s",RTC_DateStruct.Year,RTC_DateStruct.Month,RTC_DateStruct.Date,Week[RTC_DateStruct.WeekDay]);
OLED_ShowString(0,16,(uint8_t *)time_buf);
}
//时钟设置函数
void RTC_SetTime(uint8_t hour,uint8_t min,uint8_t sec,uint8_t am_pm)
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_TimeStruct.Hours=hour;
RTC_TimeStruct.Minutes=min;
RTC_TimeStruct.Seconds=sec;
RTC_TimeStruct.TimeFormat=am_pm;
RTC_TimeStruct.DayLightSaving=RTC_DAYLIGHTSAVING_NONE;
RTC_TimeStruct.StoreOperation=RTC_STOREOPERATION_RESET;
HAL_RTC_SetTime(&hrtc,&RTC_TimeStruct,RTC_FORMAT_BIN);
}
//闹钟设置函数
void RTC_SetAlarm(uint8_t hour,uint8_t min,uint8_t sec,uint8_t am_pm)
{
RTC_AlarmTypeDef RTC_AlarmStruct;
RTC_AlarmStruct.AlarmTime.Hours=hour;
RTC_AlarmStruct.AlarmTime.Minutes=min;
RTC_AlarmStruct.AlarmTime.Seconds=sec;
RTC_AlarmStruct.AlarmTime.TimeFormat=am_pm;
RTC_AlarmStruct.AlarmDateWeekDay=RTC_WEEKDAY_MONDAY;
RTC_AlarmStruct.AlarmMask=RTC_ALARMMASK_DATEWEEKDAY;
RTC_AlarmStruct.AlarmSubSecondMask=RTC_ALARMSUBSECONDMASK_ALL;
RTC_AlarmStruct.Alarm=RTC_ALARM_A;
HAL_RTC_SetAlarm_IT(&hrtc,&RTC_AlarmStruct,RTC_FORMAT_BIN);
}
(3)显示功能
使用OLED显示模块显示温湿度、时间、闹钟等信息。具体代码如下:
//OLED初始化函数
void OLED_Init(void)
{
OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示
OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率
OLED_WR_Byte(80,OLED_CMD); //设置分频因子
OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数
OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64)
OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移
OLED_WR_Byte(0X00,OLED_CMD); //默认为0
OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0]
OLED_WR_Byte(0xA1,OLED_CMD); //设置列地址映射
OLED_WR_Byte(0xC8,OLED_CMD); //设置COM扫描方式
OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置
OLED_WR_Byte(0x12,OLED_CMD); //默认0X12
OLED_WR_Byte(0x81,OLED_CMD); //对比度设置
OLED_WR_Byte(0xFF,OLED_CMD); //1~255 (对比度值,越大越亮)
OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期
OLED_WR_Byte(0xF1,OLED_CMD); //默认0x22(1个时钟周期,0x22=34时钟周期)
OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率
OLED_WR_Byte(0x40,OLED_CMD); //默认0X20,0.77xVcc
OLED_WR_Byte(0xA4,OLED_CMD); //设置全局显示开启[0x00关,0x01开]
OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式[0xa6白底黑字,0xa7黑底白字]
OLED_WR_Byte(0xAF,OLED_CMD); //开启显示
OLED_Clear();
}
//OLED清屏函数
void OLED_Clear(void)
{
uint8_t i,j;
for(i=0;i<8;i++)
{
OLED_WR_Byte(0xb0+i,OLED_CMD);
OLED_WR_Byte(0x00,OLED_CMD);
OLED_WR_Byte(0x10,OLED_CMD);
for(j=0;j<128;j++)
{
OLED_WR_Byte(0,OLED_DATA);
}
}
}
//OLED显示字符串函数
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *str)
{
uint8_t c=0,i=0,j=0;
while (str[j]!='\0')
{
c=str[j]-32;
if(x>128-1)
{
x=0;
y++;
}
if(y>8-1)
{
y=x=0;
OLED_Clear();
}
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
{
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
x+=6;
j++;
}
}
//OLED设置坐标函数
void OLED_Set_Pos(uint8_t x,uint8_t y)
{
OLED_WR_Byte(0xb0+y,OLED_CMD);
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD);
}
(4)按键功能
使用4个按键模块实现对时钟、闹钟、温湿度等功能的设置和控制。具体代码如下:
//按键扫描函数
void Key_Scan(void)
{
static uint8_t key_up=1;
if(key_up&&(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0))
{
key_up=0;
Key1_Press();
}
else if(key_up&&(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==0))
{
key_up=0;
Key2_Press();
}
else if(key_up&&(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==0))
{
key_up=0;
Key3_Press();
}
else if(key_up&&(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==0))
{
key_up=0;
Key4_Press();
}
else if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)&&HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)&&HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)&&HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin))
{
key_up=1;
}
}
//按键1功能函数
void Key1_Press(void)
{
if(!menu_flag)
{
RTC_ShowTime();
menu_flag=1;
}
else
{
menu_flag=0;
}
}
//按键2功能函数
void Key2_Press(void)
{
if(menu_flag)
{
if(menu_index==0)
{
menu_index=3;
}
else
{
menu_index--;
}
}
}
//按键3功能函数
void Key3_Press(void)
{
if(menu_flag)
{
if(menu_index==3)
{
menu_index=0;
}
else
{
menu_index++;
}
}
}
//按键4功能函数
void Key4_Press(void)
{
if(menu_flag)
{
switch(menu_index)
{
case 0: //时间设置
menu_time_flag=1;
break;
case 1: //闹钟设置
menu_alarm_flag=1;
break;
case 2: //温湿度设置
break;
case 3: //退出菜单
menu_flag=0;
break;
default:
break;
}
}
}
(5)串口通信
使用串口与PC机进行通信,将温湿度数据发送给PC机。具体代码如下:
//串口发送温湿度数据函数
void Send_Temp_Hum(void)
{
uint8_t temp_buf[10]={0};
sprintf((char *)temp_buf,"Temp:%d,Hum:%d\r\n",temperature,humidity);
HAL_UART_Transmit(&huart1,temp_buf,strlen((char *)temp_buf),0xff);
}
- 整体流程
(1)初始化各模块,包括DHT11传感器、DS3231时钟芯片、OLED显示模块和按键模块。
(2)循环读取DHT11传感器的温湿度数据,并通过串口发送给PC机。
(3)循环显示时钟时间和日期。
(4)按键扫描,根据按键功能设置时钟、闹钟、温湿度等信息。
(5)定时器中断处理闹钟功能。
- 结束语
通过STM32F411微控制器芯片设计一个带温湿度显示的电子钟。该电子钟可以通过DHT11温湿度传感器采集并显示测量到的温湿度。同时该电子钟具有时钟和闹钟功能,可以将温湿度、时间和闹钟信息送PC机显示。该电子钟可以应用于家庭或办公室等场合,为人们提供准确的时间和温湿度信息
原文地址: https://www.cveoy.top/t/topic/hq15 著作权归作者所有。请勿转载和采集!