/******************************************************************************
* 1. 第一个按钮按下后,设备过渡到应用模式
* 2. 应用模式:
* a、连续采样ADC的温度传感器通道,对比较结果初始值
* b、将PWM根据测量ADC偏移:红色发光二极管的正偏移,绿LED为负偏移
* c、发送到PC的UART通过TimerA的温度值
* d、键按一下“ - >使用当前的温度校准
* e、通过UART发送字符'',通知电脑
******************************************************************************/
#include "msp430x20x2.h"
#define LED0 BIT0
#define LED1 BIT6
#define LED_DIR P1DIR
#define LED_OUT P1OUT
#define BUTTON BIT3
#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 TXD BIT1 // TXD on P1.1
#define RXD BIT2 // RXD on P1.2
#define APP_STANDBY_MODE 0 //APP待机模式
#define APP_APPLICATION_MODE 1 //APP应用模式
#define TIMER_PWM_MODE 0
#define TIMER_UART_MODE 1
#define TIMER_PWM_PERIOD 2000 //周期
#define TIMER_PWM_OFFSET 20
#define TEMP_SAME 0
#define TEMP_HOT 1
#define TEMP_COLD 2
#define TEMP_THRESHOLD 5 //阀值
// Conditions for 9600/4=2400 Baud SW UART, SMCLK = 1MHz
#define Bitime_5 0x05*4 // ~ 0.5 bit length + small 调整
#define Bitime 13*4//0x0D
#define UART_UPDATE_INTERVAL 1000 //Uart更新区间
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; //temp 极性
unsigned int TXByte;
/* 使用8值的移动平均滤波器采样ADC值*/
long tempMeasured[8]; //测量值
unsigned char tempMeasuredPosition=0; //测量位置
long tempAverage; //平均值
long tempCalibrated, tempDifference;
void InitializeLeds(void);
void InitializeButton(void);
void PreApplicationMode(void); // 闪烁LED, 等待按键按下
void ConfigureAdcTempSensor(void);
void ConfigureTimerPwm(void);
void ConfigureTimerUart(void);
void Transmit(void);
void InitializeClocks(void);
void main(void)
{
unsigned int uartUpdateTimer = UART_UPDATE_INTERVAL; //Uart更新空间
unsigned char i;
WDTCTL = WDTPW + WDTHOLD; // 停止 WDT
InitializeClocks();
InitializeButton();
InitializeLeds();
PreApplicationMode(); // 闪烁LED, 等待按键按下
/* 应用模式开始 */
applicationMode = APP_APPLICATION_MODE;
ConfigureAdcTempSensor(); //配置ADC温度传感器
ConfigureTimerPwm(); //配置定时器PWM
__enable_interrupt(); //使能中断
/* 主函数应用循环 */
while(1)
{
ADC10CTL0 |= ENC + ADC10SC; // 采样和转换开始
__bis_SR_register(CPUOFF + GIE); // LPM0中断使能
/* 移动平均滤波器的8个值进行采样的ADC中有所稳定 */
tempMeasured[tempMeasuredPosition++] = ADC10MEM;
if (tempMeasuredPosition == 8)
tempMeasuredPosition = 0;
tempAverage = 0;
for (i = 0; i < 8; i++)
tempAverage += tempMeasured[i];
tempAverage >>= 3; // 除以8获得平均值,此处采用右移3位实现除以8
if ((--uartUpdateTimer == 0) || calibrateUpdate )
{
ConfigureTimerUart();
if (calibrateUpdate)
{
TXByte = 248; // 一个具有高值的字符, 超过温度范围
Transmit();
calibrateUpdate = 0;
}
TXByte = (unsigned char)( ((tempAverage - 630) * 761) / 1024 );
Transmit();
uartUpdateTimer = UART_UPDATE_INTERVAL;
ConfigureTimerPwm();
}
tempDifference = tempAverage - tempCalibrated;
if (tempDifference < -TEMP_THRESHOLD)
{
tempDifference = -tempDifference;
tempPolarity = TEMP_COLD;
LED_OUT &= ~ LED1;
}
else
if (tempDifference > TEMP_THRESHOLD)
{
tempPolarity = TEMP_HOT;
LED_OUT &= ~ LED0;
}
else
{
tempPolarity = TEMP_SAME;
TACCTL0 &= ~CCIE;
TACCTL1 &= ~CCIE;
LED_OUT &= ~(LED0 + LED1);
}
if (tempPolarity != TEMP_SAME)
{
tempDifference <<= 3;
tempDifference += TIMER_PWM_OFFSET;
TACCR1 = ( (tempDifference) < (TIMER_PWM_PERIOD-1) ? (tempDifference) : (TIMER_PWM_PERIOD-1) );
TACCTL0 |= CCIE;
TACCTL1 |= CCIE;
}
}
}
void PreApplicationMode(void)
{
LED_DIR |= LED0 + LED1;
LED_OUT |= LED0; // LED的切换效果
LED_OUT &= ~LED1;
BCSCTL1 |= DIVA_1; // ACLK/2
BCSCTL3 |= LFXT1S_2; // ACLK = VLO
TACCR0 = 1200;
TACTL = TASSEL_1 | MC_1; // TACLK = SMCLK, Up mode.
TACCTL1 = CCIE + OUTMOD_3; // TACCTL1 Capture Compare
TACCR1 = 600;
__bis_SR_register(LPM3_bits + GIE); // LPM0使能中断
}
void ConfigureAdcTempSensor(void)
{
unsigned char i;
/* 配置ADC温度传感器通道 */
ADC10CTL1 = INCH_10 + ADC10DIV_3; // Temp Sensor ADC10CLK/4
ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
__delay_cycles(1000); // 等待选择ADC参考
ADC10CTL0 |= ENC + ADC10SC; // 采样和转换开始
__bis_SR_register(CPUOFF + GIE); // LPM0使能中断
tempCalibrated = ADC10MEM;
for (i=0; i < 8; i++)
tempMeasured[i] = tempCalibrated;
tempAverage = tempCalibrated;
}
void ConfigureTimerPwm(void)
{
timerMode = TIMER_PWM_MODE;
TACCR0 = TIMER_PWM_PERIOD;
TACTL = TASSEL_2 | MC_1; // TACLK = SMCLK, 截至模式.
TACCTL0 = CCIE;
TACCTL1 = CCIE + OUTMOD_3; // TACCTL1捕获比较
TACCR1 = 1;
}
void ConfigureTimerUart(void)
{
timerMode = TIMER_UART_MODE; // 配置 TimerA0 UART TX
CCTL0 = OUT; // TXD Idle as Mark
TACTL = TASSEL_2 + MC_2 + ID_3; // SMCLK/8, 连续模式
P1SEL |= TXD + RXD; //
P1DIR |= TXD; //
}
void Transmit()
{
BitCnt = 0xA; // 装载位计数器, 8data + ST/SP
while (CCR0 != TAR) // 防止异步捕获
CCR0 = TAR; // 当前TA计数器的状态
CCR0 += Bitime; // 一些时间直到第一位
TXByte |= 0x100; // 新增标记停止位TXByte
TXByte = TXByte << 1; // 加空间的起始位
CCTL0 = CCIS0 + OUTMOD0 + CCIE; // TXD = mark = idle
while ( CCTL0 & CCIE ); // 等待TX完成
}
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
if (timerMode == TIMER_UART_MODE)
{
CCR0 += Bitime; // 新增偏移量CCR0
if (CCTL0 & CCIS0) // TX on CCI0B?
{
if ( BitCnt == 0)
CCTL0 &= ~ CCIE; // All bits TXed, 失能中断
else
{
CCTL0 |= OUTMOD2; // TX Space
if (TXByte & 0x01)
CCTL0 &= ~ OUTMOD2; // TX Mark
TXByte = TXByte >> 1;
BitCnt --;
}
}
}
else
{
if (tempPolarity == TEMP_HOT)
LED_OUT |= LED1;
if (tempPolarity == TEMP_COLD)
LED_OUT |= LED0;
TACCTL0 &= ~CCIFG;
}
}
#pragma vector=TIMERA1_VECTOR
__interrupt void ta1_isr(void)
{
TACCTL1 &= ~CCIFG;
if (applicationMode == APP_APPLICATION_MODE)
LED_OUT &= ~(LED0 + LED1);
else
LED_OUT ^= (LED0 + LED1);
}
void InitializeClocks(void)
{
BCSCTL1 = CALBC1_1MHZ; // 设定范围
DCOCTL = CALDCO_1MHZ;
BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO / 8 = 1MHz
}
void InitializeButton(void) // 配置按钮
{
BUTTON_DIR &= ~BUTTON;
BUTTON_OUT |= BUTTON;
BUTTON_REN |= BUTTON;
BUTTON_IES |= BUTTON;
BUTTON_IFG &= ~BUTTON;
BUTTON_IE |= BUTTON;
}
void InitializeLeds(void)
{
LED_DIR |= LED0 + LED1;
LED_OUT &= ~(LED0 + LED1);
}
/* *************************************************************
*按钮按下口中断
* 1、在待机模式:进入和退出应用模式
* 2、在应用模式:重新调整温度传感器
* *********************************************************** */
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
BUTTON_IFG = 0;
BUTTON_IE &= ~BUTTON; /* 去抖 */
WDTCTL = WDT_ADLY_250;
IFG1 &= ~WDTIFG; /* 清除中断标志 */
IE1 |= WDTIE;
if (applicationMode == APP_APPLICATION_MODE)
{
tempCalibrated = tempAverage;
calibrateUpdate = 1;
}
else
{
applicationMode = APP_APPLICATION_MODE; // 从待机状态切换到应用模式
__bic_SR_register_on_exit(LPM3_bits);
}
}
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
IE1 &= ~WDTIE; /* 失能中断 */
IFG1 &= ~WDTIFG; /* 清除中断标志 */
WDTCTL = WDTPW + WDTHOLD; /* 使 WDT 返回至保持状态 */
BUTTON_IE |= BUTTON; /* 去抖完成 */
}
// ADC10中断服务程序
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
__bic_SR_register_on_exit(CPUOFF); // 返回到Active模式
} |