ARM嵌入基础应用 16_第1页
ARM嵌入基础应用 16_第2页
ARM嵌入基础应用 16_第3页
ARM嵌入基础应用 16_第4页
ARM嵌入基础应用 16_第5页
已阅读5页,还剩49页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第15章

RTC时钟与DS18B20传感器作者:黄克亚2025年5月本章概要CONTENTSRTC时钟DS18B20时序与函数驱动BKP寄存器DS18B20简介与功能特性带温度显示的电子万年历项目15.1RTC时钟STM32F103微控制器内部也集成了一个RTC模块,可以实现不间断计时,大大简化系统软硬件设计难度。15.1RTC时钟15.1.1RTC简介RTC(Real-TimeClock),即实时时钟。实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。RTC及其时钟都使用备用存储区域,而备用存储区域使用VBAT备用电源(一般为纽扣电池),所以主电源断电或系统复位也不影响RTC的工作。15.1RTC时钟15.1.2RTC主要特性可编程的预分频系数:分频系数最高为220。32位的可编程计数器,可用于较长时间段的测量。2个分离的时钟:用于APB1接口的PCLK1和RTC时钟三种RTC的时钟源:HSE时钟除以128;LSE振荡器时钟;LSI振荡器时钟。2个独立的复位类型:APB1接口由系统复位;RTC核心只能由后备域复位。3个专门的可屏蔽中断:闹钟中断,秒中断,溢出中断。RTC主要特性15.1RTC时钟15.1.3RTC内部结构第一部分(APB1接口)用来和APB1总线相连。此单元还包含一组16位寄存器,可通过APB1总线对其进行读写操作。第二部分(RTC核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是RTC的预分频模块,它可编程产生最长为1s的RTC时间基准TR_CLK。第二个模块是一个32位的可编程计数器,可被初始化为当前的系统时间。15.1RTC时钟15.1.4RTC复位过程RTC核心又称为后备区域,即图中加阴影部分,系统电源正常时由VDD(即3.3V)供电,当VDD电源被切断,它们仍然由VBAT(钮扣电池)维持供电。系统复位或从待机模式唤醒后,RTC的设置和时间维持不变,即后备区域独立工作。15.2备份寄存器(BKP)备份寄存器处于后备区域,不受复位影响。15.2备份寄存器(BKP)15.2.1BKP简介备份寄存器是42个16位的寄存器,可用来存储84个字节的用户应用程序数据。它们处在备份域里,当VDD电源被切断,它们仍然由VBAT维持供电。当系统在待机模式下被唤醒,或系统复位,或电源复位时,他们也不会被复位。此外,BKP控制寄存器用来管理侵入检测和RTC校准功能。复位后,对备份寄存器和RTC的访问被禁止,并且备份域被保护以防止可能存在的意外的写操作。15.2备份寄存器(BKP)15.2.2BKP特性20字节数据后备寄存器(中容量和小容量产品),或84字节数据后备寄存器(大容量和互联型产品)。用来管理防侵入检测并具有中断功能的状态/控制寄存器。用来存储RTC校验值的校验寄存器。在PC13引脚(当该引脚不用于侵入检测时)上输出RTC校准时钟,RTC闹钟脉冲或者秒脉冲。1234BKP特性15.3RTC时钟的操作对RTC时钟的操作主要是初始化RTC,之后只要读取时钟数值即可15.3RTC时钟的操作14.1.2I2C总线的数据传送打开相应的时钟先就需要打开备份区域时钟。而一般操作RTC,还会用到一个时钟,就是电源时钟,在电源控制里面有操作RTC的一些设置,所以还要将电源控制的时钟打开。其参考代码如下:01使能备份寄存器操作可以使用PWR_BackupAccessCmd()函数,它只有一个参数,也就是设置的状态,因要使能所以设为ENABLE。02RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//打开电源时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//打开BKP备份区域时钟复位备份寄存器当然这个操作不要每次都执行,因为备份区域的复位将导致之前存在的数据丢失,所以要不要复位,视情况而定。可以使用BKP_DeInit()函数复位备份寄存器。0315.3RTC时钟的操作14.1.2I2C总线的数据传送设置外部低速时钟要使用外部的低速时钟来控制RTC,代码为:04RCC_LSEConfig(RCC_LSE_ON);//设置外部低速晶振(LSE),使用外设低速晶振。使能RTC时钟打开RTC,代码为:05在开启外部低速时钟的时候,确定它是否成功起振,需检测外部低速时钟是否开启。代码为:while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);/*检查指定的RCC标志位设置与否,等待低速晶振(LSE)就绪*/等待它起振好了之后将它作为RTC的时钟,代码为:RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//设置RTC时钟(RTCCLK),选择LSE作为RTC时钟RCC_RTCCLKCmd(ENABLE);//使能RTC时钟在对RTC连续操作的时候还要检测它是否执行完成,才能够接着对它进行操作,所以操作完之后再检测是否操作完成。代码为:RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成15.3RTC时钟的操作14.1.2I2C总线的数据传送等待RTC时钟寄存器同步要其参考代码如下:06RTC_WaitForSynchro();//等待RTC寄存器同步开启秒中断要读取时钟,每秒更新一次,所以开启秒中断。其参考代码如下:07RTC_ITConfig(RTC_IT_SEC,ENABLE);//使能RTC秒中断,然后等待操作完成。RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成。设置RTC时钟的预分频要进行32768分频。其参考代码如下:08RTC_SetPrescaler(32768-1);//设置RTC预分频的值然后等待操作完成RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成设置初始化时间设置初始化时间也就是将要初始化的时钟存入到32位寄存器。这里原理就是,直接将对应的时间数据转换为秒数值写入到32位寄存器中,每当这个32位寄存器加1,那么比0时0分0秒,多了一秒就是0时0分1秒。因此到时候直接读取寄存器值即可。0915.3RTC时钟的操作15.3.2.RTC时间写入初始化RTC时间写入初始化,分为两种情况:一种情况是第一次使用RTC,需要对RTC完全初始化,即15.3.1所介绍的所有步骤均应包含在内,还需要将当前时间对应数值写入到RTC_CNT寄存器当中,并向BKP_DR1寄存器中写入数值0XA5A5,表示已经初始化过RTC寄存器;另一种情况是断电恢复或是上电复位,而不希望复位RTC寄存器后备区域,此时只需要等待RTC寄存器同步和使能RTC秒中断即可,具体代码会在文中后续部分贴出。15.4RTC与BKP相关库函数介绍RTC与BKP库函数接口,具体应用将会在项目实例中详细介绍。15.4RTC与BKP相关库函数15.4.1函数PWR_BackupAccessCmd函数名PWR_BackupAccessCmd函数原形voidPWR_BackupAccessCmd(FunctionalStateNewState)功能描述使能或者失能RTC和后备寄存器访问输入参数NewState:RTC和后备寄存器访问的新状态,这个参数可以取:ENABLE或者DISABLE输出参数无返回值无先决条件无被调用函数无15.4.2函数BKP_DeInit()函数名BKP_DeInit函数原形voidBKP_DeInit(void)功能描述将外设BKP的全部寄存器重设为缺省值输入参数无输出参数无返回值无先决条件无被调用函数RCC_BackupResetCmd例:/*EnableaccesstotheRTCandbackupregisters*/PWR_BackupAccessCmd(ENABLE);例:/*ResettheBKPregisters*/BKP_DeInit();15.4RTC与BKP相关库函数15.4.3函数RCC_LSEConfigRCC_LSE:该参数设置了LSE的状态函数名RCC_LSEConfig函数原形voidRCC_LSEConfig(u32RCC_LSE)功能描述设置外部低速晶振(LSE)输入参数RCC_LSE:LSE的新状态,参阅Section:RCC_LSE查阅更多该参数允许取值范围输出参数无返回值无先决条件无被调用函数无例:/*EnabletheLSE*/RCC_LSEConfig(RCC_LSE_ON);RCC_LSE描述RCC_LSE_OFFLSE晶振OFFRCC_LSE_ONLSE晶振ONRCC_LSE_BypassLSE晶振被外部时钟旁路15.4RTC与BKP相关库函数15.4.4函数RCC_GetFlagStatusRCC_FLAG:给出了所有可以被函数RCC_GetFlagStatus检查的标志位列表。函数名RCC_GetFlagStatus函数原形FlagStatusRCC_GetFlagStatus(u8RCC_FLAG)功能描述检查指定的RCC标志位设置与否输入参数RCC_FLAG:待检查的RCC标志位参阅Section:RCC_FLAG查阅更多该参数允许取值范围输出参数无返回值RCC_FLAG的新状态(SET或者RESET)先决条件无被调用函数无RCC_FLAG描述RCC_FLAG_HSIRDYHSI晶振就绪RCC_FLAG_HSERDYHSE晶振就绪RCC_FLAG_PLLRDYPLL就绪RCC_FLAG_LSERDYLSI晶振就绪RCC_FLAG_LSIRDYLSE晶振就绪RCC_FLAG_PINRST管脚复位RCC_FLAG_PORRSTPOR/PDR复位9RCC_FLAG_SFTRST软件复位RCC_FLAG_IWDGRSTIWDG复位RCC_FLAG_WWDGRSTWWDG复位RCC_FLAG_LPWRRST低功耗复位例:/*TestifthePLLclockisreadyornot*/FlagStatusStatus;Status=RCC_GetFlagStatus(RCC_FLAG_PLLRDY);15.4RTC与BKP相关库函数15.4.5函数RCC_RTCCLKConfigRCC_RTCCLKSource:该参数设置了RTC时钟(RTCCLK)函数名RCC_RTCCLKConfig函数原形voidRCC_RTCCLKConfig(u32RCC_RTCCLKSource)功能描述设置RTC时钟(RTCCLK)输入参数RCC_RTCCLKSource:定义RTCCLK参阅Section:RCC_RTCCLKSource查阅更多该参数允许取值范围输出参数无返回值无先决条件RTC时钟一经选定即不能更改,除非复位后备域被调用函数无RCC_RTCCLKSource描述RCC_RTCCLKSource_LSE

选择LSE作为RTC时钟RCC_RTCCLKSource_LSI

选择LSI作为RTC时钟RCC_RTCCLKSource_HSE_Div128

选择HSE时钟频率除以128作为RTC时钟例:/*SelecttheLSEasRTCclocksource*/RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);15.4RTC与BKP相关库函数15.4.6函数RCC_RTCCLKCmd15.4.7函数RTC_WaitForSynchro函数名RCC_RTCCLKCmd函数原形voidRCC_RTCCLKCmd(FunctionalStateNewState)功能描述使能或者失能RTC时钟输入参数NewState:RTC时钟的新状态,这个参数可以取:ENABLE或者DISABLE输出参数无返回值无先决条件该函数只有在通过函数RCC_RTCCLKConfig选择RTC时钟后,才能调用被调用函数无函数名RCC_RTCCLKCmd函数名RTC_WaitForSynchro函数原形voidRTC_WaitForSynchro(void)功能描述等待RTC寄存器与RTC的APB时钟同步输入参数无输出参数无返回值无先决条件无被调用函数无例:/*EnabletheRTCclock*/RCC_RTCCLKCmd(ENABLE);例:/*WaituntiltheRTCregistersaresynchronizedwithRTCAPBclock*/RTC_WaitForSynchro();15.4RTC与BKP相关库函数15.4.8函数RTC_WaitForLastTask函数名RTC_WaitForLastTask函数原形voidRTC_WaitForLastTask(void)功能描述等待最近一次对RTC寄存器的写操作完成输入参数无输出参数无返回值无先决条件无被调用函数无15.4.10函数RTC_SetPrescaler函数名RTC_SetPrescaler函数原形voidRTC_SetPrescaler(u32PrescalerValue)功能描述设置RTC预分频的值输入参数PrescalerValue:新的RTC预分频值输出参数无返回值无先决条件在使用本函数前必须先调用函数RTC_WaitForLastTask(),等待标志位RTOFF被设置被调用函数RTC_EnterConfigMode()RTC_ExitConfigMode()例:/*WaituntillastwriteoperationonRTCregistersisterminated*/RTC_WaitForLastTask();/*SetsAlarmvalueto0x10*/RTC_SetAlarm(0x10);例:/*WaituntillastwriteoperationonRTCregistersisterminated*/RTC_WaitForLastTask();/*SetsPrescalervalueto0x7A12*/RTC_SetPrescaler(0x7A12);15.4RTC与BKP相关库函数15.4.9函数RTC_ITConfigRTC_IT:输入参数RTC_IT使能或者失能RTC的中断。函数名RTC_ITConfig函数原形voidRTC_ITConfig(u16RTC_IT,FunctionalStateNewState)功能描述使能或者失能指定的RTC中断输入参数1RTC_IT:待使能或者失能的RTC中断源参阅Section:RTC_IT查阅更多该参数允许取值范围输入参数2NewState:RTC中断的新状态这个参数可以取:ENABLE或者DISABLE输出参数无返回值无先决条件在使用本函数前必须先调用函数RTC_WaitForLastTask(),等待标志位RTOFF被设置被调用函数无例:/*WaituntillastwriteoperationonRTCregistersisterminated*/RTC_WaitForLastTask();/*Alarminterruptenabled*/RTC_ITConfig(RTC_IT_ALR,ENABLE);RTC_IT描述RTC_IT_OW溢出中断使能RTC_IT_ALR闹钟中断使能RTC_IT_SEC秒中断使能15.4RTC与BKP相关库函数15.4.11函数RTC_SetCounter函数名RTC_SetCounter函数原形voidRTC_SetCounter(u32CounterValue)功能描述设置RTC计数器的值输入参数CounterValue:新的RTC计数器值输出参数无返回值无先决条件在使用本函数前必须先调用函数RTC_WaitForLastTask(),等待标志位RTOFF被设置被调用函数RTC_EnterConfigMode()RTC_ExitConfigMode()15.4.12函数RTC_GetCounter()函数名RTC_GetCounter函数原形u32RTC_GetCounter(void)功能描述获取RTC计数器的值输入参数无输出参数无返回值RTC计数器的值先决条件无被调用函数无例:/*WaituntillastwriteoperationonRTCregistersisterminated*/RTC_WaitForLastTask();/*SetsCountervalueto0xFFFF5555*/RTC_SetCounter(0xFFFF5555);例:/*Getsthecountervalue*/u32RTCCounterValue;RTCCounterValue=RTC_GetCounter();15.4RTC与BKP相关库函数15.4.13函数BKP_ReadBackupRegister函数名BKP_ReadBackupRegister函数原形u16BKP_ReadBackupRegister(u16BKP_DR)功能描述从指定的后备寄存器中读出数据输入参数BKP_DR:数据后备寄存器输出参数无返回值指定的后备寄存器中的数据先决条件无被调用函数无15.4.15函数RCC_ClearFlag函数名RCC_ClearFlag函数原形voidRCC_ClearFlag(void)功能描述清除RCC的复位标志位输入参数RCC_FLAG:清除的RCC复位标志位,可以清除的复位标志位有:RCC_FLAG_PINRST,RCC_FLAG_PORRST,RCC_FLAG_SFTRST,RCC_FLAG_IWDGRST,RCC_FLAG_WWDGRST,RCC_FLAG_LPWRRST输出参数无返回值无先决条件无被调用函数无例如:/*ReadDataBackupRegister1*/u16Data;Data=BKP_ReadBackupRegister(BKP_DR1);例如:/*Cleartheresetflags*/RCC_ClearFlag();15.4RTC与BKP相关库函数15.4.14函数BKP_WriteBackupRegisterBKP_DR:参数BKP_DR用来选择数据后备寄存器函数名BKP_WriteBackupRegister函数原形voidBKP_WriteBackupRegister(u16BKP_DR,u16Data)功能描述向指定的后备寄存器中写入用户程序数据输入参数1BKP_DR:数据后备寄存器参阅Section:BKP_DR查阅更多该参数允许取值范围输入参数2Data:待写入的数据输出参数无返回值无先决条件无被调用函数无BKP_DR描述BKP_DR描述BKP_DR1选中数据寄存器1BKP_DR6选中数据寄存器6BKP_DR2选中数据寄存器2BKP_DR7选中数据寄存器7BKP_DR3选中数据寄存器3BKP_DR8选中数据寄存器8BKP_DR4选中数据寄存器4BKP_DR9选中数据寄存器9BKP_DR5选中数据寄存器5BKP_DR10选中数据寄存器10例:/*Write0xA587toDataBackupRegister1*/BKP_WriteBackupRegister(BKP_DR1,0xA587);15.5DS18B20温度传感器温度传感器则提供了感知周围温度的手段,是嵌入式系统常用且实用的扩展功能。15.5DS18B20温度传感器15.5.1功能特性与内部结构DS18B20是由Dallas半导体公司推出的一种单总线接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。单总线接口具有简洁且经济的特点,可使用户轻松地组建传感器网络,DS18B20测量温度范围为-55~+125℃,可编程配置9~12有效数据位数,对应0.5、0.25、0.125和0.0625转换精度。测量数据直接以单总线的数字方式传输,大大提高了系统的抗干扰性。图15-2DS18B20内部结构15.5DS18B20温度传感器15.5.2数据组件数据组件包括64位光刻ROM、高速缓存RAM和EEPROM存储器。1.光刻ROM2.高速缓存RAM光刻ROM总共64位,只能读不能写,其中前8位是产品家族码,中间48位是DS18B20的序列号,最后8位是前面56位的循环冗余校验码。每片DS18B20的ROM编码各不相同。高速缓存RAM总共9个字节,用来存放各类数据,各字节的作用如下:字节0、字节1:存放当前16位温度转换结果,字节1为高字节,字节0为低字节。D15~D11:5位,符号位S,表示温度正负,0表示正温度,1表示负温度。D10~D4:共7位,温度值的整数位。D3~D0:共4位,温度值的小数位。15.5DS18B20温度传感器高速缓存RAM字节2、字节3:依次为高温触发器TH和低温触发器TL,用来临时存放用户设定的温度报警上限值和下限值。字节4:配置寄存器,用来临时存放用户设定的配置数据。D7固定为0,D4~D0固定为1,R1、R0为温度转换精度选择控制位R1R0分辨率转换精度最大转换时间009位0.5℃93.75ms0110位0.25℃187.5ms1011位0.125℃375ms1112位0.0625℃750ms字节5~字节7:保留字节字节8:CRC校验字节,其内容为高速缓存RAM前8个字节内容的循环冗余校验值。3.EEPROM存储器EEPROM存储器共3个字节,分别与高速缓存RAM的字节2(TH)、字节3(TL)、字节4(配置寄存器)相对应,用来保存用户对DS18B20的设定值。15.5DS18B20温度传感器15.5.3访问命令DS18B20的ROM命令表命令代码用法说明读ROM33H读取DS18B20温度传感器ROM中的64位编码。匹配ROM55H发出此命令之后,接着发出64位ROM编码,访问单总线上与该编码相对应的DS18B20。跳过ROMCCH忽略64位的ROM序列号的匹配而直接访问单总线上的DS18B20,适用于单片工作。搜索ROMF0H获取单总线上各DS18B20的64位光刻ROM序列号。报警搜索ECH执行该命令后,只有温度超过设定值上限或下限的DS18B20才作出响应。DS18B20的存储控制命令命令代码用法说明温度转换44H启动DS18B20进行温度转换,结果存入内部高速缓存RAM的字节0、字节1中。写高速缓存RAM4EH命令后要紧随1~3个字节的待写人的数据。用于将数据依次写入TH、TL和配置寄存器中。读高速缓存RAMBEH命令执行后,DS18B20会依次将高速缓存RAM中的字节0至字节8的内容发送到单总线上。复制高速缓存RAM48H将高速缓存RAM中字节2至字节4的内容复制到片内EEPROM中。读EEPROMB8H将片内EEPROM的内容对应地复制到高速缓存RAM的字节2至字节4中。读电源供供电方式B4H读取DS18B20的供电方式,0:寄生供电方式,1:外部电源供电。15.5DS18B20温度传感器15.5.4引脚功能与接口电路DS18B20具有3引脚的TO-92和8引脚的SOIC两种封装形式。各封装形式下的引脚分布如图所示,其中NC表示空引脚,不与任何电路连接,GND为接地引脚,DQ为数据输入/输出引脚,VDD为可选的供电电源引脚。DS18B20可以采用DQ引脚输入寄生电源供电,也可以采用VDD引脚连接独立电源供电。开发板实际电路15.5DS18B20温度传感器15.5.5读写时序与驱动函数引脚定义将实验平台使用的引脚、端口以及电平操作函数采用宏定义的形式写入到传感器头文件当中。01GPIO配置DS18B20连接微控制器PE4引脚,对其进行初始化,因采用单总线方式通信,一条数据线既需要发送数据又需要接收数据,还需要分别编写输入配置函数和输出配置函数。02参考代码如下:#definedq(GPIO_Pin_4)//PE4#defineGPIO_ds18b20GPIOE#defineds18b20_dq_HGPIO_SetBits(GPIO_ds18b20,dq)#defineds18b20_dq_LGPIO_ResetBits(GPIO_ds18b20,dq)参考代码如下:voidds18b20_init()/*DS18B20端口初始化函数*/{ GPIO_InitTypeDefGPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); GPIO_InitStructure.GPIO_Pin=dq; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIO_ds18b20,&GPIO_InitStructure);}15.5DS18B20温度传感器15.5.5读写时序与驱动函数voidDQININT()/*GPIO输入配置函数*/{GPIO_InitTypeDefGPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=dq;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIO_ds18b20,&GPIO_InitStructure); }voidDQOUTINT()/*GPIO输出配置函数*/{GPIO_InitTypeDefGPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=dq;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIO_ds18b20,&GPIO_InitStructure); }初始化03参考代码如下:voidds18b20init(){DQOUTINT();//配置输出ds18b20_dq_L;delay_us(480);//延时480微妙ds18b20_dq_H;delay_us(480);//延时480微妙}15.5DS18B20温度传感器15.5.5读写时序与驱动函数写时序DS18B20字节写入程序首先将数据引脚配置为输出模式,随后拉低总线15μs,如果待发送数据位为1则拉高总线,如果待发送数据位为0则继续拉低总线,延时60μs,循环8次即可完成一个字节的发送。04voidds18b20wr(u8dat){u8i=0;DQOUTINT();//输出for(i=0;i<8;i++){ds18b20_dq_L;//拉低总线delay_us(15);//延时15微妙if((dat&0x01)==1)ds18b20_dq_H;elseds18b20_dq_L;delay_us(60);//延时60微妙ds18b20_dq_H;//拉高总线dat>>=1;//准备下一位数据的发送 }}15.5DS18B20温度传感器15.5.5读写时序与驱动函数DS18B20字节读取程序首先配置引脚为输出模式,拉低总线4μs,再释放总线10μs,然后配置引脚为输入模式,读取引脚电平,并将其移入读入数据字节当中,依次类推,循环8次即可完成一个字节的读取。读时序05DS18B20字节读取程序首先配置引脚为输出模式,拉低总线4μs,再释放总线10μs,然后配置引脚为输入模式,读取引脚电平,并将其移入读入数据字节当中,循环8次即可完成一个字节的读取。u8DS18b20rd(){u8i=0,value=0;for(i=0;i<8;i++){value>>=1;DQOUTINT();//输出ds18b20_dq_L;//拉低delay_us(4);//延时4微妙ds18b20_dq_H;delay_us(10);//延时10微妙DQININT();//输入配置if(GPIO_ReadInputDataBit(GPIO_ds18b20,dq)==1){value|=0x80;//读数据从低位开始}delay_us(45);//延时45微妙}returnvalue;}15.5DS18B20温度传感器15.5.6读取温度参考代码如下:doublereadtemp(){ u16temp; u8low,high; doublevalue; ds18b20init(); //初始化

ds18b20wr(0xcc); //发送忽略ROM指令

ds18b20wr(0x44); //发送温度转换指令

delay_ms(800); ds18b20init(); //初始化

ds18b20wr(0xcc); //发送忽略ROM指令

ds18b20wr(0xbe); //发读暂存器指令

low=DS18b20rd(); //温度的低八位

high=DS18b20rd(); //温度的高八位

temp=high; temp=(temp<<8)+low; if((temp&0xf800)==0xf800) { temp=(~temp)+1; //负数原码为取反加1 value=temp*(-0.0625);//乘以12位的分辨率

} else {value=temp*0.0625;//正数原码、补码相同} returnvalue;}读取一次D18B20温度的操作步骤如下:初始化DS18B20。因为单片工作,所以跳过ROM操作。发送温度转换命令,延时等待转换完成。再次初始化,跳过ROM操作。发送读取温度命令读取温度值。15.5DS18B20温度传感器15.5.6读取温度参考代码如下:voidds18b20_start_convert()//启动温度转换{ds18b20init();//初始化ds18b20wr(0xcc);//发送忽略ROM指令ds18b20wr(0x44);//发送温度转换指令}doubleds18b20_read_operate() //读取温度操作{u16temp;u8low,high;doublevalue;ds18b20init(); //初始化ds18b20wr(0xcc); //发送忽略ROM指令ds18b20wr(0xbe); //发读暂存器指令low=DS18b20rd(); //温度的低八位high=DS18b20rd(); //温度的高八位temp=high;temp=(temp<<8)+low;if((temp&0xf800)==0xf800){temp=(~temp)+1; //负数原码为取反加1value=temp*(-0.0625);}else{value=temp*0.0625; //正数原码、补码相同}returnvalue;}由上述代码可知,温度读取函数有一个长达800ms的延时,对系统实时性影响很大,为跳过这一长延时,可以将整个温度读取函数拆分为启动温度转换和读取温度操作两个函数,以便在某些场合进行特殊应用,15.6带温度显示的电子万年历本项目实现带温度显示的电子万年历,同时可以通过串口实现网络时间同步。15.6带温度显示的电子万年历15.6.1项目分析一是利用STM32F103微控制器的RTC模块实现电子万年历,要求主电源断电而计时不间断,利用USART串口通信功能自动将PC时间同步到实验平台,实现时间精确设置。01

数码管动态显示02串口初始化03对RTC进行初始化,写入当前时间数值。04RTC同步05开启秒中断15.6带温度显示的电子万年历15.6.1项目分析另一个功能是利用单总线温度传感器DS18B20实时检测环境温度进行DS18B20初始化DS18B20实时检测环境温度无限循环结构中读取温度项目交换了操作顺序,即在一个读取周期内,先读取上一次转换完成的温度数据。然后再启动下一次转换,其余时间交给CPU的其他任务,成功地实现了多任务融合。15.6带温度显示的电子万年历第一步:复制第14章创建工程模板文件夹到桌面,并将文件夹改名为“14RTC+USART+18B20”,将原工程模板编译一下,直到没有错误和警告为止。13I2C+24C0214RTC+USART+18B20第二步:为工程模板的ST_Driver项目组添加3个RTC操作需要用到的源文件,分别为stm32f10x_bkp.c、stm32f10x_pwr.c和stm32f10x_rtc.c,这3个文件均位于..\Libraries\STM32F10x_StdPeriph_Driver\src目录下。15.6.2项目实施第三步:点击“File/New”新建两个文件,将其改名为RTC.C和RTC.H并保存到工程模板下的APP文件夹中。并将RTC.C文件添加到APP项目组下。15.6带温度显示的电子万年历项目实施第四步:在RTC.C文件中输入如下源程序,在程序中首先包含RTC.H头文件,并重新声明本文件中需要引用的外部变量。然后创建3个函数,分别为RTC_NVIC_Config()、rtc_init()和clockinit_RTC()。为实现电子万年历功能,编写了3个日历处理函数,分别为RTC_GetCountValue()、RTC_GetDateTime()和RTC_GetWeek()。RTC_NVIC_Config()函数用于RTC秒中断优先级设置。rtc_init()函数用于RTC初始化,只在第一次设置RTC模块时调用。clockinit_RTC()为复位初始化函数,在main函数中调用。函数RTC_GetCountValue()将时间信息转换为RTC计数值,一般用于时间设定。函数RTC_GetDateTime()将RTC计数值转换为日历,一般用于时间读取。函数RTC_GetWeek由日期自动计算出星期。RTC源程序,非放映时双击右侧图标可打开15.6带温度显示的电子万年历项目实施第五步:在RTC.H文件中输入如下源程序,其中条件编译格式不变,只要更改一下预定义变量名称即可,需要将刚定义函数的声明加到头文件当中。参考代码如下:#ifndef_RTC_H#define_RTC_H#include"stm32f10x.h"voidrtc_init(void);voidclockinit_RTC(void);voidRTC_GetDateTime(void);u8RTC_GetWeek(u16year,u8month,u8day);u32RTC_GetCountValue(u16year,u8month,u8day,u8hour,u8minute,u8second);#endif15.6带温度显示的电子万年历项目实施第六步:新建两个文件,将其改名为ds18b20.c和ds18b20.h并保存到工程模板下的APP文件夹中。将ds18b20.c文件添加到APP项目组下。在ds18b20.c文件中输入DS18B20驱动源程序,包括端口初始化、输入配置、输出配置、DS18B20初始化、字节写入、字节读取和读温度函数,相关代码在上一节均有详细讲解,在此就不将代码再次贴出。在ds18b20.h文件中输入如下源程序,其中条件编译格式不变,需要将引脚宏定义和驱动函数声明添加到头文件当中。参考代码如下:#ifndef_DS18B20_H#define_DS18B20_H#include"stm32f10x.h"#include"systick.h"/*引脚宏义*/#definedq(GPIO_Pin_4)//PE4#defineGPIO_ds18b20GPIOE#defineds18b20_dq_HGPIO_SetBits(GPIO_ds18b20,dq)#defineds18b20_dq_LGPIO_ResetBits(GPIO_ds18b20,dq)/*DS18B20驱动函数声明*/voidds18b20_init(void);voidDQOUTINT(void);voidDQININT(void);voidds18b20init(void);voidds18b20wr(u8dat);u8DS18b20rd(void);doublereadtemp(void);voidds18b20_start_convert(void);doubleds18b20_read_operate(void);#endif15.6带温度显示的电子万年历项目实施第七步:在main.h文件的中间部分添加#include"RTC.H"和#include"ds18b20.h"语句,即包含RTC.H和ds18b20.h头文件,为精简工程以及提高编译速度,本项目移除了部分没有使用的项目文件,相应头文件包含语句一并删除。参考代码如下:#ifndef_MAIN_H#define_MAIN_H#include"stm32f10x.h"#include"dsgshow.h"#include"OLED.H"#include"USART.H“#include"EXTI.H"#include"ds18b20.h"#include"RTC.H"#include"stdio.h"#include"string.h"#endif15.6带温度显示的电子万年历项目实施第八步:在main.c文件中输入如下源程序,在main函数中,首先定义变量并赋初值,然后分别对所有用到的外设进行初始化,最后进入日期更新、温度读取和数码管动态显示的无限循环结构当中,并等待中断发生。参考代码如下:#include"main.h"u16year=2024;u8TempStr[17]={0},DateFresh=1;u8month=10,day=31,week=4,hour=9,minute=30,second=25;char*name[7]={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};intmain(){u8Start=0;doublevalue=20.0; //温度值clockinit_RTC(); //时钟初始化Usart1_Init(); //串口初始化ds18b20_init(); //DS18B20初始化EXTIInti(); //外部中断初始化DsgShowInit(); //数码管显示初始化GPIO_Write(GPIOE,0xFFFF); //关所有数码管OLED_Init(); //OLED初始化OLED_Clear(); //OLED清屏value=readtemp(); //开机进行一次温度检测OLED_ShowCHinese(12+8*0,6,0); /*"温",0*/OLED_ShowCHinese(12+8*2,6,1); /*"度",1*/OLED_ShowCHinese(12+8*11,6,2); /*"℃",2*/if(value>0)sprintf((char*)TempStr,"+%05.2f",value);elsesprintf((char*)TempStr,"-%05.2f",value);注意:需要修改OLEDFont.h中的字模”苏州大学”为“温度℃”。OLED_ShowString(12+8*5,6,TempStr)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论