基于F280049C完成智能温度调节展示系统
该项目使用了F280049C,实现了智能温度调节展示系统的设计,它的主要功能为:LCD显示当前温度和设定阈值,开启加热后会调节当前温度到设定阈值。。
标签
参加活动/培训
F280049C
智能温度调节系统
zjl761
更新2024-03-28
246

1、功能介绍

1、温度传感器检测温度变化,LCD显示当前温度和设定温度。

2、LED当设定温度与当前温度不超过5度时,亮绿灯,否则,亮红灯。

3、摇杆和按键用来调节设定温度和是否开启加热。

2、设计思路

2.1、设计思路

1、用ADC获取按键通过电阻网络输出的电平值

2、用输入捕获获取摇杆通过运放电路输出的PWM的频率和占空比

3、通过SPI驱动LCD,通过I2C获取温度传感器的温度值

4、输出PWM控制加热模块

5、使用一个定时器进行获取键值和当前温度

2.2、流程图

3、程序实现

1、按键

由于有一个按键在硬件电路上被屏蔽了,使用旋转编码器代替。

1.1、硬件资源

引脚功能
ADCINA0获取电阻网络输出的电平值

1.2、初始化设置

设置电压基准源:选择内部的1.65V电源

时钟源:选择系统时钟,再进行2分频

引脚选择:选择ADCA的IN0引脚

1.3、程序编写

ADC获取的是一个12位数据,为了方便,就没有转化为电压值,直接使用了原始数据来进行判断。

下面是判断键值的代码,写在定时器中断中。

 //获取按键电压值
 ADC_forceMultipleSOC(myADC0_BASE, (ADC_FORCE_SOC0 | ADC_FORCE_SOC1));
 while(ADC_getInterruptStatus(myADC0_BASE, ADC_INT_NUMBER1) == false)
 {
 }
 ADC_clearInterruptStatus(myADC0_BASE, ADC_INT_NUMBER1);
 KeyValue = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
 ​
 //分配键值
 if(KeyValue >=2400){
 Key_flag = 0;
 }else if(KeyValue >=2000 && KeyValue < 2200){
 Key_flag = 2;
 }else if(KeyValue >=700 && KeyValue < 900){
 Key_flag = 1;
 }


2、摇杆

2.1、硬件资源

引脚功能介绍
GPIO7获取运放网络输出PWM的频率和占空比

2.2、初始化设置

引脚:通过Xbar将GPIO7输入引脚映射到ECAP1

时钟源:默认系统时钟

触发事件配置:事件1捕获下降沿,事件2捕获上升沿,事件3捕获下降沿,事件4捕获上升沿,

中断源选择:事件4

计数器复位:使能,4个事件都触发

2.3、程序编写

在实际的程序编写中,只用到前面两个事件。

下面是输入捕获的中断函数,用于获取PWM的频率和占空比。

 __interrupt void INT_myECAP0_ISR(void)
 {
     cap1Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_1);
     cap2Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_2);
     cap3Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_3);
     cap4Count = ECAP_getEventTimeStamp(myECAP0_BASE, ECAP_EVENT_4);
 ​
     Duty_get = cap1Count * 100.0 / (cap1Count + cap2Count) + 0.5;
     Fre_get = 100000000.0 / (cap1Count + cap2Count);
 ​
     //遥杆上下
     if(Duty_get >= 32 && Duty_get <= 35){
         Rocker_flag = 1;
    }else if(Duty_get >= 56 && Duty_get <= 58){
         Rocker_flag = 0;
    }else if(Duty_get >= 80 && Duty_get <= 90){
         Rocker_flag = 2;
    }
 ​
     //摇杆左右
 /*   if(Fre_get >= 200 && Fre_get <= 250){
         LED_SetColor(1);
     }else if(Fre_get >= 280 && Fre_get <= 320){
         LED_SetColor(2);
     }else if(Fre_get >= 420 && Fre_get <= 460){
         LED_SetColor(3);
     }*/
 ​
     ECAP_clearInterrupt(myECAP0_BASE,ECAP_ISR_SOURCE_CAPTURE_EVENT_4);
     ECAP_clearGlobalInterrupt(myECAP0_BASE);
 ​
     //
     // Start eCAP
     //
     ECAP_reArm(myECAP0_BASE);
 ​
     //
     // Acknowledge the group interrupt for more interrupts.
     //
     Interrupt_clearACKGroup(INT_myECAP0_INTERRUPT_ACK_GROUP);
 }

cap1Count表征高电平时长对应的计数值,cap2Count表征低电平时长对应的计数值。

用系统时钟的频率100M除以二者之和,得到PWM的频率。

用高电平时长对应的计数值除以二者之和,得到PWM的占空比,根据表达习惯,将得到的值乘以100,让占空比的单位变为%。


3、LCD

3.1、硬件资源

使用模拟SPI

引脚定义功能介绍
GPIO57LCD_SCL时钟线
GPIO16LCD_SDA数据线
GPIO17LCD_RST复位线
GPIO39LCD_DC控制线
GPIO59LCD_CS片选

3.2、初始化配置

GPIO:配置为输出

3.3、程序编写

使用的往期活动案例的代码,原来的硬件平台是MSP430,只要将引脚定义和输出函数修改一下就能使用。

如下。

 //-----------------LCD端口定义----------------
 ​
 #define LCD_SCLK_Clr() GPIO_writePin(myLCD_SCL, 0);//SCL=SCLK
 #define LCD_SCLK_Set() GPIO_writePin(myLCD_SCL, 1);
 ​
 #define LCD_MOSI_Clr() GPIO_writePin(myLCD_SDA, 0);//SDA=MOSI
 #define LCD_MOSI_Set() GPIO_writePin(myLCD_SDA, 1);
 ​
 #define LCD_RES_Clr() GPIO_writePin(myLCD_RST, 0);//RES
 #define LCD_RES_Set() GPIO_writePin(myLCD_RST, 1);
 ​
 #define LCD_DC_Clr()   GPIO_writePin(myLCD_DC, 0);//DC
 #define LCD_DC_Set()   GPIO_writePin(myLCD_DC, 1);
 ​
 #define LCD_CS_Clr()   GPIO_writePin(myLCD_CS, 0);//CS
 #define LCD_CS_Set()   GPIO_writePin(myLCD_CS, 1);

另外,使用二级菜单来实现调节温度的设定值和启用和关闭加热电路。

 void get_page(void)
 {
     if(Page == 1 && Home_sec == 0 && Key_flag == 1){
         Page = 21;
    }else if(Page == 1 && Home_sec == 1 && Key_flag == 1){
         Page = 22;
    }else if(Page == 1 && Home_sec == 2 && Key_flag == 1){
         Page = 23;
    }else if((Page == 21 || Page == 22 || Page == 23) && Key_flag == 2){
         Page = 1;
    }
 }

通过上述函数得到页面标志位。

 void GUI_display(void)
 {
      switch(Page)
      {
          case 1:
              GUI_1();
              break;
          case 21:
              GUI_21();
              break;
          case 22:
 //             GUI_22();
              break;
          case 23:
              GUI_23();
              break;
      }
 }

再通过上述函数进行页面的刷新。

另外,由于这块板卡在给定的例程中,定义的RAM比较小,使用字符库lcdfont.h时,会出现空间不够用的情况,只要在ram.cmd文件中分配足够大的空间就可以了。

 MEMORY
 {
 PAGE 0 :
    /* BEGIN is used for the "boot to SARAM" bootloader mode   */
 ​
    BEGIN           : origin = 0x000000, length = 0x000002
    RAMM0           : origin = 0x0000F6, length = 0x00030A
 ​
    RAMLS0         : origin = 0x008000, length = 0x000800
    RAMLS1         : origin = 0x008800, length = 0x000800
    RAMLS2     : origin = 0x009000, length = 0x000800
    RAMLS3     : origin = 0x009800, length = 0x000800
    RAMLS4     : origin = 0x00A000, length = 0x000800
    RESET           : origin = 0x3FFFC0, length = 0x000002
 ​
  /* Flash sectors: you can use FLASH for program memory when the RAM is filled up*/
    /* BANK 0 */
    FLASH_BANK0_SEC0 : origin = 0x080000, length = 0x002000 /* on-chip Flash */
 //   FLASH_BANK0_SEC1 : origin = 0x081000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC2 : origin = 0x082000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC3 : origin = 0x083000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC4 : origin = 0x084000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC5 : origin = 0x085000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC6 : origin = 0x086000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC7 : origin = 0x087000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC8 : origin = 0x088000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC9 : origin = 0x089000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC10 : origin = 0x08A000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC11 : origin = 0x08B000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC12 : origin = 0x08C000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC13 : origin = 0x08D000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC14 : origin = 0x08E000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK0_SEC15 : origin = 0x08F000, length = 0x001000 /* on-chip Flash */
 ​
 PAGE 1 :
 ​
    BOOT_RSVD       : origin = 0x000002, length = 0x0000F1     /* Part of M0, BOOT rom will use this for stack */
    RAMM1           : origin = 0x000400, length = 0x0003F8     /* on-chip RAM block M1 */
 //   RAMM1_RSVD     : origin = 0x0007F8, length = 0x000008     /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
 ​
    RAMLS5     : origin = 0x00A800, length = 0x001800
 //   RAMLS6     : origin = 0x00B000, length = 0x000800
 //   RAMLS7     : origin = 0x00B800, length = 0x000800
 ​
    RAMGS0     : origin = 0x00C000, length = 0x002000
    RAMGS1     : origin = 0x00E000, length = 0x002000
    RAMGS2     : origin = 0x010000, length = 0x002000
    RAMGS3     : origin = 0x012000, length = 0x001FF8
 //   RAMGS3_RSVD : origin = 0x013FF8, length = 0x000008     /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
 /* BANK 1 */
    FLASH_BANK1_SEC0 : origin = 0x090000, length = 0x002000 /* on-chip Flash */
 //   FLASH_BANK1_SEC1 : origin = 0x091000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC2 : origin = 0x092000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC3 : origin = 0x093000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC4 : origin = 0x094000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC5 : origin = 0x095000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC6 : origin = 0x096000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC7 : origin = 0x097000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC8 : origin = 0x098000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC9 : origin = 0x099000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC10 : origin = 0x09A000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC11 : origin = 0x09B000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC12 : origin = 0x09C000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC13 : origin = 0x09D000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC14 : origin = 0x09E000, length = 0x001000 /* on-chip Flash */
    FLASH_BANK1_SEC15 : origin = 0x09F000, length = 0x001000 /* on-chip Flash */
 }
 ​
 SECTIONS
 {
    codestart       : > BEGIN,     PAGE = 0
    .TI.ramfunc     : > RAMM0,      PAGE = 0
    .text           : >> RAMLS0 | RAMLS1 | RAMLS2 | RAMLS3 | RAMLS4 | FLASH_BANK0_SEC0,   PAGE = 0
    .cinit           : > RAMM0,     PAGE = 0
    .switch         : > RAMM0,     PAGE = 0
    .reset           : > RESET,     PAGE = 0, TYPE = DSECT /* not used, */
 ​
    .stack           : > RAMM1,     PAGE = 1
 ​
 #if defined(__TI_EABI__)
    .bss             : > RAMLS5 | FLASH_BANK1_SEC0,     PAGE = 1
    .bss:output     : > RAMLS5,     PAGE = 1
    .init_array     : > RAMM0,      PAGE = 0
    .const           : > RAMLS5 | RAMGS0 | FLASH_BANK1_SEC0,      PAGE = 1
    .data           : > RAMLS5 | FLASH_BANK1_SEC0,     PAGE = 1
    .sysmem         : > RAMLS5,     PAGE = 1
    .bss:cio         : > RAMLS0,     PAGE = 0
 #else
    .pinit           : > RAMM0,      PAGE = 0
    .ebss           : > RAMLS5,     PAGE = 1
    .econst         : > RAMLS5,     PAGE = 1
    .esysmem         : > RAMLS5,     PAGE = 1
    .cio             : > RAMLS0,     PAGE = 0
 #endif
 ​
    ramgs0           : > RAMGS0,    PAGE = 1
    ramgs1           : > RAMGS1,    PAGE = 1  
 }

MEMORY中的FLASH_BANK都是可以使用的。


4、温度传感器

4.1、硬件资源

使用的是模拟I2C。

引脚定义功能介绍
GPIO37I2C_SCL时钟线
GPIO35I2C_SDA数据线

4.2、初始化配置

GPIO:配置为输出

4.3、程序编写

使用的往期活动案例的代码,原来的硬件平台是MSP430,只要将引脚定义和输出函数修改一下就能使用。

如下。

 #define SCL_H GPIO_writePin(myI2C_SCL, 1)
 #define SCL_L GPIO_writePin(myI2C_SCL, 0)
 #define SDA_H GPIO_writePin(myI2C_SDA, 1)
 #define SDA_L GPIO_writePin(myI2C_SDA, 0)
 ​
 #define SDA_OUT GPIO_setDirectionMode(myI2C_SDA, GPIO_DIR_MODE_OUT)
 #define SDA_IN GPIO_setDirectionMode(myI2C_SDA, GPIO_DIR_MODE_IN)
 #define SDA_GET GPIO_readPin(myI2C_SDA)

以下是读取温度传感器的函数,返回值是当前温度值。

 float Read_NST112_Temp(void)
 {
     int Origin_Temp = I2C_ReadReg(NST112_ADDRESS,NST112_REG_Temp);
     float Temp;
     Temp = (char)(Origin_Temp>>8);
     unsigned char decimal=(unsigned char)Origin_Temp;
     if(Temp>=0)
         Temp += (float)(decimal>>4)/16;
     else
         Temp -= (float)(((~decimal)>>4)+1)/16;
     return Temp;
 }


5、加热

5.1、硬件资源

引脚功能介绍
GPIO0输出PWM波以控制加热电路

5.2、初始化配置

时基单元:对系统时钟4分频,计数模式选择向上计数模式,周期值设置为25000,此时频率为1kHz。

比较单元:比较值的初值设置为0,通过改变比较值,可以改变输出PWM的占空比。

动作单元:选择事件为输出高电平

5.3、程序编写

通过改变输出PWM的占空比,能够控制加热电路的功率。由于加热电路与温度传感器之间的热传递比较缓慢,容易加热过度,所以若当前温度超过了设定温度,占空比设置为应有的十分之一。

 void Heat_on()
 {
     //加热
     if(heat_state == 1){
         if(pid_T.ActualT < pid_T.SetT){
             Duty = PID_realize(pid_T.SetT,pid_T.ActualT);
                 EPWM_setCounterCompareValue(myHeat_BASE, EPWM_COUNTER_COMPARE_A, (uint16_t)(Duty * 250));
        }else{
                 EPWM_setCounterCompareValue(myHeat_BASE, EPWM_COUNTER_COMPARE_A, (uint16_t)(Duty * 50));
        }
    }
 }

其中,通过PID计算得到应该输出的占空比。

 float PID_realize( float v, float v_r)
 {
     pid_T.SetT = v;
     pid_T.ActualT = v_r;   // 实际传入 = ADC_Value * 3.3f/ 4096
     pid_T.err = pid_T.SetT - pid_T.ActualT;   //计算偏差
     pid_T.integral = (pid_T.integral*(pid_T.Times-1) + pid_T.err)/pid_T.Times;                        //积分求和
     LIMIT(pid_T.integral,-pid_T.integral_limit,pid_T.integral_limit);
     pid_T.result = pid_T.Kp * pid_T.err + pid_T.Ki * pid_T.integral + pid_T.Kd * ( pid_T.err - pid_T.err_last);//位置式公式
     pid_T.err_last = pid_T.err;             //留住上一次误差
     pid_T.Pwr=25+pid_T.result;
     LIMIT(pid_T.Pwr,10,pid_T.result_limit);
     return pid_T.Pwr;
 }


6、定时器

6.1、硬件资源

CPUTIMER2

6.2、初始化配置

时间周期:2的32次方

中断:使能

定时器开启:不开启,在主函数中开启

6.3、程序编写

开启定时器,并配置中断周期

 configCPUTimer(myCPUTIMER2_BASE, DEVICE_SYSCLK_FREQ, 500000);

在中断函数里获取键值和当前温度

 __interrupt void INT_myCPUTIMER2_ISR(void)
 {
     //获取按键电压值
     ADC_forceMultipleSOC(myADC0_BASE, (ADC_FORCE_SOC0 | ADC_FORCE_SOC1));
     while(ADC_getInterruptStatus(myADC0_BASE, ADC_INT_NUMBER1) == false)
    {
    }
     ADC_clearInterruptStatus(myADC0_BASE, ADC_INT_NUMBER1);
     KeyValue = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
 ​
     //分配键值
     if(KeyValue >=2400){
         Key_flag = 0;
    }else if(KeyValue >=2000 && KeyValue < 2200){
         Key_flag = 2;
    }else if(KeyValue >=700 && KeyValue < 900){
         Key_flag = 1;
    }
 ​
     //获取温度值
     pid_T.ActualT = Read_NST112_Temp();
 ​
     //温度判断
     t_dif = pid_T.SetT - pid_T.ActualT;
     if(t_dif >= -5 && t_dif <= 5){
         LED_SetColor(2);   //绿灯
    }else{
         LED_SetColor(1);   //红灯
    }
 }

4、遇到的主要困难

1、该平台的硬件SPI比较难配置,所以使用模拟SPI。

2、RAM空间分配不足,可以通过修改cmd文件实现。


附件下载
3.yinghe_project2.zip
团队介绍
南京邮电大学
团队成员
zjl761
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号