[资料分享] msp430g2553单片机 感应温度的呼吸灯

fish001   2017-12-16 11:07 楼主
//程序烧进板子后先进入led灯交替闪烁的待机模式;按下按键后,进入应用模式,绿灯开始呼吸;此时温度上升后绿灯呼吸加快,温度下降后呼吸又会变慢。当温度过高时红灯亮
#include  "msp430g2553.h"
#define     LED1                  BIT0
#define     LED2                  BIT6
#define     LED_DIR               P1DIR
#define     LED_OUT               P1OUT
#define     BUTTON                BIT3  //P1.3为板上按键S2
#define     BUTTON_OUT            P1OUT //端口输出寄存器
#define     BUTTON_DIR            P1DIR //端口方向控制寄存器
#define     BUTTON_IN             P1IN  //端口输入寄存器
#define     BUTTON_IE             P1IE  //端口中断允许寄存器
#define     BUTTON_IES            P1IES //端口中断触发沿控制寄存器
#define     BUTTON_IFG            P1IFG //端口中断标志寄存器
#define     BUTTON_REN            P1REN //端口上下拉电阻使能控制寄存器
#define     APP_STANDBY_MODE      0 //待机模式标志,也就是接上电源(或USB)后红绿灯交替闪的状态
#define     APP_APPLICATION_MODE  1 //应用模式标志,也就是待机模式时按按键后进入的状态,也就是测量温度
#define     TIMER_PWM_MODE        0
long     TIMER_PWM_PERIOD   =   5000;
#define     TIMER_PWM_OFFSET      20
#define     TEMP_SAME             0
#define     TEMP_HOT              1
#define     TEMP_COLD             2
#define     TEMP_THRESHOLD        0
//   Conditions for 9600/4=2400 Baud SW UART, SMCLK = 1MHz
#define     Bitime_5              0x05*4                      // ~ 0.5 bit length + small adjustment
#define     Bitime                13*4//0x0D
unsigned char BitCnt;
unsigned char applicationMode = APP_STANDBY_MODE; //功能模式标志,初始值为待机模式
unsigned char timerMode = TIMER_PWM_MODE;
unsigned char tempMode;
unsigned char calibrateUpdate = 0;
unsigned char tempPolarity = TEMP_SAME;
unsigned int TXByte;
long tempMeasured[8]; //定义数组以计算8次10位ADC温度采样的平均值
unsigned char tempMeasuredPosition=0; //温度测量值数组索引
long tempAverage; //8次10位ADC温度采样的平均值
long tempCalibrated, tempDifference;
void InitializeLeds(void);  //IO端口初始化,设置两颗LED对应的端口并两设置为熄灭初始状态
void InitializeButton(void);  //IO端口初始化,配置按键
void PreApplicationMode(void);                     //进入待机模式,红绿灯交替闪,等待按键 Blinks LED, waits for button press
void ConfigureAdcTempSensor(void);  //配置温度传感器模数转换
void ConfigureTimerPwm(void); //配置定位器为PWM模式
void InitializeClocks(void);  //初始化时钟系统

void main(void)
{
  unsigned char i;

  WDTCTL = WDTPW + WDTHOLD;                 // 停止看门狗 Stop WDT

  InitializeClocks(); //初始化时钟系统

  InitializeButton(); //配置按键

  InitializeLeds(); //设置端口并两设置两颗LED对应为熄灭初始状态

  PreApplicationMode();

  applicationMode = APP_APPLICATION_MODE; //功能模式标志变成应用模式

  ConfigureAdcTempSensor(); //配置温度传感器模数转换

  ConfigureTimerPwm();  //配置定位器PWM模式

  __enable_interrupt();                     //使能全局中断 Enable interrupts.

  LED_OUT &=~LED1;
  while(1)

  {

    ADC10CTL0 |= ENC + ADC10SC;             //ADC使能,ADC开始转换一次 Sampling and conversion start

    __bis_SR_register(CPUOFF + GIE);

    P1SEL |=BIT6;
    P1OUT |=BIT6;
    ConfigureTimerPwm();
    unsigned int j;
        for(j=0;j
        {
          CCR1=j;
         _delay_cycles(1000);
         }
        for(j=TIMER_PWM_PERIOD ;j>0;j-=1)
        {
          CCR1=j;
          _delay_cycles(1000);
        }
        for (j=TIMER_PWM_PERIOD;j>0;j-=1)
        {
          _delay_cycles(100);
        }

    tempMeasured[tempMeasuredPosition++] = ADC10MEM;  //将温度采样值存入温度值数组下一位

    if (tempMeasuredPosition == 8)

      tempMeasuredPosition = 0; //复位温度采样值数组索引

    tempAverage = 0;

    for (i = 0; i < 8; i++)

      tempAverage += tempMeasured;

    tempAverage >>= 3;  //除以8得到平均值   Divide by 8 to get average

    tempDifference = tempAverage - tempCalibrated;  //计算相对于参考温度的差值

    if (tempDifference < -TEMP_THRESHOLD) //如果采样温度值低于参考温度值差值TEMP_THRESHOLD
    {

      tempDifference = -tempDifference; //差值取正

      tempPolarity = TEMP_COLD; //极性变量设为值TEMP_COLD


    }

    else

    if (tempDifference > TEMP_THRESHOLD)  //如果采样温度值高于参考温度值差值TEMP_THRESHOLD

    {

      tempPolarity = TEMP_HOT;  //极性变量设为值TEMP_HOT

    }

    else  //如果相对于参考温度值偏差没有超过阈值TEMP_THRESHOLD

    {

      tempPolarity = TEMP_SAME; //性变量设为值TEMP_SAME

      TACCTL0 &= ~CCIE; //关TACCTL0中断使能

      TACCTL1 &= ~CCIE; //关TACCTL1中断使能

    }

    if (tempPolarity != TEMP_SAME)  //如果相对于参考温度值偏差超过阈值TEMP_THRESHOLD

    {

      tempDifference <<= 9; //温度偏差值乘以8

      //tempDifference += TIMER_PWM_OFFSET; //加上一个偏置值

      TACCR1 = ( (tempDifference) < (TIMER_PWM_PERIOD-1) ? (tempDifference) : (TIMER_PWM_PERIOD-1) ); //置TACCR1,最大为TIMER_PWM_PERIOD-1。

      //TACCR1值控制亮的时间,定时器计数到TACCR1在中断中将关闭灯,在TACCR0中断中亮灯

      TACCTL0 |= CCIE;  //开TACCTL0中断使能

      TACCTL1 |= CCIE;  //开TACCTL1中断使能


    }

  } //返回主循环

}



//进入待机模式,红绿灯交替闪,等待按键

void PreApplicationMode(void)

{

  LED_DIR |= LED1 + LED2; //p1.0和P1.6口为输出

  LED_OUT |= LED1;

  LED_OUT &= ~LED2; //绿灯灭

  BCSCTL1 |= DIVA_1;

  BCSCTL3 |= LFXT1S_2;

  TACCR0 = 1200;

  TACTL = TASSEL_1 | MC_1;
  TACCTL1 = CCIE + OUTMOD_3;

  TACCR1 = 600;

  __bis_SR_register(LPM3_bits + GIE);
}



//配置温度传感器模数转换

void ConfigureAdcTempSensor(void)

{

  unsigned char i;

  /* Configure ADC Temp Sensor Channel */

  ADC10CTL1 = INCH_10 + ADC10DIV_3; //选择ADC通道为温度传感器,时钟4分频         // Temp Sensor ADC10CLK/4

  ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;  // VR+ = VREF+ and VR- = VSS,采样保持时间=64×ADC10CLK周期,打开内部参考电压,打开ADC模块,ADC中断允许

  __delay_cycles(1000); //延时等待ADC参考电压建立                     // Wait for ADC Ref to settle

  ADC10CTL0 |= ENC + ADC10SC; //ADC使能,ADC开始转换一次                // Sampling and conversion start

  __bis_SR_register(CPUOFF + GIE);  //进入省电模式LPM0,等待AD转换完成中断          // LPM0 with interrupts enabled

  tempCalibrated = ADC10MEM;

  for (i=0; i < 8; i++)

    tempMeasured = tempCalibrated;

  tempAverage = tempCalibrated; //第一次转换,平均温度取样值和校准值相等

}



//配置定位器为PWM模式

void ConfigureTimerPwm(void)

{

  timerMode = TIMER_PWM_MODE;

  TACCR0 = TIMER_PWM_PERIOD;                              //

  TACTL = TASSEL_2 | MC_1;  //定时器时钟源选择辅助时钟SMCLK,增计数模式                  // TACLK = SMCLK, Up mode.

  TACCTL1 = OUTMOD_7;//CCIE + OUTMOD_3;  //捕获/比较控制寄存器1设置为比较模式,输出模式为“置位/复位” ,中断允许  ??OUTMOD_3有什么用?                // TACCTL1 Capture Compare


}

//TACCR0中断专用, Timer A0 interrupt service routine

#pragma vector=TIMER0_A0_VECTOR

__interrupt void Timer_A (void)

{

    if (tempPolarity == TEMP_HOT)
    {

      //LED_OUT |= LED1;  //如果相对于参考温度偏差为正,LED1绿灯置为亮
    TIMER_PWM_PERIOD -= tempDifference;
     if (TIMER_PWM_PERIOD < 0)
     {
     LED_DIR |= LED1;
     LED_OUT |= LED1;
     //TIMER_PWM_PERIOD = 1;
     }
     tempCalibrated = tempAverage;
    }

    if (tempPolarity == TEMP_COLD)
    {

      //LED_OUT |= LED2;  //如果相对于参考温度偏差为负,LED2红灯置为亮
    TIMER_PWM_PERIOD += tempDifference;
    tempCalibrated = tempAverage;
    if (TIMER_PWM_PERIOD>0)
    {
    LED_OUT &= ~LED1;
    }
    }

    TACCTL0 &= ~CCIFG;  //清中断标志位??有必要么?不是自动清除?
    TACCTL0 &= ~CCIE;

}

//TACCR1和定时器共用中断向量

#pragma vector=TIMER0_A1_VECTOR

__interrupt void ta1_isr(void)

{
  TACCTL1 &= ~CCIFG;  //捕获比较中断标志CCIFG。比较模式:定时器 TAR 值等于寄存器 CCR1 值时CCIFG置位。需手动清除

  if (applicationMode == APP_APPLICATION_MODE)
  {

    //LED_OUT &= ~(LED1 + LED2);  //如果程序运行至是应用模式,置两灯皆灭
    TACCTL1 &= ~CCIE;
  }

  else

    LED_OUT ^= (LED1 + LED2); //如果是待机模式,异或,原来两个灯本来就是一亮一灭的,所以反复中断的效果是交替闪烁。PreApplicationMode(void)中

}

void InitializeClocks(void)

{

  BCSCTL1 = CALBC1_1MHZ;  //用FLASH中信息存贮器A段的校准数据设置基本时钟系统控制寄存器 1                    // Set range

  DCOCTL = CALDCO_1MHZ; //用FLASH中信息存贮器A段的校准数据设置 DCO 控制寄存器,设置DCO校准为1MHz,详细原理请查看G2系列芯片的Users Guide

  BCSCTL2 &= ~(DIVS_3); //SMCLK为0分频DCO                     // SMCLK = DCO = 1MHz

}

void InitializeButton(void)                 // Configure Push Button

{

  BUTTON_DIR &= ~BUTTON;  //按键对应的端口方向为输入

  BUTTON_OUT |= BUTTON; //设置输出寄存器对应的按键位为1

  BUTTON_REN |= BUTTON; //使能上拉电阻,因为对应的输出寄存器位为1。反之如果对应的输出寄存器位为0则自动选择下拉电阻。

  BUTTON_IES |= BUTTON; //选择下降沿中断

  BUTTON_IFG &= ~BUTTON;  //中断标志清零

  BUTTON_IE |= BUTTON;  //按键中断允许

}



//设置两颗LED对应的端口并两设置为熄灭初始状态

void InitializeLeds(void)

{

  LED_DIR |= LED1 + LED2; //P1DIR=BIT1+BIT6 p1.0和P1.6口为输出

  LED_OUT &= ~(LED1 + LED2);  //两个LED低电平熄灭

}

/* *************************************************************

* Port Interrupt for Button Press

* 1. During standby mode: to exit and enter application mode

* 2. During application mode: to recalibrate temp sensor

* *********************************************************** */

#pragma vector=PORT1_VECTOR

__interrupt void PORT1_ISR(void)

{

  BUTTON_IFG = 0; //清P1口所有中断标志

  BUTTON_IE &= ~BUTTON; //禁止按键中断使能,防抖动,经过看门狗定时器延时在看门狗定时器中断中再打开            /* Debounce */

  WDTCTL = WDT_ADLY_250;  //=(WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS0)看门狗设置为定时器模式,计数清零,时钟源为辅助时钟ACLK,定时周期为Taclk×32768

  IFG1 &= ~WDTIFG;  //清看门狗定时器中断标志                 /* clear interrupt flag */

  IE1 |= WDTIE;  //使能看门狗定时器中断



  if (applicationMode == APP_APPLICATION_MODE)  //如果是应用模式

  {

    //tempCalibrated = tempAverage; //???如果中断发生在for (i = 0; i < 8; i++) tempAverage += tempMeasured;不是错了么?

    calibrateUpdate  = 1; //参考温度校准标志变量

  }

  else

  {

    applicationMode = APP_APPLICATION_MODE; //由待机模式切换到应用模式 // Switch from STANDBY to APPLICATION MODE

    __bic_SR_register_on_exit(LPM3_bits); //退出低功耗模式LPM3

  }

}



// WDT Interrupt Service Routine used to de-bounce button press

#pragma vector=WDT_VECTOR

__interrupt void WDT_ISR(void)

{

    IE1 &= ~WDTIE;  //禁止看门狗定时器中断                   /* disable interrupt */

    IFG1 &= ~WDTIFG;  //清看门狗定时器中断标志                 /* clear interrupt flag */

    WDTCTL = WDTPW + WDTHOLD; //使看门狗关闭状态        /* put WDT back in hold state */

    BUTTON_IE |= BUTTON;  //使能按键中断             /* Debouncing complete */

}

// ADC10 interrupt service routine

#pragma vector=ADC10_VECTOR

__interrupt void ADC10_ISR (void)

{

  __bic_SR_register_on_exit(CPUOFF);  //退出省电模式        // Return to active mode

}






回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复