实战篇: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

相关文章

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

conda安装GPU版pytorch默认却是cpu版本

《conda安装GPU版pytorch默认却是cpu版本》本文主要介绍了遇到Conda安装PyTorchGPU版本却默认安装CPU的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录一、问题描述二、网上解决方案罗列【此节为反面方案罗列!!!】三、发现的根本原因[独家]3.1 p

Redis指南及6.2.x版本安装过程

《Redis指南及6.2.x版本安装过程》Redis是完全开源免费的,遵守BSD协议,是一个高性能(NOSQL)的key-value数据库,Redis是一个开源的使用ANSIC语言编写、支持网络、... 目录概述Redis特点Redis应用场景缓存缓存分布式会话分布式锁社交网络最新列表Redis各版本介绍旧

IIS 7.0 及更高版本中的 FTP 状态代码

《IIS7.0及更高版本中的FTP状态代码》本文介绍IIS7.0中的FTP状态代码,方便大家在使用iis中发现ftp的问题... 简介尝试使用 FTP 访问运行 Internet Information Services (IIS) 7.0 或更高版本的服务器上的内容时,IIS 将返回指示响应状态的数字代

Python logging模块使用示例详解

《Pythonlogging模块使用示例详解》Python的logging模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查,下面给大家介绍Pythonlogging模... 目录一、为什么使用 logging 模块?二、核心组件三、日志级别四、基本使用步骤五、快速配置(bas

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

查看MySQL数据库版本的四种方法

《查看MySQL数据库版本的四种方法》查看MySQL数据库的版本信息可以通过多种方法实现,包括使用命令行工具、SQL查询语句和图形化管理工具等,以下是详细的步骤和示例代码,需要的朋友可以参考下... 目录方法一:使用命令行工具1. 使用 mysql 命令示例:方法二:使用 mysqladmin 命令示例:方

Java版本不兼容问题详细解决方案步骤

《Java版本不兼容问题详细解决方案步骤》:本文主要介绍Java版本不兼容问题解决的相关资料,详细分析了问题原因,并提供了解决方案,包括统一JDK版本、修改项目配置和清理旧版本残留等步骤,需要的朋... 目录错误原因分析解决方案步骤第一步:统一 JDK 版本第二步:修改项目配置第三步:清理旧版本残留兼容性对

Python datetime 模块概述及应用场景

《Pythondatetime模块概述及应用场景》Python的datetime模块是标准库中用于处理日期和时间的核心模块,本文给大家介绍Pythondatetime模块概述及应用场景,感兴趣的朋... 目录一、python datetime 模块概述二、datetime 模块核心类解析三、日期时间格式化与