本设计采用STM32F103RB作为主控制器,设计题目为基于STM32的温度调控系统设计,主要完成的要求是:液晶屏LCD实时显示当前温度信息与温度上限、温度下限等;LED1以500毫秒的频率不断闪烁,作为系统指示灯;四个按键分别设置温度上限加、温度上限减、温度下限加、温度下限减;当当前温度高于设定温度上限时,蜂鸣器报警提示;低于报警温度下限时LED2点亮。
1.2 设计原理概述
利用STM32F103RB控制器以单总线协议获取DS18B20传感器的温度数值,液晶屏LCD实时显示当前温度与温度上限下限等信息,利用按键中断去检测四个设置按键的状态,当按下按键时,进入中断函数处理按键信息,并且转换为一个标志位,在主函数轮询查询标志位的状态,开启一个系统滴答毫秒级定时器,在中断函数里处理LED以500毫秒闪烁的信息与计时。并且设置了温度上限与温度下限值,通过按键设置,当温度高于温度上限时,蜂鸣器报警提示,当温度低于温度下限时LED2以2Hz频率闪烁,最后加入了一个数码管显示当前温度的功能。
1.3 总体方案设计
方案比较选择:经过查阅相关文献与书籍,本设计最终分为:LCD显示模块、DS18B20温度检测模块、按键检测模块、LED指示模块、数码管显示模块等。
为了用户的视觉体验相比串口显示数据,液晶屏显示更加直观,为了节约设计成本,本次采用不带触摸屏的LCD显示器件,该显示器采用8位数据线传输信息,刷新频率比较快,满足本次设计需求;温度传感器采用DS18B20,该传感器体积非常小,类似三极管封装,并且采用单总线协议,这样设计节约控制器的引脚资源,且温度的分辨率、灵敏度、稳定性、线性度相对一般温度传感器(如DHT11)较好,价格便宜等。
系统总体设计方框图如图1.1所示,基本工作原理为STM32读取温度传感器数值,进行数据转换等处理,然后将处理后的温度信息显示在LCD与数码管上,将当前温度数值与温度上下限进行比较,当高于上限时蜂鸣器报警提示,当低于温度下限时LED2闪烁提示,LED1在系统工作后以2Hz频率工作。
图1.1 系统总体设计方框图
2 硬件电路设计
2.1 硬件电路模块设计
2.1.1 主控模块
本系统采用STM32F103系列微处理器IC,该芯片的设计原理图如图2.1所示。
选择STM32的原因是因为他的资料很丰富,控制功能强大,比如有硬件IIC、SPI、DMA、12位高精度ADC等等,本STM32处理器采用外部高速8MHz晶振作为系统工作时钟源,22pF电容为了匹配晶振起振,还有一些电容为了滤除电源带来的杂波。
图2.1 主控模块电路图
2.2.2 检测模块设计
按键检测电路如图2.2.2所示,四个按键引脚默认为高电平状态,上拉电阻为10K欧姆,当按键按下的时候变为低电平,在软件上设置低下降沿中断便可在中断函数做处理,这样提高系统响应的实时性。
图2.2.2 按键检测电路图
图2.2.3 DS18B20温度测量电路图
温度测量电路中采用DS18B20温度传感器,性价比非常高,适合一般消费类电子产品使用。在温度传感器的OUT引脚中加上一个4.7K的上拉电阻,增强DS18B20的电瓶输出能力。且在其附近的电源正负引脚中并联一个0.1uF的电容,是温度传感器工作电压稳定,防止干扰造成测量误差。
2.2.4 蜂鸣器报警电路设计
蜂鸣器报警电路如图2.2.4所示,采用PNP三极管作为蜂鸣器的开关驱动管子,在蜂鸣器两端并联一个二极管可以保护三极管等器件,因为蜂鸣器内部构造为电感,而电感是一个储能元件,在电流突变的时候会有反向电动势的现象。加入一个泄电二极管可以释放蜂鸣器的反向电流从而起到保护电路的作用。
3 系统软件设计
3.1 软件设计流程
软件运行主流程图如3.1软件程序执行框架图所示, 首先开始初始化系统滴答时钟,初始化相关的输入输出模块,然后读取温度数值并且显示,做相关事件的处理等等。
图3.1 软件程序执行框架图
3.2 源程序设计
3.2.1 主程序设计
主程序流程图如图3.2.1所示,首先开始后进入体统初始化,如初始化定时器、按键、LED、蜂鸣器、液晶屏、数码管、系统中断等,然后不断进行DS18B20温度数据的检测与四个按键中断标志位的检测,并且将数据显示到液晶屏与数码管上面,通过四个按键中断来设置温度的上下限,如果判断当前温度超过温度上限则蜂鸣器报警,超过下限则LED2报警指示,如此不断循环。
使用说明:首先给系统上电,然后当按下B1的时候,累加温度报警上限,当按下B2的时候,温度报警上限减一;当按下B3的时候,温度下限加一,当按下B4的时候,温度下限减一。当按下复位RESET按键的时候,系统进入复位状态;在程序运行的时候LED1以2Hz的频率闪烁,代表系统工作正常,当检测到温度高于上限的时候,蜂鸣器报警提示 ;当当前温度小于温度下限的时候,LED2闪烁报警提示。液晶屏和数码管实时显示当前的温度数据和温度上下限。
#include “stm32f10x.h”
#include “lcd.h”
#include “seg.h”
#include “stdio.h”
#include “ds18b20.h”
#include “main.h”
#include “led.h”
u32 DelayTiming = 0;
//温度上下限
int TempLimit_UP = 39;
int TempLimit_DOWN = 26;
u8 Temp_LED_AlrmFlag = 0, Temp_BEEP_AlrmFlag = 0; //各标志位
int main(void)
{
u8 str[20];
float x = 0.0;
u8 y = 0;
u16 z = 0;
SysTick_Config(SystemCoreClock/1000); //打开SysTick 毫秒级中断
STM3210B_LCD_Init(); //液晶屏初始化
LCD_DisplayStringLine(Line1,(u8*)" DS18B20 DEMO ");
LCD_SetTextColor(Blue);
LCD_SetBackColor(White);
//数码管初始化
STM3210B_SEG_Init();
SEG_DisplayValue(16,16,16); //SEG OFF
//LED1、LED2、蜂鸣器初始化
LED1_AND_LED2_AND_BEEP_Configuration();
LOOP: //LOOP死循环
//温度读取与转换
z = (ds18b20_read()& 0x07FF);
x = z/16.;
y = z/16;
KeyScan(); //查询中断标志->SB
//显示温度上限与下限
snprintf((char*)str, sizeof(str), " Limit_H:%2d Limit_L:%2d", TempLimit_UP, TempLimit_DOWN);
LCD_DisplayStringLine(Line2,str); //液晶屏显示当前温度
snprintf((char*)str, sizeof(str), " Temperatrue:%2.2f", x);
LCD_DisplayStringLine(Line6,str); //液晶屏显示当前温度
//数码管显示
SEG_DisplayValue(y/10, y%10,12);
//上下限判断
if(x >= TempLimit_UP){ //高温蜂鸣器报警
Temp_BEEP_AlrmFlag = 1; //设置蜂鸣器报警标志
}else{
Temp_BEEP_AlrmFlag = 0;
GPIO_SetBits(GPIOC, BEEP);
}
if(x <= TempLimit_DOWN){ //低温LED2闪烁报警
Temp_LED_AlrmFlag = 1; //LED2闪烁标志
}else{
Temp_LED_AlrmFlag = 0;
GPIO_SetBits(GPIOC, LED2);
}
// Delay_Ms(100);
goto LOOP;
}
extern u32 DelayTiming;
void SysTick_Handler(void)//毫秒级中断
{
static unsigned int Time_ms = 0;
Time_ms += 1;
if(Time_ms >= 500){ //2Hz 频率
Time_ms = 0;
//LED1系统运行指示
GPIO_WriteBit(GPIOC, LED1 , (BitAction) (1 - GPIO_ReadOutputDataBit(GPIOC, LED1)));
if(Temp_BEEP_AlrmFlag == 1){
GPIO_WriteBit(GPIOC, BEEP , (BitAction) (1 - GPIO_ReadOutputDataBit(GPIOC, BEEP)));
}
if(Temp_LED_AlrmFlag == 1){
GPIO_WriteBit(GPIOC, LED1 , (BitAction) (1 - GPIO_ReadOutputDataBit(GPIOC, LED1)));
}
}
if(DelayTiming != 0){
DelayTiming--;
}
}
//毫秒级中断延时函数
void Delay_Ms(u32 nTime)
{
DelayTiming = nTime;
while(DelayTiming != 0);
}
温度读取函数:
//
s16 ds18b20_read(void)
{
u8 val[2];
u8 i = 0;
s16 x = 0;
ow_reset();
ow_byte_wr(OW_SKIP_ROM);
ow_byte_wr(DS18B20_CONVERT);
delay_us(750000);
ow_reset();
ow_byte_wr( OW_SKIP_ROM );
ow_byte_wr ( DS18B20_READ );
for ( i=0 ;i<2; i++)
{
val[i] = ow_byte_rd();
}
x = val[1];
x <<= 8;
x |= val[0];
return x;
}
数码管显示函数:
uc8 Seg7[17] = { 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x4f,0x79,0x78,0x00};
void STM3210B_SEG_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//
void SEG_DisplayValue(u8 Bit1, u8 Bit2, u8 Bit3)
{
u8 i = 0; //
u8 code_tmp = 0;
code_tmp = Seg7[Bit3];
for(i=0;i<8;i++){
if(code_tmp & 0x80){
SER_H;
}else{
SER_L;
}
SCK_H;
code_tmp = code_tmp << 1;
SCK_L;
}
code_tmp = Seg7[Bit2];
for(i=0;i<8;i++){
if(code_tmp & 0x80){
SER_H;
}else{
SER_L;
}
SCK_H;
code_tmp = code_tmp << 1;
SCK_L;
}
code_tmp = Seg7[Bit1];
for(i=0;i<8;i++){
if(code_tmp & 0x80){
SER_H;
}else{
SER_L;
}
SCK_H;
code_tmp = code_tmp << 1;
SCK_L;
}
RCLK_H;
RCLK_L;
}
3.2.2 模块程序设计
按键中断程序处理流程图如图3.3.3所示,首先初始化相关模块与系统时钟等,然后进入主函数,当按键中断发生下降沿信号时,正在执行的主函数将被打断,进而处理按键中断相关处理函数,在中断处理函数中设置标志位与相关事件的处理。
4 系统调试
4.1 系统硬件调试
调试工具主要为示波器、JTAG仿真器以及万用表等,用示波器检测蜂鸣器、LED1与LED2引脚的输出波形,分别控制传感器周围温度超过上下限查看波形变化,由于本次采用的数码管控制芯片为三个级联的SN74LS595N移位寄存器,所以通讯协议只需几个CPU引脚即可方便控制,只是软件编写方面优点麻烦,有时候会出现显示不正确的情况,经过检查为电路虚焊,改正后问题解决。
4.2 系统软件调试
软件调试采用Multisim仿真软件仿真电路,采用Keil_v5软件的JTAG仿真,仿真图如图4.2所示。单步执行程序,并且查看寄存器R0~R7的值,由于硬件电路相对比较简单,所以仿真工作也比较简单,主要是软件程序的编写。主要遇到的问题是数码管驱动,由于采用级联的移位寄存器来控制数码管,所以显得复杂一些。
原理图
链接:https://pan.baidu.com/s/17r7pBQ4WsTmtlyKAV0wGTQ
提取码:g9kn