基于STM32的温控风扇的设计程序

这周末有空,自己完成一个用STM32开发板加上一个电脑散热风扇,以及DS18B0完成了一温控和手动的风扇。主要功能是:1、自动模式,利用温度控制风扇的转速以及风扇的开关;

2、手动模式,通过按键控制风扇的转速和开关。

下面直接分享温控风扇的主要程序:


一、DS18B20程序:

#inlcude “stm32f10x.h”

#include "ds18b20.h"
static void DS18B20_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DS18B20_CLK, ENABLE);    
  GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

/*调用库函数,初始化DS18B20_PORT*/
  GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);

GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);  
}

static void DS18B20_Mode_IPU(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
 GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
 GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}

/*
 * 函数名:DS18B20_Mode_Out_PP
 * 描述  :使DS18B20-DATA引脚变为输出模式
 * 输入  :无
 * 输出  :无
 */
static void DS18B20_Mode_Out_PP(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;   
  GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
}


/*
 *主机给从机发送复位脉冲
 */
static void DS18B20_Rst(void)
{
/* 主机设置为推挽输出 */
DS18B20_Mode_Out_PP();

DS18B20_DATA_OUT=0;
/* 主机至少产生480us的低电平复位信号 */
delay_us(750);

/* 主机在产生复位信号后,需将总线拉高 */
DS18B20_DATA_OUT=1;

/*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/
delay_us(15);
}


/*
 * 检测从机给主机返回的存在脉冲
 * 1:成功
 * 0:失败
 */
int DS18B20_Check(void)
{
uint8_t pulse_time = 0;

/* 主机设置为上拉输入 */
DS18B20_Mode_IPU();

/* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号 
* 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
*/
while( DS18B20_DATA_IN() && pulse_time<100 )
{
pulse_time++;
delay_us(1);
}
/* 经过100us后,存在脉冲都还没有到来*/
if( pulse_time >=100 )
return 0;
else
pulse_time = 0;

/* 存在脉冲到来,且存在的时间不能超过240us */
while( !DS18B20_DATA_IN() && pulse_time<240 )
{
pulse_time++;
delay_us(1);
}
if( pulse_time >=240 )
return 0;
else
return 1;
}


/*
 * 从DS18B20读取一个bit
 */
static uint8_t DS18B20_Read_Bit(void)
{
uint8_t dat;

/* 读0和读1的时间至少要大于60us */
DS18B20_Mode_Out_PP();
/* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
DS18B20_DATA_OUT=0;
delay_us(10);

/* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
DS18B20_Mode_IPU();
//Delay_us(2);

if( DS18B20_DATA_IN() == SET )
dat = 1;
else
dat = 0;

/* 这个延时参数请参考时序图 */
delay_us(45);

return dat;
}


/*
 * 从DS18B20读一个字节,低位先行
 */
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i, j, dat = 0;

for(i=0; i<8; i++) 
{
j = DS18B20_Read_Bit();
dat = (dat) | (j<<i);
}

return dat;
}


/*
 * 写一个字节到DS18B20,低位先行
 */
void DS18B20_Write_Byte(uint8_t dat)
{
uint8_t i, testb;
DS18B20_Mode_Out_PP();

for( i=0; i<8; i++ )
{
testb = dat&0x01;
dat = dat>>1;
/* 写0和写1的时间至少要大于60us */
if (testb)
{
DS18B20_DATA_OUT=0;
/* 1us < 这个延时 < 15us */
delay_us(8);

DS18B20_DATA_OUT=1;
delay_us(58);
}
else
{
DS18B20_DATA_OUT=0;
/* 60us < Tx 0 < 120us */
delay_us(70);

DS18B20_DATA_OUT=1;
/* 1us < Trec(恢复时间) < 无穷大*/
delay_us(2);
}
}
}


void DS18B20_Start(void)
{
DS18B20_Rst();   
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0X44); /* 开始转换 */
}


void DS18B20_Init(void)
{
DS18B20_GPIO_Config();
DS18B20_Rst();

// return DS18B20_Presence();
}


/*
 * 存储的温度是16 位的带符号扩展的二进制补码形式
 * 当工作在12位分辨率时,其中5个符号位,7个整数位,4个小数位
 *
 *         |---------整数----------|-----小数 分辨率 1/(2^4)=0.0625----|
 * 低字节  | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |
 *
 *
 *         |-----符号位:0->正  1->负-------|-----------整数-----------|
 * 高字节  |  s  |  s  |  s  |  s  |    s   |   2^6  |   2^5  |   2^4  |
 *
 * 
 * 温度 = 符号位 + 整数 + 小数*0.0625
 */
float DS18B20_Get_Temp(void)
{
uint8_t tpmsb, tplsb;
short s_tem;
float f_tem;

DS18B20_Rst();
delay_us(300);
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0X44); /* 开始转换 */

DS18B20_Rst();
delay_us(300);
DS18B20_Write_Byte(0XCC); /* 跳过 ROM */
DS18B20_Write_Byte(0XBE); /* 读温度值 */

tplsb = DS18B20_Read_Byte();  
tpmsb = DS18B20_Read_Byte(); 

s_tem = tpmsb<<8;
s_tem = s_tem | tplsb;

if( s_tem < 0 ) /* 负温度 */
f_tem = (~s_tem+1) * 0.0625;
else
f_tem = s_tem * 0.0625;

return f_tem;
}

二、利用PWM风扇控制程序:

#include "stm32f10x.h"
#include "fanner.h"
#include "ds18b20.h"
#include "delay.h"
#include "lcd.h"




u16 change;   //保存温度变化
int flag=0; //作为手动挡和自动挡
int pluse=79; //保存捕获比较寄存器的值
int j=1; //电风扇手动挡档数


/*设置风扇相关的GPIO,定时器和捕获比较的设置*/
void fanner_config(void)
{

GPIO_InitTypeDef GPIO_InitStructer;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer;
TIM_OCInitTypeDef TIM_OCInitStructer;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

GPIO_InitStructer.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructer.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructer);

TIM_TimeBaseInitStructer.TIM_Period=99; //周期为100
TIM_TimeBaseInitStructer.TIM_Prescaler=71;
TIM_TimeBaseInitStructer.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructer.TIM_CounterMode=TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructer);

TIM_OCInitStructer.TIM_OCMode=TIM_OCMode_PWM1; //pwm模式1,小于比较捕获寄存器的值为有效电平
TIM_OCInitStructer.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructer.TIM_Pulse=0;
TIM_OCInitStructer.TIM_OCPolarity=TIM_OCPolarity_Low; //有效电平为低电平,pwm输入到风扇负极,比较寄存器越大,低电平时间越长
TIM_OC3Init(TIM3, &TIM_OCInitStructer);
TIM_ARRPreloadConfig(TIM3, ENABLE);
TIM_Cmd(TIM3, ENABLE); //开计数器

}


/*风扇控制*/
void temp_con(void)
{

if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1)
{
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==1);
flag++;
}
}
/*自动情况*/
if(flag%2==0)
{
LCD_Clear(0, 60, 100, 20, BLACK);
LCD_DispStr(66, 60,"atuo", WHITE);

change=(int)DS18B20_Get_Temp();


if(change>26 || change<22) //温度在22-17度之间,风扇转速随温度升高而加快
{

TIM_SetCompare3(TIM3, 0);
}
else
{
TIM_SetCompare3(TIM3, change*5-31); //随温度调节捕获比较寄存器的值,调整转速
}
}
/*手动模式*/
if(flag%2!=0) 
{
LCD_DispStr(66, 60,"human", WHITE);
LCD_DisNum(56,60,j,WHITE);
TIM_SetCompare3(TIM3, pluse);

if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)==0)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)==0)
{
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)==0);
pluse=pluse+5;
j=j+1;

if(pluse>99)
{
pluse=79;
j=1;
}
LCD_DisNum(56,60,j,WHITE);
TIM_SetCompare3(TIM3, pluse);
}
}

}

}



基于单片机的温控风扇设计 摘 要 温控风扇在现代社会中的生产以及人们的日常生活中都有广泛的应用,如工业生产中大型机械散热系统中的风扇、现在笔记本电脑上的广泛应用的智能CPU风扇等。本文设计了基于单片机的温控风扇系统,采用单片机作为控制器,利用温度传感器DS18B20作为温度采集元件,并根据采集到的温度,通过一个达林顿反向驱动器ULN2803驱动风扇电机。根据检测到的温度与系统设定的温度的比较实现风扇电机的自动启动和停止,并能根温度的变化自动改变风扇电机的转速,同时用LED八段数码管显示检测到的温度与设定的温度。 关键词:单片机、DS18B20温控风扇 第一章 整体方案设计 1.1 前 言 在现代社会中,风扇被广泛的应用,发挥着举足轻重的作用,如夏天人们用的散热风扇、工业生产中大型机械中的散热风扇以及现在笔记本电脑上广泛使用的智能CPU风扇等。而随着温度控制技术的发展,为了降低风扇运转时的噪音以及节省能源等,温控风扇越来越受到重视并被广泛的应用。在现阶段,温控风扇设计已经有了一定的成效,可以使风扇根据环境温度的变化进行自动无级调速,当温度升高到一定时能自动启动风扇,当温度降到一定时能自动停止风扇的转动,实现智能控制。 随着单片机在各个领域的广泛应用,许多用单片机作控制的温度控制系统也应运而生,如基于单片机的温控风扇系统。它使风扇根据环境温度的变化实现自动启停,使风扇转速随着环境温度的变化而变化,实现了风扇智能控制。它的设计为现代社会人们的生活以及生产带来了诸多便利,在提高人们的生活质量、生产效率的同时还能节省风扇运转所需的能量。 本文设计了由ATMEL公司的8052系列单片机AT89C52作为控制器,采用DALLAS公司的温度传感器DS18B20作为温度采集元件,并通过一个达林顿反向驱动器ULN2803驱动风扇电机的转动。同时使系统检测到得环境温度以及系统预设的温度动态的显示在LED数码管上。根据系统检测到得环境温度与系统预设温度的比较,实现风扇电机的自动启停以及转速的自动调节。 1.2 系统整体设计设计的整体思路是:利用温度传感器DS18B20检测环境温度并直接输出数字温度信号给单片机AT89C52进行处理,在LED数码管上显示当前环境温度值以及预设温度值。其中预设温度值只能为整数形式,检测到的当前环境温度可精确到小数点后一位。同时采用PWM脉宽调制方式来改变直流风扇电机的转速。并通过两个按键改变预设温度值,一个提高预设温度,另一个降低预设温度值。系统结构框图如下: 结 论 本次设计的系统以单片机为控制核心,以温度传感器DS18B20检测环境温度,实现了根据环境温度变化调节不同的风扇电机转速,在一定范围能能实现转速的连续调节,LED数码管能连续稳定的显示环境温度和设置温度,并能通过两个独立按键调节不同的设置温度,从而改变环境温度与设置温度的差值,进而改变电机转速。实现了基于单片机的温控风扇设计。 本系统设计可推广到各种电动机的控制系统中,实现电动机的转速调节。在生产生活中,本系统可用于简单的日常风扇智能控制,为生活带来便利;在工业生产中,可以改变不同的输入信号,实现对不同信号输入控制电机的转速,进而实现生产自动化,如在电力系统中可以根据不同的负荷达到不同的电压信号,再由电压信号调节不同的发电机转速,进而调节发电量,实现电力系统的自动化调节。综上所述,该系统的设计和研究在社会生产和生活中具有重要地位。 附录2:程序代码 #include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit DQ=P1^7; sbit key1=P1^3; sbit key2=P1^4; sbit dianji=P3^1; float ff; uint y3; uchar shi,ge,xiaoshu,sheding=20,gaonum,dinum; uchar code dispcode[]={ //段码 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; uchar code tablel[]={ //带小数点的段码 0xbf,0x86,0xdb,0xcf, 0xe6,0xed,0xfd, 0x87,0xff,0xef}; uchar dispbitcode[]={ //位选 0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f}; uchar dispbuf[8]={0,0,0,0,0,0,0,0}; void Delay(uint num)// 延时函数 { while( --num ); } void digitalshow(uchar a4,uchar a3,uchar a2,uchar a1,uchar a0) { dispbuf[0]=a0; dispbuf[1]=a1; dispbuf[2]=a2; dispbuf[3]=a3; dispbuf[4]=a4; P2=0xff; P0=dispcode[dispbuf[0]]; P2=dispbitcode[5]; Delay(1);
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值