描述
<h2>项目要求</h2>
<p><span style="color:#999AAA"> 这是第九届立创电赛的项目;<br>设计一款桌面温湿度检测仪,采用的主控芯片为STM32G030K6T6,温湿度传感器型号是盛思锐的SHT40/AD1B。</span></p>
<h2>项目分析</h2>
<p><span style="color:#999AAA"></span></p>
<ol>
<li>STM32G030K6T6芯片,使用Arm Cortex-M0+内核;最大主频64Mhz;
具有32KB的Flash以及8K的SRAM,供电电压在2.0V~3.6V之间;<br></li>
<li>采用2节5号电池供电,可以省去电源转换电路,初学者也比较容易调试;<br></li>
<li>盛思锐的SHT40是一款灵敏度、精度都较高的温湿度传感器,采用IIC进行通信,可以方便的与单片机进行通信;<br></li>
<li>显示采用LED数码管具有美观、清淅,价格便宜的优点;<br></li>
</ol>
<p><span style="color:#FF0000"> <strong>5.在硬件不变的情况下增加时钟、秒表、电池电压检测、自动休眠等实用功能;
6.因为是电池供电,尽量节能。</strong><span style="color:#999AAA"><br></span></span></p>
<h2></h2>
<p><span style="color:#999AAA">总体设计方案框图
<img src="//image.lceda.cn/oshwhub/0f08ffb1363c4ddea0a9f219837a3fed.png" alt="1111.png"></span></p>
<h2>原理图设计说明</h2>
<p><span style="color:#999AAA">设计原理图<br>
原理图与第九届立创电赛官方提供的一样,具体原理这里不缀述,可参考第九届立创电赛#桌面温湿度检测仪#官方讲座:<br>【手把手教你做温湿度仪:原理图设计-上】<a href="https://www.bilibili.com/video/BV1ui421Y7L6?vd_source=c8ee4f10435a9f625620c244f4dfb939" target="_blank">https://www.bilibili.com/video/BV1ui421Y7L6?vd_source=c8ee4f10435a9f625620c244f4dfb939</a><br>
我的硬件全部是按照官方提供的原理图做的,只是软件部分增加了实用功能。如果你也是按官方提供的原理图做的,想测试一下我的程序的效果,可直接下载的我的开源的软件程序。
不同之处是SHT40温湿度 传感器模块的那个插座,官方是间距:1.27mm 1x4P 弯插,因为比赛时商城一时被买光了,所有这边用1.27mm 2x4P 弯插,把两排并联成一排,与1x4P 弯插一模一样管脚排列。<br>
原理图中SHT40温湿度传感器是一个插座,所以如果自动形成BOM表时,要另外加购传感器模块,型号是:SHT40/AD1B。</span></p>
<p><img src="//image.lceda.cn/oshwhub/7da16f50e08e44ebbb3db2d47f8d7539.png" alt="sh40_原理图.png">
原理图分以下几个部分:(可参考第九届立创电赛#桌面温湿度检测仪#官方讲座)
主控电路,晶振电路,SHT40温湿度传感器模块,三态输出8位移位寄存器,
共阴极三位数码管,唤醒按键,测试LED,两节5号电池盒+防反接保护,SWD下载调试接口。
唤醒按键:同时具有模式转换功能。</p>
<h2>PCB设计说明</h2>
<p><span style="color:#999AAA">PCB的布局、布线与第九届立创电赛官方提供的基本一样,具体可参考第九届立创电赛#桌面温湿度检测仪#官方讲座:【手把手教你做温湿度仪:PCB布局技巧】<a href="https://www.bilibili.com/video/BV15y411i73T?vd_source=c8ee4f10435a9f625620c244f4dfb939" target="_blank">https://www.bilibili.com/video/BV15y411i73T?vd_source=c8ee4f10435a9f625620c244f4dfb939</a><br>
因为是第一次参加这种训练赛,并且是第一次使用STM32,所以我这边全部和比赛官方保持一致,如果你,对STM32G030K6T6芯片有一定的了解,有很多地方可以改进,包括原理图、PCB也可以改进,空闭的引脚都可以引出,可以做很多实验和功能验证。这些只能等我的第二版了。</span></p>
<h2>软件说明</h2>
<p><span style="color:#999AAA">软件部分:
我这个桌面温湿度检测仪与官方最大的不同在于软件部分:
其中:
1、LED数码管显示程序函数;
2、温湿度传感器数据采集和换算函数;
请参考第九届立创电赛官方讲座的讲解,这里再不缀述了。
<span style="color:#FF0000"><strong>扩展功能部分说明有:</strong><span style="color:#999AAA">
<span style="color:#000000"><strong>1、为了实现秒表功能,启用了定时器1,并且设定成1ms中断一次;</strong><span style="color:#999AAA">
在STM32CubeMX中设定定时器1使能,并且定时设成1ms;在主main以中断的形式启动定时器1;
<span style="color:#000000"><strong>2、为了实现时钟功能在低功耗模式下能工作,启用了外部时钟源;</strong><span style="color:#999AAA">
在STM32CubeMX中RTC项目中激活LSE时钟源和日历功能。<br>
<span style="color:#000000"><strong>3、五种模式之间转换;</strong><span style="color:#999AAA">
Modelcharg()为模式转换函数,按键每按住0.5秒钟以上切换一次模式,顺序如下:温湿度->时钟->秒表->电池电压->休眠->温湿度;在时钟模式,进一步判断按键按下情况,分别进行计时设置、分设置操作;在秒表模式,进一步判断按键按下的次数,分别进行计时开始、暂停或复位的操作;具体参考程序mian.c中的函数;
<span style="color:#000000"><strong>4、时钟读取和时钟设置功能;</strong><span style="color:#999AAA">
采用如下两个HAL库函数分别读取时间和日期,
void TaskRTC(void)
{
HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&sDate,RTC_FORMAT_BIN);
}
时钟设置功能:因为只有一个按键,所以只能通过巧妙设计,快速按压按键 二次,如同我们操作鼠标的双击,来切换到时钟和分钟的设定模式。 具体参照我的程序中的时钟设定函数void clockset(void);<br>
时钟显示功能:与温湿度显示原理一样,通过LED数码管显示函数把时和分的高低位显示在第一排和第二排上。因为才两个三位显示器,所以这里只对时间的时、分进行显示。如果要年月日显示原理一模一样的。
这里有所不同的是,增加了闪烁功能,通过设计一个PWM 0.5秒通0.5秒断的信号outpwm来切换显示与不显示,从而达到闪烁的效果。<br>
if (!outpwm )
{<br>
ShowNum(1,2, hour /10 %10,0);
ShowNum(1,3, hour %10,0);<br>
ShowNum(2,2, 18,0);//18是空 字模第18位是空的字模,具有看《增加部分英文字母和特殊字符字模》的说明;
ShowNum(2,3, 18 ,0);//18是空
}
else
{
ShowNum(1,2, 18 ,0);
ShowNum(1,3, 18 ,0);
}
<span style="color:#000000"><strong>5、秒表计时函数;</strong><span style="color:#999AAA">
秒表计时函数是CountTime()函数,先定义一个计时变量CountMinutes,当计时启动时,在定时器1的中断回调函数中,进行CountMinutes++,计时暂停时,停止CountMinutes累加,计时复位时,CountMinutes清0,从而实现计时功能,精度达ms级别,因为显示器只有3位,所以取0.1s为单位显示。<br>
<span style="color:#000000"><strong>6、电池电压测量与显示;</strong><span style="color:#999AAA">
电池电压测量在STM32CubeMX的ADC项选定基准电压和VIN9与Vbat,(此处Vbat的作用是什么,还不明白,有测出来过,但总是固定值,不知其义,有高手知道可以知会一声,) 我们只讨论基准电压Vref和VIN9.
<img src="//image.lceda.cn/oshwhub/6175fde512b949ab9e6166091aeba210.png" alt="ADC1.png">
以下程序就是把基准电压Vref和VIN9读入数组adc1_val中:<br>
HAL_ADC_Start (&hadc1);
HAL_ADC_PollForConversion(&hadc1,10);
adc1_val[i]=HAL_ADC_GetValue (&hadc1);
adc1_val[0]读出基本准电压读数,adc1_val[1]读出VIN9电压读数,就可以算出VIN9的电压=120 <em> VIN9电压读数 / 基准电压读数; 然后按显示温湿度的方法显示出来,
最后显示出来的值,再与万用表测量的值进行比较,修正 一下系数120为122,即:VIN9的电压=122</em>VIN9电压读数/基准电压读数,小数点显得在第1位,可能我这MCU内核电压是1.22v;在显示电池电压时,我在显示器上行显示了英文字母bAt.,是因为我增加了数码管的字模。
<span style="color:#000000"><strong>7、数码管的字模;</strong><span style="color:#999AAA">
因为数码管不仅可以显示数字,通过增加字模数组的值,可以显示其他字符。
数码管的字模数组的程序 gpio.c的最前面,增加后的字模数组:
uint16_t sgh_value[19]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x80,0x40,0x77,0x7c,0x79,0x38,0x78,0x73,0};<br>//0,1,2,3,4,5,6,7,8,9,.,-,A,b,E,L,t,P,空,
这里举例,如果要显示bAt.,只要取位置13、12、16。
我在进入电池电压显示时显示了bAt,进入低功耗模式的倒计时时,显示了SLEEP.
如图:
<img src="//image.lceda.cn/oshwhub/8b4e349fa8ad4e8db3ac3770d5185d32.png" alt="bAt.png"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p><img src="//image.lceda.cn/oshwhub/d57862f444b54542842eccce4eb4e027.png" alt="SLEEP.png">
<span style="color:#000000"><strong>7、进入深度休眠模式函数;</strong><span style="color:#999AAA">
EnterSTOPMode()函数,可自动进入休眠模式,通过计算空闲时间是否达到设定的时间(温湿度模式、时钟、电压模下设定为1分钟自动进入休眠模式,EnterSTOPTime =60000、秒表模式设定为1小时自动进入休眠模式,EnterSTOPTime =60000 * 60),条件满足,就进入STOPMode,此时主控芯片时钟会关闲,以便达到最大程度的节能。
手动进入休眠模式:把模式调到手动进入休眠模式,此时LED显示器显示SLEEP.09 倒计时计数10秒后,进入休眠模式,
休眠模式的意义:这个小仪器设计的初衷是显示温湿度,采用了5号电池供电, 可是经过实际测试,LED显示器显示电流在21-22mA左右。</span></span></p>
<p><img src="//image.lceda.cn/oshwhub/a7a957e602bf46478bf000ca87c28d72.png" alt="22ma.png">
5号电池按某孚碱性电池的容量为1600mAh,可用时间=1600 / 22=72小时,天数=72/24=3天,也就是说2节5号电池,24小时开机,只够用3天,有点少了,所以这个小仪器,如果想24小时开机,就要设计成充电器或充电电池供电。
官方提供下载的程序,经过实际测试是进行SlepMode睡眠模式,睡眠时电流在2.8mA左右。我们再来算一算,待机使用天数,天数=1600 / 2.8/24=23.8天,还是有点少,毕竟就放在那儿没显示,一天偶尔把玩一下,20几天就没电了,
我这个程序,是进行STOPMode休眠模式(停止模式,停止了MCU的时钟),经过测试,待机电流仅0.32ma,经过计算,两节5号电池待机最大时间可到7个月,STOPMode休眠模式此时停止了内部时钟,外部时钟没停止,时钟功能仍然有有效。</p>
<p><img src="//image.lceda.cn/oshwhub/cd2443cb2882459199983825137a2c97.png" alt="326ua.png">
还的一个情况,如果低功耗模式是进入STANDBYMode待机模式,经过测试,整机电流为0.62ma,反尔比STOPMode高,有兴趣的同学可以自行测试一下;
以上都在我有程序mian.c中,请参照我上传的程序附件。<br>
<br></p>
<p><strong>这里贴出主代码块int main(void):请参照我上传的程序附件。</strong>
//倒计时进入休眠模式 倒计时初值ms ,dowmtime=9000; 可以在下面程序中修改,
// 自动进入休眠模式的时间设定 EnterSTOPTime =60000;//等待进入休眠时间60000=1min ,可以在下面程序中修改<br>
... ...</p>
<p>int main(void)
{
/<em> USER CODE BEGIN 1 </em>/
float Temperature=0,Humidity=0;
uint16_t Temp=0,Humi=0;<br>
//计分钟 计0.1 定义变量
uint32_t CountMinutes=0;
uint32_t CountCseconds=0;
uint16_t UP_Disply=0,DOWN_Disply=0;
;
/<em> USER CODE END 1 </em>/</p>
<p>/<em> MCU Configuration--------------------------------------------------------</em>/</p>
<p>/<em> Reset of all peripherals, Initializes the Flash interface and the Systick. </em>/
HAL_Init();</p>
<p>/<em> USER CODE BEGIN Init </em>/</p>
<p>/<em> USER CODE END Init </em>/</p>
<p>/<em> Configure the system clock </em>/
SystemClock_Config();</p>
<p>/<em> USER CODE BEGIN SysInit </em>/</p>
<p>/<em> USER CODE END SysInit </em>/</p>
<p>/<em> Initialize all configured peripherals </em>/
MX_GPIO_Init();
MX_I2C1_Init();
MX_TIM1_Init();
MX_RTC_Init();
MX_ADC1_Init();
/<em> USER CODE BEGIN 2 </em>/
//SN74HC595_Send_Data(SN_DIG,0x00);
//SN74HC595_Send_Data(SN_LED2,0xFF);</p>
<p>/<em> USER CODE END 2 </em>/</p>
<p>/<em> Infinite loop </em>/
/<em> USER CODE BEGIN WHILE </em>/<br>
//以中断的形式启动定时器1
HAL_TIM_Base_Start_IT(&htim1 );<br>
Close_Led();
sTime.Hours=12;
sTime.Minutes =12;
HAL_RTC_SetTime(&hrtc,&sTime,RTC_FORMAT_BIN);
HAL_ADCEx_Calibration_Start(&hadc1);
uint8_t display_h=0;
uint8_t display_m=0;
uint8_t display_sec=0;
while (1)
{
/<em> USER CODE END WHILE </em>/<br>
/<em> USER CODE BEGIN 3 </em>/
//Toggle_Led();
//HAL_Delay(500);
//Scanf_key();
for(i=0;i<3;i++)
{
HAL_ADC_Start (&hadc1);
HAL_ADC_PollForConversion(&hadc1,10);
adc1_val[i]=HAL_ADC_GetValue (&hadc1);
}
Vref=adc1_val[0];
VIN9=adc1_val[1];
Vbat=adc1_val[2];
for(i=0;i<3;i++)
{
adc1_h[i]=adc1_val[i]/256;
adc1_l[i]=adc1_val[i] % 256;
}
GetTemperatureHumidity(&Temperature,&Humidity );
Temp=(uint16_t)(Temperature <em> 10);
Humi=(uint16_t)(Humidity </em> 10);
CountCseconds=(countMiliSeconds/100)%600;
CountMinutes=countMiliSeconds/1000/60;
EnterSTOPMode();//进入深度睡眠模式
Modelcharg();//模式转换
TaskRTC();//读时钟
pwm();//闪烁用脉冲
if (Display_sel==2)//计时器模式
{
CountTime();
}
else
{
Countflag=0;
PB5pushNum=0;
CountTimeStart=0;
countMiliSeconds=0;
}
if (Display_sel!=4)//倒计时进入休眠模式
{
dowmtime=9000;//倒计时初值ms
}<br>
//显示模式选择
switch (Display_sel)
{
case 0://温湿度模式
UP_Disply=Temp;
DOWN_Disply=Humi;
ShowNum(1,1,UP_Disply/100,0);
ShowNum(1,2,UP_Disply/10 %10,1);
ShowNum(1,3,UP_Disply %10,0);
ShowNum(2,1, DOWN_Disply /100,0);
ShowNum(2,2, DOWN_Disply /10 %10,1);
ShowNum(2,3, DOWN_Disply %10,0);
EnterSTOPTime =60000;//等待进入休眠时间60000=1min
break;<br>
case 1://时钟模式
display_h=sTime.Hours;
display_m=sTime.Minutes;
display_sec=sTime.Seconds;
clockset();//时间设定函数
//正常显示时间
if (!clocksetflag)//非时间设定模式--->正常显示时间
{
EnterSTOPTime =60000;//等待进入休眠时间60000=1min
ShowNum(1,2,display_h /10 %10,0);
//ShowNum(1,3,display_h %10,0);
ShowNum(2,2, display_m /10 %10,0);
//ShowNum(2,3, display_m %10,0);
//让点闪烁
if (!outpwm )
{<br>
ShowNum(1,3,display_h %10,0);
ShowNum(2,3, display_m %10,1);
}
else
{
ShowNum(1,3,display_h %10,1);
ShowNum(2,3, display_m %10,0);
}<br>
}
else
{
//clockset();//时间设定函数
}
break;
case 2://秒表模式
UP_Disply=CountMinutes;
DOWN_Disply=CountCseconds;
ShowNum(1,1,UP_Disply/100,0);
ShowNum(1,2,UP_Disply/10 %10,0);
ShowNum(1,3,UP_Disply %10,0);
ShowNum(2,1, DOWN_Disply /100,0);
ShowNum(2,2, DOWN_Disply /10 %10,1);
ShowNum(2,3, DOWN_Disply %10,0);
EnterSTOPTime =60000<em>60;//等待进入休眠时间60000=1min 1h
break;
case 3://电池电压
V_BAT=VIN9</em>122/Vref ;
DOWN_Disply=V_BAT<em>2;
ShowNum(1,1,13,0);//b
ShowNum(1,2,12,0);//A
ShowNum(1,3,16,1);//t.
// ShowNum(1,1,UP_Disply/100,0);
// ShowNum(1,2,UP_Disply/10 %10,0);
// ShowNum(1,3,UP_Disply %10,0);
ShowNum(2,1, DOWN_Disply /100,1);
ShowNum(2,2, DOWN_Disply /10 %10,0);
ShowNum(2,3, DOWN_Disply %10,0);
EnterSTOPTime =60000;//等待进入休眠时间6000=1min<br>
break;
case 4://睡眠模式
ShowNum(1,1,5,0);//S
ShowNum(1,2,15,0);//L
ShowNum(1,3,14,0);//E
ShowNum(2,1, 14,0);//E
ShowNum(2,2,17,1);//P
sleepdstart=1;
ShowNum(2,3,dowmtime/1000,0);//显示倒计时
if (dowmtime==0)
{
//进入睡眠模式
Close_Led();
HAL_SuspendTick(); //暂停滴答定时器,防止通过滴答定时器中断唤醒
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); /</em> 执行WFI指令, 进入深度睡眠模式 */
SystemClock_Config(); //恢复时钟
HAL_ResumeTick(); //恢复滴答定时器
Display_sel=0;
}
break;
default :
break;
}<br>
}
}</p>
<h2>实物展示说明</h2>
<p><span style="color:#999AAA">1.温湿度显示的样子如下:<br>
上面数码管显示温度,下面数码管显示湿度。<br></span></p>
<p><img src="//image.lceda.cn/oshwhub/0ec5c9eab6a741b29a5ef8e7226691bf.jpg" alt="微信图片_20240725200302.jpg">
2.时钟显示的样子如下:<br>
上面数码管显示时,下面数码管显示分,快速点两下按键,可进入时间设定模式。<br>
<img src="//image.lceda.cn/oshwhub/15632bb12f324614ac40200ae2833635.png" alt="setclock.png">
3.秒表显示的样子如下:<br>
上面数码管显示分钟,下面数码管显示秒,精确到0.1秒。<br>
<img src="//image.lceda.cn/oshwhub/0ff59aebe2204a5695e3ac561eb2536f.png" alt="计时显示.png"><br>
4.电池电压显示的样子如下:<br>
上面数码管显示字母BAT,下面数码管电压值。<br></p>
<p><img src="//image.lceda.cn/oshwhub/1092317e2b3c4602981e94064cb8408e.png" alt="显示bat.png">
5.倒计时进入休眠的样子如下:<br>
数码管SLEEP.秒。<br></p>
<p><img src="//image.lceda.cn/oshwhub/abda49fcfa6043808f1393b2e8a45027.png" alt="显示sleep.png"></p>
<h2>注意事项</h2>
<p><span style="color:#999AAA">
1.PCB元件焊接芯片元件放置方向必须放对,有个点标志要与PCB板上的点对应。<br>
2.PCB元件焊接时,要注意管脚不可虚焊,或连锡短路现象。<br>
3.小元件贴片电阻、贴片电容先焊,再焊芯片元件,直插件后焊,不耐热的元件比如LED灯,按键,后焊,并且不作过多停留。<br>
4.如果PCB布局跟我一样,没改过的,温湿度传感器模块是采用4p 1.27mm插件模块,元件朝下,
<span style="color:#000000"> 插反了会烧温湿度传感器模块。<span style="color:#999AAA">
我就第一次插反了烧温湿度传感器模块。最好是电池焊点贴个胶布或其他绝缘的东西。<br></span></span></span></p>
<p><img src="//image.lceda.cn/oshwhub/d84126248598447f82da44b1f12e83af.png" alt="注意22.png"></p>
<p><img src="//image.lceda.cn/oshwhub/bef9beb56e8747c0a8e7828f6360dc7e.png" alt="sh40_22.png">
<span style="color:#999AAA">
5.全部焊接完成后,一定要检查无误后才能接下载器,或接上电池。
6.下载器的3V3与电池最好不要同时接,接了下载器3V3管脚就可以不放电池,放了电池就可以不接下载器的3V3,只接CLK,DIO,GND。下载器的3V3与电池同时接时,质量不好的下载器容易烧坏。
7.下载官方程序时,进入休眠模式时间放长一点,不然一旦进入休眠,很不方便下载程序,下载我这程序没有这方面的问题,我这个进入休眠模式时间1分钟,休眠时,点一下按键,有一分钟的时间,足够时间让你下载程序。</span></p>
<h2>使用说明</h2>
<p><span style="color:#999AAA">
1.唤醒键每按住0.5秒一次就切换模式一下,模式顺序为:温湿度->时钟->秒表->电池电压->休眠->温湿度;<br>
2.自动休眠,温湿度、时钟、电池电压模式下自动进入休眠时间为1分钟,秒表模式下自动进入休眠时间为1小时;<br>
3.时钟模式下,双击唤醒键,进入“时”设置,时数字会闪,唤醒键每点一下,时+1,按住0.5秒确定,进入“分”设置,同样分数字会闪,唤醒键每点一下,分+1,按住0.5秒确定,保存住设置时间;<br>
4.秒表模式下,点一下,开始计时,再点一下暂停计时,双击唤醒键秒表复位;<br>
5.休眠模式下,倒计数9秒后,进入休眠.</span></p>
<h2>演示视频</h2>
<p><span style="color:#999AAA">
</span></p>
-
实物展示.mp4
-
3e567618c9c19d98fbc5191db08c521f.mp4
评论(0)