0 卖盘信息
BOM询价
您现在的位置: 首页 > 电子资讯 >技术信息 > 基于温度的MAXQ2000单片机风扇控制办法(MAX1407 DS1920)

基于温度的MAXQ2000单片机风扇控制办法(MAX1407 DS1920)

来源: hqbuy
2024-02-26
类别:技术信息
eye 1
文章创建人 拍明芯城

凭借其众多功能,MAXQ2000可以创建许多有用的应用,例如通过脉宽调制(PWM)控制风扇的速度。MAXQ2000的众多功能包括其具有PWM和串行外设接口(SPI )的定时器以及1线 功能。本应用笔记描述了MAXQ2000如何通过PWM实时驱动风扇并改变其速度。这个过程需要使用Maxim的另一款产品,MAX1407多通道数据采集系统(DAS)。利用SPI, MAXQ2000可以与MAX1407(包含16位数字转换器[ADC]和数字转换器[DAC])通信。作为使用热敏电阻的替代方案,MAXQ2000的1-Wire总线主机可以与温度一起使用按钮(DS1920)。本应用程序说明中使用的源代码可下载。

概述

该程序运行在MAXQ2000评估套件(Rev. B)上,借助温度按钮(DS1920),或外部热敏电阻。MAXQ2000评估套件(Rev. B)包括一个LCD显示器,两个按钮,一个MAX1407 ADC,两个uart,三个定时器,1线和许多其他功能。该程序使用LCD显示,按钮和MAX1407或1-Wire来检测温度。此外,还需要一个直流风扇和适用的驱动电路,一个热敏电阻和一个电源。MAXQ2000评估套件将驱动外部电路来控制风扇速度。液晶显示屏显示当前温度,并定期从摄氏到华氏变化。按钮允许用户改变风扇的低速和全速温度阈值。

检测温度的默认方法是通过使用按钮,但如果正确按钮不可用或通信有问题,程序使用热敏电阻通过MAXQ2000的SPI来获得温度值。的按钮(DS1920)是一个温度传感1线器件。该程序使用RL1005-5744-103-SA热敏电阻与MAX1407结合使用。

一旦温度被读取,显示被发送到LCD, PWM占空比根据温度变化进行调整。

程序中有最低温度和最高温度两个阈值,如果温度低于最低温度阈值,则风扇关闭;如果温度高于最高温度阈值,风扇将被设置为最高转速。如果温度介于最小阈值和最大阈值之间,则速度与两个温度阈值之间的分数距离成正比。

这两个阈值可以通过标记为SW4和SW5的两个按钮进行配置。SW4将阈值切换为更改——基数或最大值。为变化选择的阈值显示在数值数据和C/F字符之间。下划线表示将更改基本阈值,而overscore表示将更改最大阈值。SW5将当前选择的阈值增加1。每改变一个门限,系统会重新计算风扇转速。

这个应用程序需要在MAXQ2000上使用三个定时器中的两个。定时器1通过热敏电阻定期检查温度,定时器0使用P6.5的PWM输出来控制风扇。定时器1不能用于PWM,因为它具有与MAX1407通信期间使用的硬件资源。

硬件设置


图1 将热敏电阻硬件连接到MAXQ2000评估套件。

首先,使用RL1005-5744-103-SA热敏电阻和10k欧姆电阻构建热敏电阻设置。这是通过首先将J7引脚7和8连接到热敏电阻的一侧来完成的。在热敏电阻的另一侧,从J7的引脚1连接一根电线。接下来,连接J7的引脚1和接地(J2的引脚71或72是接地)之间的10k欧姆电阻。如果按钮选项正在使用,然后是按钮应放在按钮夹DS9094FS(或类似的东西),应该焊接到电路板的1线部分。接下来,通过切换SW6.2和SW6.5来启用按钮。LCD显示器连接到J3。为了通过热敏电阻读取温度,打开所有SW3,使其能够与MAX1407通信。MAX1407的ADC部分将来自热敏电阻的信号转换成可用于计算温度的数字值。an的使用按钮需要JU7和JU8和an上的跳线按钮剪辑。


图2 将PWM输出连接到风扇的可能硬件设置。

解释软件的定义和内容

#define PWMFREQ 1000 //将此更改为所需的PWM频率#define CPUFREQ 13500000 //将此更改为匹配当前时钟//频率#define MIN_TICKS 0 //最小计时器滴答数//风扇克服静摩擦#define POLLING_INTERVAL 500 //温度检查之间的毫秒数//


以下是编译时要检查的一些基本定义:

#define LCD0_PATTERN_C 0x039#define LCD0_PATTERN_F 0x071#define lcd0_pattern_0 0x03F#define LCD_PATTERN_1 0x006#define LCD_PATTERN_2 0x05B#define LCD_PATTERN_4 0x066#define LCD_PATTERN_5 0x06D#define LCD_PATTERN_6 0x07D#define LCD_PATTERN_7 0x07F#define LCD_PATTERN_9 0x067int PATTERNS[] = {LCD_PATTERN_0, LCD_PATTERN_1, LCD_PATTERN_2, LCD_PATTERN_4, LCD_PATTERN_5,LCD_PATTERN_6, LCD_PATTERN_7, LCD_PATTERN_8, LCD_PATTERN_9};


使用上述定义,数字的LCD显示非常容易。LCD模式是预定义的,然后添加到一个名为patterns的数组中以供检索。显示某个数字非常简单,如下所示:

LCD2 = PATTERNS[desired_digit];

定时器1初始化

t2 = 0xFFFF - (CPUFREQ/128/1000*POLLING_INTERVAL);//设置重载值。T2r1 = t2v1;//设置当前定时器值T2C1 = 0x00000;//设置比较值T2CFG1_bit。T2DIV = 7 //设置分割模式为除以128 T2CNA1_bit。Tr2 = 1;//启动定时器T2CNA1_bit。T2pol0 = 1;//设置极性高T2CNA1_bit。Et2 = 1;//使能定时器中断T2CNB1_bit。T2oe1 = 1;//打开定时器输出IMR_bit。Im4 = 1;//启用模块4的中断


定时器1负责定期检查温度。初始值(T2V1)取决于温度轮询之间的毫秒时间长度(POLLING_INTERVAL)。计算在两个不同的行上完成的原因是为了防止值变得太大而使寄存器无法处理。T2R1指定定时器到达65,535时返回的值。T2C1被设置在重新加载值(T2R0)以下,以确保它永远不会产生中断。T2CFG1是配置许多定时器选项的寄存器。定时器的时钟划分被设置为将系统时钟除以128,这意味着每128个系统时钟周期相当于1个定时器周期。系统时钟也可以被分割,然后将一个计时器周期的时间乘以(以2的幂)。T2CNA1是定时器0本身的寄存器。这将启动定时器运行并启用定时器中断,而T2CNB1启用定时器输出。最后,启用模块4中的中断。

定时器0初始化

T2V0 = 0xFFFF - (CPUFREQ / PWMFREQ);//设置当前定时器值T2R0 = T2V0;//设置重载值T2C0 = T2R0+1;//设置比较值为加载值+1 T2CNA0_bit。t20e0 = 0;//关闭PWM输出T2CNA0_bit。T2pol0 = 0;//改变PWM的极性,所以它开始“关闭”T2CNA0_bit。t20e0 = 1;// T2CFG0 = 0x00;//设置定时器分割为1


下一个要初始化的项目是定时器0,它控制PWM,并通过它控制风扇。定时器0是一个16位定时器,与定时器1完全相同。当定时器达到比较值(即T2V0 == T2C0)时,端口引脚状态倒转。当定时器重新加载时,端口引脚也反转(图3)。t2v0设置定时器的初始值,而T2R2设置重新加载值,两者都设置为0xFFFF - (CPU频率/ PWM频率)。此计算用于使将代码移植到具有不同CPU时钟速度的系统或更改所需的PWM频率更容易。


图3 端口引脚图。

子选项T2EO0确保PWM输出关闭,以改变极性(T2POL0)。当极性开关设为0时,则PWM的启动状态为关断;如上图所示。T2CFG0确保定时器不分割系统时钟,并告诉定时器比较T2V0和T2C0。

getadcng负责将信号转换为数字值。从热敏电阻中恢复温度的步骤如下所示。

sendSPI (RD_ADC);//读取1407的ADC寄存器spiData = sendSPI(0x0FF);spiData |= 0x01;//设置起始转换位。sendSPI (WR_ADC);//将新值写回sendSPI(spiData);// 1407寄存器。do {sendSPI(RD_STAT);//读取1407的状态寄存器。spiData = sendSPI(0x0FF);} while((spiData &0x02) == 0x00);//位1表示AtoD转换完成。sendSPI (RD_DATA);//发送命令读取1407的数据寄存器。SPICF = 0x04;//设置SPI为16位模式。spiData = sendSPI(0x0FFFF);//读取Data寄存器。SPICF = 0x00;//将SPI调回8位模式。返回spiData;

液晶初始化

/ / LCRA_bit。FRM = 7;//设置帧频率。/ / LCRA_bit。LCCS = 1;//设置时钟源为HF/128。/ / LCRA_bit。占空率= 0;//设置静态占空比。/ / LCRA_bit。Lra = 0;//设置R-adj为0。/ / LCRA_bit。Lrigc = 1;//选择外置LCD驱动电源。LCRA = 0x03E0;//一次执行所有配置更改。PCF = 0x0F;//设置所有段作为输出。LCFG_bit。Opm = 1;//设置为正常运行模式。LCFG_bit。Dpe = 1;//启用显示。LCD1 = 0x08;


为了显示当前的温度,你必须打开液晶显示器。前五行代码被注释掉了,因为它们被压缩成一条语句。LCRA是LCD调整寄存器,它控制LCD显示设置。改变FRM设置帧频率;有了这个,你可以降低频率和使用更少的功率。帧频率是用于显示在LCD上的电源频率。LCCS将LCD时钟划分为128。Duty将显示设置为静态,这意味着显示输出永远不会改变。LCFG是LCD配置寄存器。因为LCD只需要显示,将PCF更改为0x0F将LCD中的所有段设置为输出。将OPM和DPE设置为1分别打开LCD并使能显示。LCD1 = 0x08显示下划线,表示按钮将增加最小阈值。通过下面的两行简单代码,LCD显示器现在处于活动状态并准备显示。

LCRA = 0x03E0;LCFG = 0xF3;


所有需要做的就是将值(如PATTERNS[digit]中的项目)加载到LCD寄存器中,这是非常快速和容易的。

初始化按钮

EIE1 = 0x84;//启用中断15和10 EIES1 = 0x84;//设置边缘过渡。Im1 = 1;//打开模块1的中断


现在该初始化按钮了。与按钮绑定的中断为10和15,对应于EIE1(外部中断启用1)上的4和80(十六进制)。EIE1启用这些外部中断,而EIES1(外部中断边缘选择1)将中断触发器设置为下降沿(按下按钮)。如果这被清除为零,释放按钮是触发中断的动作。IMR是中断掩码寄存器,它跟踪哪个模块允许来自哪个模块的中断,IM1启用来自模块1的中断。

按钮中断

按钮允许用户更改base_temp和max_temp阈值。SW4(中断10)更改将要更改的阈值,而SW5(中断15)将阈值增加1。如果max_temp值达到149,它会将自身降低为base_temp+1。如果base_temp比max_temp低1,则base_temp变为50。

#pragma vector = 1__interrupt void pushButtonInterrupt {if (EIF1 &0x04) //中断10 //修改阈值改变{if(last_state == 0) //修改max_temp而不是base_temp {LCD1 = 0x01;//更改显示下划线last_state = 1;} else //修改base_temp而不是max_temp {LCD1 = 0x08;Last_state = 0;//将显示更改为overscore}}


"#pragma vector = 1"是一个编译器指令,表示该函数处理来自模块1的任何中断,模块1是外部中断的来源。

pushButtonInterrupt函数首先检查触发了哪个中断。中断10为0x04,中断15为0x80。如果它要更改阈值,那么它将更改切换并更新显示。如果它是阈值增量器,则阈值增加1。如果阈值已达到其上限,则绕到下限。

if (EIF1 &0x80) //中断15 //增加基本或最大温度的阈值{if(last_state == 0){//增加base_temp if(base_temp <(max_temp -1)) {++base_temp;如果(base_temp比;LCD4 = 0x40) //如果大于99,则输出100位的1;else LCD4 = 0;//否则不打印LCD3 = getLCDDigit((base_temp /10) %10);//打印10的数字LCD2 = getLCDDigit(base_temp %10);//打印1的数字}else if (base_temp == max_temp -1) //如果基本温度将等于最大温度{//将基本温度设置为50而不是增加base_temp = 50;LCD3 = getLCDDigit(5);//打印50显示LCD2 = getLCDDigit(0);}}


如果阈值被修改,它会检查last_state的值。当last_state为0时,base_temp被修改;否则max_temp会被修改。如果base_temp正好比max_temp小1,程序将base_temp包装为任意值50。

else if(last_state == 1) //增加max_temp {if(max_temp <149) {++max_temp;如果(max_temp比;99) LCD4 = 0x40;//显示100位数字else LCD4 = 0;LCD2 = getLCDDigit(max_temp %10);//显示LCD3 = getLCDDigit((max_temp / 10) %10);//显示10s位}else {if (max_temp == 149) //如果max_temp为极限,则循环max_temp = base_temp+1;//如果(max_temp >99) LCD4 = 0x40;//清除100位数字否则LCD4 = 0;LCD2 = getLCDDigit(max_temp %10);//显示LCD3 = getLCDDigit((max_temp / 10) %10);//显示10s位}}xplier = ((CPUFREQ/PWMFREQ) / (max_temp - base_temp));//重新计算乘数}EIF1 = 0;//清除外部中断标志


按钮中断的这一部分改变了max_temp的阈值。它增加max_temp直到它等于149,然后它绕到比base_temp大1。如果base_temp是65,那么max_temp将是66。

新增加/包装的值会在LCD上短暂显示,这样用户就知道它已经改变了。下一次计时器重新加载时,LCD会变回温度,并以温度更新显示。

阈值更改后,将重新计算xplier。xplier是决定T2C1值的乘数。在按钮中断完成之前,它清除EIF1(外部中断标志1),以便为下一个中断做好准备。

定时器1中断

#pragma vector = 4 __interrupt void timer1Interrupt {T2CNA1_bit。Tr2 = 0;//停止计时器。if(++count == 20) //偶尔改变单位。{count = 0;摄氏= ~摄氏度;} readTemp  ;//获取并显示当前温度。T2CNB1_bit。Tf2 = 0;//清除溢出标志。T2CNB1_bit。Tcc2 = 0;//清除溢出标志。//输出一个带有第一个小数点的'alive'信号,LCD0.7 if (count &1) LCD0 = LCD0 | 0x80;else LCD0 = LCD0 &0 x7f;T2CNA1_bit。Tr2 = 1;//启动定时器}


注意:如果定时器2也被使用,这个函数将运行定时器2的中断,因为定时器2也位于模块4。

将TR2设置为0将定时器关闭,然后检查计数是否等于20。count用于定期将显示从华氏温度更改为摄氏温度。readTemp 调用负责检测温度的函数。readTemp完成后,指示可能的计时器溢出的标志(TF2和TCC2)被清除。if语句检查计数实际上是在每次检查温度时创建一个“勾号”。这个“勾号”是启用或禁用单位字符左边的小数点。这有助于了解它检查的频率和速度,以及当温度保持不变时它正在运行。最后,计时器再次启动。

功能

readTemp 函数负责读取和显示温度,以及驱动PWM。

if(re ButtonTemp(&temp)==FALSE) //检查是否可以找到设备{//如果没有找到iButton设备adc = getADCRe ng ;//读取热敏电阻值。= convertToTemp(adc);//将此值转换为摄氏度。} showTemp(临时);//显示温度驱动pwm (temp);//更新风扇转速


它做的第一件事是试图从1-Wire或按钮设备。如果没有有效的1线温度装置或通信发生错误,则使用热敏电阻读取温度。一旦读取温度,通过调用showTemp函数,LCD显示将更新为最新的温度。之后,drivePWM改变风扇的转速。

有关与1-Wire通信的更多信息和按钮设备,请参阅1-Wire公共领域套件。这是一个软件开发工具包,包含用C编写的1-Wire API,并包括本应用程序中使用的温度示例。

浮点convertToTemp(unsigned int adc){double temp = -0.00135477 * (double)adc + 69.17;返回(浮动)临时;}


convertToTemp将MAX1407的温度转换为摄氏度。请注意,这个公式给出了室温附近的近似值,并没有补偿热敏电阻随温度的非线性变化。

无效showTemp(int temp){LCFG_bit。Dpe = 0;//禁用显示。//清除除温度单位(F或C)以外的所有显示。LCD0 = ((celsius == 0) ?Lcd0_pattern_f: lcd0_pattern_c);//清除数字LCD1 = LCD2 = LCD3 = LCD4 = 0;if(last_state == 0) //显示正在编辑的正确阈值LCD1 = 0x08;else LCD1 = 0x01;


showTemp函数所做的第一件事是将单位系统写入显示器,然后通过将LCD寄存器设置为0来清除显示器上的所有数字。然后显示表示要通过按钮编辑的阈值的下划线或下划线。

if(celsius == 0) {temp = CtoF(temp);//转换为华氏温度}if (temp >199) //如果温度是200+ {temp = temp % 200;} if(temp >99) //如果温度为100+ {show100s ;//在LCD上显示一个'1'温度-= 100;//调整温度变量。} LCD3 = getLCDDigit(temp / 10);//显示LCD上的十位LCD2 = getLCDDigit(temp % 10);//显示LCFG_bit上的1位。Dpe = 1;//启用显示。


如果当前的单位制是华氏温度,则通过函数CtoF将温度转换为华氏温度。如果温度超过100,它将显示100位数字的1,并在显示器上显示其他数字。

drivePWM是通过改变PWM比较值来设置风扇功率的功能。

T2CNA0_bit。Tr2 = 0;//关闭定时器T2CNA0_bit。t20e0 = 0;//关闭PWM输出T2CNA0_bit。T2pol0 = 0;//改变PWM的极性,使其从T2CNA0_bit开始。t20e0 = 1;//使PWM输出T2V0 = T2R0;//手动重新加载定时器值


此顺序关闭风扇,然后手动重新加载计时器值。下面,代码设置了风扇的实际速度。如果温度低于base_temp阈值,则风扇将设置在尽可能低的设置上,否则它将检查温度是否高于最大阈值,在这种情况下,风扇将设置在最高设置上。最后,如果温度在阈值之间,它会根据温度计算风扇的转速。然后计时器被重新打开。


图4 顶部的输出是正常的,而底部的跟踪是可能的,如果计时器没有停止和手动重新加载。

在更新比较和重新加载值时禁用计时器,以避免无意中反转输出,这一点很重要。图4显示了两种类型的输出。顶部的输出是正常的,而底部的图形是可能的,如果计时器没有停止并手动重新加载。发生的情况是,新的比较值高于当前计时器值,当计时器最终达到新的比较值时,端口引脚状态反转,计时器继续。然而,由于状态的变化是不希望的,因此它具有反转定时器输出极性的效果。

if(temp <= base_temp) //低于此温度风扇关闭{//强制端口引脚P6.5低PO6 &= 0xDF;} else {if(temp >= max_temp) //超过此温度风扇全速运行{//强制端口引脚P6.5高PO6 |= 0x20;} else //根据温度设置风扇转速{T2C0 = 65535 - ((temp - base_temp) * xplier);if((65535 - T2C0) <Min_ticks) t2c0 = 65535 - Min_ticks;T2CNA0_bit。Tr2 = 1;//重启定时器}}


高于base_temp阈值的每个度数都有自己的速度,这是基于所需的PWM占空比和两个阈值之间的范围。MIN_TICKS是定时器周期的最小数量,PWM输出必须高,以便风扇以最低速度运行。随着温度的升高,风扇转速呈线性增加。只有当阈值改变时,速度的变化率才会改变。例如,base_temp和max_temp的默认阈值分别为75和85。这意味着xplier(每度风扇转速的增加)是1350。如果阈值分别更改为75和90,则xplier将为900 -这意味着风扇速度的每一度增加都会减少。导风器越低,风机增加越平稳。

void main {initTimer1 ;//为热敏电阻初始化timer1 /iButton轮询initTimer0 ;//初始化PWM输出timer0 init1407 ;//初始化1407 initOW ;//初始化1线子系统initLCD ;//初始化LCD显示initPushButtons ;//初始化按钮__enable_interrupt ;//启用全局中断while(1);}


main函数调用初始化函数并启用全局中断。程序本身是中断驱动的,因此它在中断触发之前一直处于while循环中。

结论

MAXQ2000是一款高性能微控制器,具有许多有用的功能。温度驱动的风扇控制应用是使用MAXQ2000的PWM, 1-Wire和SPI功能的一个很好的例子。当这些功能与按钮和LCD显示器等交互元素结合在一起时,可能的应用程序的数量几乎是无限的。


责任编辑:David

【免责声明】

1、本文内容、数据、图表等来源于网络引用或其他公开资料,版权归属原作者、原发表出处。若版权所有方对本文的引用持有异议,请联系拍明芯城(marketing@iczoom.com),本方将及时处理。

2、本文的引用仅供读者交流学习使用,不涉及商业目的。

3、本文内容仅代表作者观点,拍明芯城不对内容的准确性、可靠性或完整性提供明示或暗示的保证。读者阅读本文后做出的决定或行为,是基于自主意愿和独立判断做出的,请读者明确相关结果。

4、如需转载本方拥有版权的文章,请联系拍明芯城(marketing@iczoom.com)注明“转载原因”。未经允许私自转载拍明芯城将保留追究其法律责任的权利。

拍明芯城拥有对此声明的最终解释权。

标签: MAXQ2000 MAX1407 DS1920

相关资讯