本程序是《MSP430系列单片机系统工程设计与实践》书里面的源码,(包含工程文件(例3.1) )完整例程下载:http://www.51hei.com/bbs/dpj-46245-1.html
关于本程序的详细解说大家可以点击上图下载电子书
- /*
-
- 带摄氏度/华氏度切换的超低功耗温度计程序
- 说明:在《温度计_基本原理》程序中,已经实现了一个温度测量和显示的系统,
- 但因为采样速率很快,且对基准源不加控制,耗电很大(800uA左右)。
- 本例中,将温度采集速度降到1秒一次,且采样间隙时间不仅关闭基
- 准源,还让CPU进入LPM3休眠状态,大大节省了耗电。该程序功耗仅10uA
- 左右,可用纽扣电池长期运行(2年)。实际上对于环境温度1秒1次采样仍
- 属浪费,如果降到5秒一次,功耗可下降到4uA左右(CR2032电池工作5年)。
- 按KEY3后,CPU进入LPM4,功耗下降到0.1uA,这是一种常用的不断电
- 的关机方法。
- 同时,该程序示例了如何例用程序库快速的完成开发任务。
- //=============================操作说明方法==============================
- 按KEY1键切换到摄氏度显示,按KEY2键切换到华氏度显示,按KEY3关机,
- 关机后按复位键可以开机。
- //===========================温度计算公式推导============================
- 430单片机内部温度传感器温度系数是:1.32mV/K (1.32mv/开尔文)
- 开尔文温度=摄氏温度+273K
- 在内部基准电压Vref=1200mV条件下,ADC数据格式设置为"有符号"时,
- 0V对应采样值0,1/2Vref(600mV)对应ADC采样值32767(忽略实际误差)。
- 推导出传感器输出Vsensor = (ADC采样值)/32768 * Vref/2
- Vsensor除以温度系数(1.32mV/K)得到开氏温度:
- DegK = ADC采样值/65536 * 1200/1.32
- 化简后 DegK = (ADC采样值 * 909)/65536
- 再减去273,得到摄氏温度:
- DegC = (ADC采样值 * 909)/65536 - 273
- 为了能显示小数点后一位,计算过程中先扩大10倍,显示时加一位小数点。得
- 到最终计算公式:
- DegC = (ADC采样值 * 9090)/65536 - 2730
- 华氏度/摄氏度的转换公式是
- DegF=DegC*(9/5)+32
- 同样扩大10倍得到DegF=DegC*9/5+320
- //===========================温度校准与修正============================
- 上述公式是在理想状况下求得的,实际上ADC、温度传感器都存在误差。(误差
- 原理参《超低功耗电压表》程序),因此需要校准。在《超低功耗电压表》中提出的
- 校准方法在这里同样适用,即输入两个已知温度(例如0/100度),记录ADC读数,然后
- 根据两点坐标写出新的直线公式,即可校准。
- 但是该方法存在2个难点:第一是在业余条件下,标准温度产生比较困难(相对
- 来说,电压表程序中产生已知电压容易得多);第二是温度传感器位于片内,难以置入
- 标准温度中(比如冰水混合物/沸水)。
- 因此,这里提出一种相对简单的近似校准方法。该温度计大部分情况测量的是室
- 温附近的范围(按0-50度考虑),而传感器的输出比例系数是按绝对零度开始的,因此微
- 小的比例误差乘以273都是不可忽略的。%2的比例误差,在27度下(300K)会造成7.92mV
- 误差,约6度。因为难以产生标准温度,所以比例系数难以校准;但偏移误差很容易通过
- 显示值和普通温度计示数之差得到。我们可以将所有的误差都折算成偏移误差,这样虽
- 然比例误差无法完全消除,但因为测温范围不大,影响也相对小得多。
- 在25度左右的室温下,抄下430显示的温度标与准温度计的温度差T_OFFSET,在显示
- 的时候将这个误差扣除。按0-50度量程考虑,25度必然是准确的,按量程25度程正负25
- K计算,2%比例误差造成的温度误差只有正负0.5度,精度已经足够高了。
-
- //=========================================================================
- 注意事项:用手触摸芯片表面可以观察到显示温度立刻上升。但请注意430单片机
- 属于静电敏感芯片,触摸芯片之前一定要先用手接触一下大地(水管、
- 电脑机箱等)再捏住电路板的GND端子(左下角),另一只手才可触摸芯片。
- (C)西安电子科技大学 测控技术与仪器教研中心 编 写:谢 楷 2020/02/20
-
- */
- //
- // MSP430FE425
- // ----------------------
- // | XIN|-
- // | | 32kHz
- // |RST XOUT|-
- // | | +----------------------+
- // |A0.6+ -| S0-S15|--->| SoftBaugh LCD_048 |
- // |A0.6- | COM0-COM3|--->| 7.1Digit,4-Mux LCD |
- // | | | | +----------------------+
- // | | | VREF |---+
- // (P1.5)| \| |/ | |
- // KEY1---->| \_/ | -+- 100nF
- // | 内部 | -+-
- // | 温度传感器 | |
- // (P1.6)| AVss |---+
- // KEY2---->| |
- // | |
- // | |
- // (P1.7)| |
- // KEY3---->| |
- // | |
- //*****************************************************************************
- #include "MSP430X42X.h" /*430单片机寄存器头文件*/
- #include "LCD_Display.h" /*LCD显示函数库头文件*/
- #include "BasicTimer.h" /*基础定时器函数库头文件*/
- #include "ADC16.h" /*16位ADC函数库头文件*/
- #define KEY1 (P1IN&BIT5) /*KEY1=P1.5*/
- #define KEY2 (P1IN&BIT6) /*KEY1=P1.6*/
- #define KEY3 (P1IN&BIT7) /*KEY1=P1.7*/
- char Timer1s=16; /*1秒计时累加变量*/
- char DegMode=1; /*温度模式变量*/
- #define Mode_C 1 /*摄氏度 宏定义*/
- #define Mode_F 0 /*华氏度 宏定义*/
- #define T_OFFSET (0) /*25度左右条件下,显示温度减去标准温度计温度*/
- /*作为校准偏移值。注意要乘10倍,10=1.0度*/
- /****************************************************************************
- * 名 称:PowerOff()
- * 功 能:关机
- * 入口参数:无
- * 出口参数:无
- * 说 明: 关机后按复位键开机。
- ****************************************************************************/
- void PowerOff()
- {
- LCD_Clear();
- LCD_DisplayChar(BR,5);
- LCD_DisplayChar(OO,4);
- LCD_DisplayChar(FF,3); //显示 '-OFF-'
- LCD_DisplayChar(FF,2);
- LCD_DisplayChar(BR,1);
- Cpu_SleepDelay(32); //'-OFF-' 停留2秒
- LCD_OFF(); //关闭LCD
- _DINT(); //禁止所有中断(禁止唤醒CPU)
- LPM4; //进入LPM4休眠(最省电的模式,0.1uA)
- //只有复位才能唤醒CPU,重新执行程序
- _NOP(); //程序永远不会运行到这一行
- }
- /****************************************************************************
- * 名 称:main()主程序
- * 功 能:每1秒采集温度一次并显示;每1/16秒扫描一次按键并处理。
- * 入口参数:无
- * 出口参数:无
- ****************************************************************************/
- void main( void )
- { int i;
- int ADC_Result=0;
- int DegC;int DegF;
- WDTCTL=WDTPW+WDTHOLD; //停止看门狗
- FLL_CTL0|=XCAP18PF; //配置晶振负载电容
- P1DIR|=BIT0+BIT1+BIT2+BIT3+BIT4;
- P2DIR|=BIT0+BIT1+BIT2+BIT3; //悬空的IO口要置为输出
- P1OUT =0; //不确定电平会造成IO耗电
- P2OUT =0;
- BT_Init(16); //BasicTimer设置为1/16秒中断(唤醒)CPU一次
- LCD_Init(); //LCD初始化
- UART_Init(2400,n,8,1);
- ADC16_Init(0,6,'S',1);//ADC16初始化,设置ADC0采样温度传感器,有符号,增益=1
- while(1)
- {
- Cpu_SleepWaitBT();//CPU休眠,等待被BasicTimer唤醒
- //-----------以下代码1/16秒运行一次--------------
- if(KEY1==0) DegMode=Mode_C; //如果KEY1被按下,切换成摄氏度显示模式
- if(KEY2==0) DegMode=Mode_F; //如果KEY2被按下,切换成华氏度显示模式
- if(KEY3==0) PowerOff(); //如果KEY3被按下,关机
- Timer1s++; //1秒累加计数
- if(Timer1s>=16) //16次累加=1秒
- {
- Timer1s=0;
- //-----------以下代码1秒运行一次-----------------
- ADC16_VrefOn(); //打开基准源
- for(i=0;i<30;i++); //略等待,等基准稳定
- ADC_Result=ADC16_Sample(0,1);//采样ADC0,单次采样
- ADC16_VrefOff(); //关闭基准源
- DegC=((long int)ADC_Result * 9090)/65536 - 2730;//计算摄氏度
- DegC-=T_OFFSET; //扣除校准偏移量
- DegF=DegC*9/5+320; //计算华氏度
- if(DegMode==Mode_C) //如果处于摄氏度显示模式
- {
- LCD_DisplayDecimal(DegC,1); //显示摄氏度,带1位小数
- LCD_InsertChar(DT);
- LCD_InsertChar(CC); // 尾部添加单位: 'C
- }
- if(DegMode==Mode_F) //如果处于华氏度显示模式
- {
- LCD_DisplayDecimal(DegF,1);//显示摄氏度,带1位小数
- LCD_InsertChar(DT);
- LCD_InsertChar(FF); // 尾部添加单位: 'F
- }
- }
- }
- }
复制代码
|