实战篇:GY-906红外测温模块 + 万年历(定时器计数中断版本) -STM32篇

本文主要是介绍实战篇:GY-906红外测温模块 + 万年历(定时器计数中断版本) -STM32篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发

       向上代码兼容GD32F450ZGT6中使用

       后续项目主要在下面该专栏中发布:

https://blog.csdn.net/qq_62316532/category_12608431.html?spm=1001.2014.3001.5482

       感兴趣的点个关注收藏一下吧!

       电机驱动开发可以跳转:

GD32F103RCT6/GD32F303RCT6-实战项目-无刷电机驱动(1)_gd32f103rct6例程-CSDN博客

       BMS电源系统开发可以跳转:暂未放链接

演示视频:

GY-906+数字万年历演示视频

介绍

从本小节开始将会对常用模块进行组合和小作业测试的方式去进行教学,博客后续发表的方式为:stm32版本+GD32版本

本节讲的是GY906红外测温模块的使用以及数字万年历的使用,其中数字万年历采用定时器计数中断制作。

GY-906 是一种常用的红外温度测量模块,广泛应用于非接触式的温度检测场景。这种模块的核心元件通常是 MLX90614 红外温度传感器芯片,由 Melexis 公司生产。MLX90614 芯片结合了先进的红外传感技术和信号处理电路,能够测量物体的表面温度而无需直接接触。

使用资源介绍

stm32f103c8t6:

两路I2C,一个通用定时器

1.其中PB8、PB9用于I2C和OLED显示屏通讯,用于显示数据信息

2.PB8、PA15用于I2C和GY-906模块通讯获取红外温度值

3.定时器3用于产生500Ms的中断,叠加2次后使得秒数+1,作为万年历的时基。

定时器3初始化:

定时器用于时基的产生,驱动我们本次万年历的时钟基础。

//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //TIM3时钟使能//定时器TIM3初始化,简单进行定时器初始化,设置 预装载值 和 分频系数TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断//中断优先级NVIC设置NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
}

对其进行初始化以产生500Ms的中断:

 TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms

GY-906模块的初始化

参考商家链接:
https://pan.baidu.com/s/1V4IX0PKG8vDOionICghSTwicon-default.png?t=N7T8https://pan.baidu.com/s/1V4IX0PKG8vDOionICghSTw

理后如下:

GY-906.c文件:
#include "GY-906.h"/*******************************************************************************
* Function Name  : Mlx90614_Configuration
* Description    : Mlx90614_Configuration
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void Mlx96014_Configuration(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_15;//SCLGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;//SDAGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_Init(GPIOA,&GPIO_InitStructure);SDA_H;SCL_H; 
}/*******************************************************************************
* Function Name  : SMBus_StartBit
* Description    : 在SMBus上生成START条件
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SMBus_StartBit(void)
{SDA_H;               // Set SDA line SMBus_Delay(1);      // Wait a few microseconds SCL_H;               // Set SCK line  SMBus_Delay(5);      // Generate bus free time between StopSDA_L;               // Clear SDA lineSMBus_Delay(10);     // Hold time after (Repeated) Start// Condition. After this period, the first clock is generated.//(Thd:sta=4.0us min)SCL_L;               // Clear SCK lineSMBus_Delay(2);      // Wait a few microseconds
}/*******************************************************************************
* Function Name  : SMBus_StopBit
* Description    : Generate STOP condition on SMBus
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/void SMBus_StopBit(void)
{SCL_L;                // Clear SCK lineSMBus_Delay(5);       // Wait a few microsecondsSDA_L;                // Clear SDA lineSMBus_Delay(5);       // Wait a few microsecondsSCL_H;                // Set SCK lineSMBus_Delay(10);      // Stop condition setup time(Tsu:sto=4.0us min)SDA_H;                // Set SDA line
}/*******************************************************************************
* Function Name  : SMBus_SendByte
* Description    : 在SMBus上发送一个字节
* Input          : Tx_buffer
* Output         : None
* Return         : None
*******************************************************************************/
u8 SMBus_SendByte(u8 Tx_buffer)
{u8        Bit_counter;u8        Ack_bit;u8        bit_out;for(Bit_counter=8; Bit_counter; Bit_counter--){if (Tx_buffer&0x80){bit_out=1;       // If the current bit of Tx_buffer is 1 set bit_out}else{bit_out=0;      // else clear bit_out}SMBus_SendBit(bit_out);           // Send the current bit on SDATx_buffer<<=1;                    // Get next bit for checking}Ack_bit=SMBus_ReceiveBit();           // Get acknowledgment bitreturn        Ack_bit;
}/*******************************************************************************
* Function Name  : SMBus_SendBit
* Description    : Send a bit on SMBus
* Input          : bit_out
* Output         : None
* Return         : None
*******************************************************************************/
void SMBus_SendBit(u8 bit_out)
{if(bit_out==0){SDA_L;   }else{SDA_H;}SMBus_Delay(2);                            // Tsu:dat = 250ns minimumSCL_H;                                     // Set SCK lineSMBus_Delay(10);                           // High Level of Clock PulseSCL_L;                                     // Clear SCK lineSMBus_Delay(10);                           // Low Level of Clock Pulse
//        SMBUS_SDA_H();                       // Master release SDA line ,return;
}
/*******************************************************************************
* Function Name  : SMBus_ReceiveBit
* Description    : 在SMBus上接收一位
* Input          : None
* Output         : None
* Return         : Ack_bit
*******************************************************************************/
u8 SMBus_ReceiveBit(void)
{u8 Ack_bit;SDA_H;             //?????????,????SCL_H;             // Set SCL lineSMBus_Delay(2);    // High Level of Clock Pulseif (SMBUS_SDA_PIN){Ack_bit=1;}else{Ack_bit=0;}SCL_L;                    // Clear SCL lineSMBus_Delay(4);           // Low Level of Clock Pulsereturn   Ack_bit;
}
/*******************************************************************************
* Function Name  : SMBus_ReceiveByte
* Description    : 在SMBus上接收一个字节
* Input          : ack_nack
* Output         : None
* Return         : RX_buffer
*******************************************************************************/
u8 SMBus_ReceiveByte(u8 ack_nack)
{u8        RX_buffer;u8        Bit_Counter;for(Bit_Counter=8; Bit_Counter; Bit_Counter--){if(SMBus_ReceiveBit())         // Get a bit from the SDA line{RX_buffer <<= 1;           // If the bit is HIGH save 1  in RX_bufferRX_buffer |=0x01;}else{RX_buffer <<= 1;           // If the bit is LOW save 0 in RX_bufferRX_buffer &=0xfe;}}SMBus_SendBit(ack_nack);           // Sends acknowledgment bitreturn RX_buffer;
}/*******************************************************************************
* Function Name  : SMBus_Delay
* Description    : 1us
* Input          : time
* Output         : None
* Return         : None
*******************************************************************************/
void SMBus_Delay(u16 time)
{u16 i, j;for (i=0; i<4; i++){for (j=0; j<time; j++);}
}/******************************************************************************** Function Name  : SMBus_ReadMemory* Description    : 从RAM/EEPROM读取数据* Input          : slaveAddress, command* Output         : None* Return         : Data
*******************************************************************************/
u16 SMBus_ReadMemory(u8 slaveAddress, u8 command)
{u16 data;               // Data storage (DataH:DataL)u8 Pec;                 // PEC byte storageu8 DataL=0;             // Low data byte storageu8 DataH=0;             // High data byte storageu8 arr[6];              // Buffer for the sent bytesu8 PecReg;              // Calculated PEC byte storageu8 ErrorCounter;        // Defines the number of the attempts for communication with MLX90614ErrorCounter=0x00;                                // Initialising of ErrorCounterslaveAddress <<= 1;        //2-7???????do{
repeat:SMBus_StopBit();                //If slave send NACK stop comunication--ErrorCounter;                 //Pre-decrement ErrorCounterif(!ErrorCounter)               //ErrorCounter=0?{break;                      //Yes,go out from do-while{}}SMBus_StartBit();               //Start conditionif(SMBus_SendByte(slaveAddress))//Send SlaveAddress ???Wr=0????????{goto  repeat;               //Repeat comunication again}if(SMBus_SendByte(command))     //Send command{goto    repeat;             //Repeat comunication again}SMBus_StartBit();                //Repeated Start conditionif(SMBus_SendByte(slaveAddress+1))  //Send SlaveAddress ???Rd=1????????{goto        repeat;           //Repeat comunication again}DataL = SMBus_ReceiveByte(ACK);   //Read low data,master must send ACKDataH = SMBus_ReceiveByte(ACK);   //Read high data,master must send ACKPec = SMBus_ReceiveByte(NACK);    //Read PEC byte, master must send NACKSMBus_StopBit();                  //Stop conditionarr[5] = slaveAddress;        arr[4] = command;arr[3] = slaveAddress+1;         //Load array arrarr[2] = DataL;                 arr[1] = DataH;                arr[0] = 0;                   PecReg=PEC_Calculation(arr);     //Calculate CRC}while(PecReg != Pec);                //If received and calculated CRC are equal go out from do-while{}data = (DataH<<8) | DataL;       //data=DataH:DataLreturn data;
}/*******************************************************************************
* Function Name  : PEC_calculation
* Description    : 计算接收字节的PEC
* Input          : pec[]
* Output         : None
* Return         : pec[0]-this byte contains calculated crc value
*******************************************************************************/
u8 PEC_Calculation(u8 pec[])
{u8         crc[6];u8        BitPosition=47;u8        shift;u8        i;u8        j;u8        temp;do{/*Load pattern value 0x000000000107*/crc[5]=0;crc[4]=0;crc[3]=0;crc[2]=0;crc[1]=0x01;crc[0]=0x07;/*Set maximum bit position at 47 ( six bytes byte5...byte0,MSbit=47)*/BitPosition=47;/*Set shift position at 0*/shift=0;/*Find first "1" in the transmited message beginning from the MSByte byte5*/i=5;j=0;while((pec[i]&(0x80>>j))==0 && i>0){BitPosition--;if(j<7){j++;}else{j=0x00;i--;}}/*End of while *//*Get shift value for pattern value*/shift=BitPosition-8;/*Shift pattern value */while(shift){for(i=5; i<0xFF; i--){if((crc[i-1]&0x80) && (i>0)){temp=1;}else{temp=0;}crc[i]<<=1;crc[i]+=temp;}/*End of for*/shift--;}/*End of while*//*Exclusive OR between pec and crc*/for(i=0; i<=5; i++){pec[i] ^=crc[i];}/*End of for*/}while(BitPosition>8); /*End of do-while*/return pec[0];
}/******************************************************************************** Function Name  : SMBus_ReadTemp* Description    : 计算并返回温度* Input          : None* Output         : None* Return         : SMBus_ReadMemory(0x00, 0x07)*0.02-273.15
*******************************************************************************/
float SMBus_ReadTemp(void)
{   return SMBus_ReadMemory(SA, RAM_ACCESS|RAM_TOBJ1)*0.02-273.15;//绝对零度
}
/*********************************END OF FILE*********************************/

在主函数中进行初始化:

Mlx96014_Configuration();

万年历设计:

首先定义本次使用到的变量:

u8 sec = 0;
u8 min = 10;
u8 hour=23;
u8 date = 19;
u8 month = 6;
u16 year = 2024;
u8 day_max=31;

其中day_max为最大天数,用于确定当前月份的最大天数是多少

判断内容如下:

 if(month==2){day_max=28;}else if(month==4||month==6||month==9||month==11){day_max=30;}else{day_max=31;}

根据不同月份,去对天数进行判断,

一年一共有365天或者366天,平年有365天,闰年有366天,闰年每隔4年一次。

平年的2月是28天,闰年2月是29天。

4月、6月、9月、11月各是30天。

1月、3月、5月、7月、8月、10月、12月各是31天。

接下来就是在定时器中断函数中对万年历的基础代码进行编写:

 if(i==2){i=0;sec++;if(sec>=60){sec=0;min++;if(min>=60){min=0;hour++;if(hour>=24){hour=0;date++;if(date>=day_max){date=0;month++;if(month>=12){year++;									 }}}}}}

在定时器500Ms的中断时间作为基础时间基数的情况下,通过秒数的累加,去驱动整个万年历进行工作

主函数

主函数中要做的就很简单,因为逻辑代码在中断里面已经做完了,所以主函数中只需要完成OLED的显示和基础功能的初始化即可!

       OLED_ShowNum(		5,	15,year,4,12);OLED_ShowString(30,	15,"/",12);//6*12 “ABC”				OLED_ShowNum(		35,	15,month,2,12);OLED_ShowString(50,	15,"/",12);//6*12 “ABC”	OLED_ShowNum(		55,	15,date,2,12);OLED_ShowNum(	15,	25,hour,2,12);OLED_ShowString(30,	25,"/",12);//6*12 “ABC”	OLED_ShowNum(		35,	25,min,2,12);OLED_ShowString(	50,	25,"/",12);//6*12 “ABC”	OLED_ShowNum(		55,	25,sec,2,12);OLED_ShowString(0,0,Temperatures,16);//6*12 “ABC”	OLED_Refresh();

总结:

经过本小结,希望大家能够掌握GY-906的使用,以及用stm32所提供的定时器去完成对万年历的设计!

这篇关于实战篇:GY-906红外测温模块 + 万年历(定时器计数中断版本) -STM32篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1078151

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

Jenkins构建Maven聚合工程,指定构建子模块

一、设置单独编译构建子模块 配置: 1、Root POM指向父pom.xml 2、Goals and options指定构建模块的参数: mvn -pl project1/project1-son -am clean package 单独构建project1-son项目以及它所依赖的其它项目。 说明: mvn clean package -pl 父级模块名/子模块名 -am参数

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类