描述
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">* 1、项目功能介绍</h3>
<hr class="horizontal-splitline normal-bold-2">
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">采用stm32G030作为主控,SHT40温湿度传感器采集温湿度数据。stm32结合三态移位寄存器通过三位数码管显示实时温度湿度。</p>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt"> </p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">*2、项目属性</h3>
<hr class="horizontal-splitline normal-bold-2">
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">在训练营的基础上,自行设计pcb并验证成功。</p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">* 3、开源协议</h3>
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">在训练营历程上修改。</p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">*4、硬件部分</h3>
<p><img src="//image.lceda.cn/pullimage/LDwj09HwNXbHgTLMZYwS4qnt65qy5fVF91NF6I2c.png"></p>
<p><img src="//image.lceda.cn/pullimage/hw6jYcrSM28PgPDUUf1g5vT4oLLKhrPJq7tYga75.png"></p>
<p> </p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">*5、软件部分</h3>
<p><p>STM32是一款由STMicroelectronics(意法半导体)生产的32位微控制器,广泛应用于嵌入式系统设计。使用STM32进行温湿度检测,通常需要结合一些外部传感器,如DHT11、DHT22、SHT3x等,这些传感器能够检测环境的温度和湿度,并将数据转换为电信号,STM32再通过其ADC(模拟数字转换器)模块读取这些信号,并进行相应的数据处理。</p> <p>将温湿度传感器的数据线连接到STM32的某个GPIO(通用输入输出)引脚上。某些传感器可能还需要连接到电源和地线。</p> <ol> <li> <p>在STM32的固件中,初始化ADC模块,配置相关的GPIO引脚,设置中断服务程序(如果使用中断方式读取数据)。</p> </li> <li> <p>编写温湿度传感器的驱动程序,这通常包括初始化传感器、读取数据、数据解析等功能。</p> </li> <li> <p>通过GPIO引脚与传感器通信,读取温湿度数据。这可能涉及到I2C、SPI或简单的GPIO操作,具体取决于传感器的通信协议。</p> </li> <li> <p>将读取到的原始数据转换为实际的温度和湿度值。这通常需要根据传感器的数据手册进行单位转换和校准。</p> </li> <li> <p>设置温湿度的阈值,当检测到的数据超出这些阈值时,可以触发报警或者控制其他设备(如空调、加热器等)。</p> </li> <li> <p>考虑到功耗,可能需要实现低功耗模式,比如在不需要频繁检测时让STM32进入睡眠模式。</p> </li> </ol></p>
<p>下面笔记是学习32时自制,有问题还请多多指点:</p>
<p>ADC采样</p>
<p>2024年9月9日</p>
<p>11:29</p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/ucf7mVuKmL5z6V9ALr3nyOqxTVo230FK44FykdLu.png"></p>
<p> </p>
<p> </p>
<p>只需在CubeMx中开始相关引脚adc采样通道</p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/SzWuX5zxM1lC2PdL4ppWNqHV7xLDehYQiWon7cSF.png"></p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/agQKxfPDbHOUYOSOfhsP3znVMzvIIyM83vbP9wiQ.png"></p>
<p>CubeMx配置</p>
<p>2024年9月9日</p>
<p>10:56</p>
<p> </p>
<p>创建新工程:</p>
<p>1,芯片选型(正确的芯片型号,正确的封装</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/BYwqS1OiocEeyYJHPlorM7xighJv1y522X2iBn2r.png"></p>
<p>2,Debug选择</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/efmF02XN34FosvWwdOK8CFOfQXvDOivzCI9yt04f.png"></p>
<p>3,时钟配置,先根据需要开启时钟,再对时钟树进行配置</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/3eQlmekq2XRI4dpOzZcZvMxn6E3VvAgG2H9RVaEK.png"></p>
<p> </p>
<p>时钟树配置时要根据板子实际外部晶振进行调整</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/GE1As4b2rbR2onSwwS723K40p9VTnxuhqgLv6Mte.png"></p>
<p>4,GPIO配置</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/nMDGoWyGrf6ofZ97sYV78AE2FXWGNOBSjFtpHX2k.png"></p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/7Hb9t8toDeJ53caeuLEhcG5yFAptfqrpTuUN0XTe.png"></p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/uI7iZFWEGMsHTHED42QzJsPHJHX54ZLfwSTII2LD.png"></p>
<p>Keil5配置</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/g19JFt7GxAW8ZvA4v4XvFHDFDdAPgGhqzdZoo3BL.png"></p>
<p>2024年9月9日</p>
<p>11:02</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/s2GIw5lKj7ljysqkawBJu4mahvSabM6YCwdSHnsG.png"></p>
<p> </p>
<p>lcd驱动(需要外部导入相关库文件)</p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/KucYWajpPU1Kd0SCMPN6SlSKreucSyFanUZeg5Qs.png"></p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/BroCR1ojGlGAiaTTkqNQbqvllvXX8ozn2EjeDfX3.png"></p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/62PYlya4ZakRmweP1GMNp69iR6jFA45YEjRJZEW6.png"></p>
<p>将这三个文件放入所建工程的组文件中(模块化的调用相当是)</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/8Mbxh1hIGr5t4gM74nRUWwaeQfwwOY8xxwaNO1UM.png"></p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/dIw33H44K6EOPYa4IEa4eod4wxsrAVAi02HqN2Ek.png"></p>
<p> </p>
<p>LCD_Init(); //初始化lcd</p>
<p>LCD_Clear(Black);// 清屏并显示初始背景色</p>
<p>LCD_SetBackColor(Black); //背景颜色</p>
<p>LCD_SetTextColor(White); //字体颜色</p>
<p> </p>
<p> </p>
<p>char miao[10];</p>
<p>int hh = 0;</p>
<p>sprintf(miao," %d",hh); // 转换函数 需要包含stdio.h 头文件</p>
<p>//将需要的内容打印到字符串中</p>
<p>//我理解为将后边hh整形数据存入 miao[]数组中,再用下边函数指针取首地址向后输入 LCD_DisplayStringLine(Line1, (u8 *)miao);</p>
<p>//lcd屏幕字符输出函数,行+内容</p>
<p>PWM配置</p>
<p>2024年9月9日</p>
<p>11:27</p>
<p>只需在CubeMx中配置响应的定时器pwm输出通道即可</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/AL1ATwctMzhCSxYZL9wUBFJua0K3nROyjQm4hpim.png"></p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/k5m7fFrIHzZj1WmNfguFLi6qMButReAGz8MnUMSh.png"></p>
<p> </p>
<p>HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);</p>
<p>TIM2->CCR1 = (常数/定时器计数值或定时器溢出值)//控制 tim2 1通道输出pwm占空比</p>
<p> </p>
<p>PWM有效驱动两条代码</p>
<p> </p>
<p>PWM频率:Freq = CK_PSC/(PSC+1)/(ARR+1)</p>
<p>PWM占空比:Duty = CCR/(ARR+1)</p>
<p>PWM分辨率:Reso = 1/(ARR+1)</p>
<p> </p>
<p>TIM定时器PWM1模式与PWM2模式的比较</p>
<p>STM32 定时器的 PWM 存在两种模式,即 PWM1 模式与 PWM2 模式,两种模式相似却又恰恰相反。</p>
<p>PWM1 模式:向上计数,当 TIMx_CNT < TIMx_CCRn 时,定时器 TIMx 的通道 n 为有效电平,否则为无效电平;向下计数,当 TIMx_CNT > TIMx_CCRn 时,定时器 TIMx 的通道 n 为无效电平,否则为有效电平 有效电平,否则为无效电平。</p>
<p> </p>
<p>PWM2 模式:向上计数,当 TIMx_CNT < TIMx_CCRn 时,定时器 TIMx 的通道 n 为无效电平,否则为有效电平;向下计数,当 TIMx_CNT > TIMx_CCRn 时,定时器 TIMx 的通道 n 为有效电平,否则为无效电平 无效电平,否则为有效电平。</p>
<p> </p>
<p>下面是 PWM1 模式与 PWM2 模式的比较表格图,能够比较直观的反映出两者的区别。</p>
<p>两种PWM模式的比较 注:</p>
<p>全文中的 TIMx 表示 STM32 的定时器,x 表示某个定时器,取值需要根据芯片来定;</p>
<p>全文中的 TIMx_CNT,表示定时器 TIMx 的计数器寄存器值;</p>
<p>全文中的 TIMx_CCRn,表示捕获比较寄存器的值,其中 n 表示某个通道,取值为1、2、3、4;</p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/3cECnDdwgUsgY2PHfl8nhbLDXWq1kjsPOoWkH9xV.png"></p>
<p>编码器驱动</p>
<p>2024年9月9日</p>
<p>11:21</p>
<p> </p>
<p>void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //PB12,PB13编码器计数函数</p>
<p>{</p>
<p>if(GPIO_Pin == GPIO_PIN_12)</p>
<p>{</p>
<p>if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12))</p>
<p>{</p>
<p>key_count--;</p>
<p>} else</p>
<p>{</p>
<p>key_count++;</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>搭配下边代码同时使用</p>
<p>if(key_count!=0)</p>
<p>{</p>
<p>key_num += key_count;</p>
<p>key_count = 0;</p>
<p>}</p>
<p> </p>
<p>注意通过中断处理来确定旋转方向</p>
<p> </p>
<p> </p>
<p>void EXTI0_IRQHandler(void)//正转:A的上升沿对应B的低电平;反转:B的上升沿对应A的低电平。</p>
<p>{</p>
<p>if (EXTI_GetITStatus(EXTI_Line0) == SET)//判断编码器A是否为高电平,中断是否触发</p>
<p>{</p>
<p>if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) ==0)//判断编码器B是否为低电平</p>
<p>{</p>
<p>Encoder_Count++;</p>
<p>}</p>
<p>EXTI_ClearITPendingBit(EXTI_Line0);//如果是,则清空标志位</p>
<p>}</p>
<p>}</p>
<p>void EXTI1_IRQHandler(void)</p>
<p>{</p>
<p>if (EXTI_GetITStatus(EXTI_Line1) == SET)//判断编码器B是否为高电平,中断是否触发</p>
<p>{</p>
<p>if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) ==0)//判断编码器A是否为低电平</p>
<p>{</p>
<p>Encoder_Count--;</p>
<p>}</p>
<p>EXTI_ClearITPendingBit(EXTI_Line1);//如果是,则清空标志位</p>
<p>}</p>
<p>}</p>
<p> </p>
<p>分别定义两个中断函数EXTI0_IRQHandler和EXTI1_IRQHandler。基本逻辑跟第一小节讲的一样,先判断第一个中断是不是被触发了,即A管脚是否是上升沿。A管脚接的是GPIOB_0,对应的中断0.然后判断B管脚是不是低电平。</p>
<p>EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line=EXTI_Line0 | EXTI_Line1;//配置中断线 EXTI_InitStructure.EXTI_LineCmd=ENABLE;//开启或关闭中断 EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//定义中断模式 EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//触发中断方式,选择上升沿触发 EXTI_Init(&EXTI_InitStructure);</p>
<p> </p>
<p>两个中断前后优先级区分清楚,先判断一个再判断另一个</p>
<p>外部中断(以按键中断为例)</p>
<p>2024年9月9日</p>
<p>11:09</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/qICnASMuITonD6FotjFZqCEKAc0UGY5SLunkxAwx.png"></p>
<p> </p>
<p>void EXTI1_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);</p>
<p>// 外部中断处理函数 }</p>
<p>void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)</p>
<p>{</p>
<p>//在hal_gpio.c中,是外部中断的回调函数,需放在主函数下</p>
<p>}</p>
<p> </p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/39Inv6TLFaO0wLMNnFZsVzVWrUoSrGWZqV4GASuf.png"></p>
<p> </p>
<p> </p>
<p> </p>
<p>void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)</p>
<p>{</p>
<p>if(GPIO_Pin == GPIO_PIN_12)</p>
<p>{</p>
<p> </p>
<p>}</p>
<p>}//多按键中断回调处理函数</p>
<p>小提示</p>
<p>2024年9月9日</p>
<p>11:01</p>
<p>keil5使用的时候ctrl + alt +空格显示提示词需要有键盘模式</p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/Mh7RrGPj32MGP5kodGopt0PLDTaBlfhKgSogHQMD.png"></p>
<p> </p>
<p> </p>
<p><img style="max-width: 100%;" src="//image.lceda.cn/pullimage/0Zw981N44KLuuAwiL031zOVKV5m7X2vQXfLik355.png"></p>
<p>重定义变量类型</p>
<p>2024年9月9日</p>
<p>10:50</p>
<p>typedef signed char int8_t; //给有符号char,取别名为int8_t</p>
<p>typedef signed short int int16_t; //给有符号短整型short int,取别名int16_t</p>
<p>typedef signed int int32_t; //给有符号整型short int,取别名int32_t</p>
<p>typedef signed __INT64 int64_t; typedef unsigned char uint8_t; //给无符号char,取别名为uint8_t</p>
<p>typedef unsigned short int uint16_t;//给无符号短整型short int,取别名为uint16_t</p>
<p>typedef unsigned int uint32_t; //给无符号整型short int,取别名为uint32_t</p>
<p>typedef unsigned __INT64 uint64_t;</p>
<p>/* 7.18.1.2 */ //和上面一样,取其他别名</p>
<p>/* smallest type of at least n bits */</p>
<p>/* minimum-width signed integer types */</p>
<p>typedef signed char int_least8_t;</p>
<p>typedef signed short int int_least16_t;</p>
<p>typedef signed int int_least32_t;</p>
<p>typedef signed __INT64 int_least64_t;</p>
<p> </p>
<p>/* minimum-width unsigned integer types */</p>
<p>typedef unsigned char uint_least8_t;</p>
<p>typedef unsigned short int uint_least16_t;</p>
<p>typedef unsigned int uint_least32_t;</p>
<p>typedef unsigned __INT64 uint_least64_t;</p>
<p>/* fastest minimum-width signed integer types */</p>
<p>typedef signed int int_fast8_t;</p>
<p>typedef signed int int_fast16_t;</p>
<p>typedef signed int int_fast32_t;</p>
<p>typedef signed __INT64 int_fast64_t;</p>
<p>/* fastest minimum-width unsigned integer types */</p>
<p>typedef unsigned int uint_fast8_t;</p>
<p>typedef unsigned int uint_fast16_t;</p>
<p>typedef unsigned int uint_fast32_t;</p>
<p>typedef unsigned __INT64 uint_fast64_t;</p>
<p>肯能顺序导入不太对,大家有需要自己找下。</p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">*6、BOM清单</h3>
<hr class="horizontal-splitline normal-bold-2">
<p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">主页自动生成。</p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">*7、大赛LOGO验证、</h3>
<p>视频中也是可以看到的</p>
<p><img src="//image.lceda.cn/pullimage/hCIK0fjHActCJiVoQq3pXkqo9e8EHqtcbx0qHCOI.png"></p>
<h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt">* 8、演示您的项目并录制成视频上传</h3>
<p>已上传</p>
评论(0)