#include <msp430x14x.h>
#include "HDQ.h"
// 定义工作的状态
enum
{
imWrite,
imWriteE,
imRead,
imReadE,
imDelay
};
// 定义全局变量
// 中断服务程序的模式
static unsigned char ISRMode;
// 接收到的数据
static unsigned char Xfer;
// 发送数据的位数
static unsigned char BitCnt;
// 记录时间戳
static unsigned int Ticks;
// Break及恢复
static void HDQBreak(void)
{
// 设置Break的时间
TACCR0 = TAR + tBreak * 2;
// 复位OUT0,使能中断
TACCTL0 = OUTMOD_0 + CCIE;
// 设置中断服务为延时模式
ISRMode = imDelay;
// 进入低功耗模式
_BIS_SR(LPM0_bits);
// 设置Break的恢复时间
TACCR0 += tBR;
// 设置OUT0,使能中断
TACCTL0 = OUTMOD_0 + OUT + CCIE;
// 进入低功耗模式
_BIS_SR(LPM0_bits);
}
// HDQ总线的写操作
static void HDQBasicWrite(unsigned char Data)
{
Xfer = Data;
// 复位OUT0
TACCTL0 = OUTMOD_0;
TACCR0 = TAR;
// 位开始的时间戳
Ticks = TACCR0;
// 设置低电平的时间
if (Xfer & 0x01)
// “1”
TACCR0 += tHW1;
else
// “0”
TACCR0 += tHW0;
// Toggle OUT0,中断使能
TACCTL0 = OUTMOD_4 + CCIE;
// 设置传输的位数为8
BitCnt = 8;
// 中断服务为写模式
ISRMode = imWrite;
// 进入低功耗模式
_BIS_SR(LPM0_bits);
}
void HDQSetup(void)
{
// P1.1为输出
P1DIR |= BIT1;
// 选择TA0功能
P1SEL |= 0x02;
}
// HDQ的写操作
void HDQWrite(unsigned char Addr, unsigned char Data)
{
// 选择SMCLK为时钟源,连续模式
TACTL = TASSEL_2 + MC_2;
// P1.1为输出
P1DIR |= 0x02;
// 总线Break
HDQBreak();
// 发送地址,确保R/W比特为0
HDQBasicWrite(Addr | 0x80);
// 延时
// 设置时间
TACCR0 += tCYCH;
// 设置OUT0,中断使能
TACCTL0 = OUTMOD_0 + OUT + CCIE;
// 设置中断服务为延时模式
ISRMode = imDelay;
// 进入低功耗
_BIS_SR(LPM0_bits);
// 写入数据
HDQBasicWrite(Data);
// P1.1为输入
P1DIR &= ~0x02;
// 停止Timer_A
TACTL = 0;
}
// HDQ的读操作
unsigned int HDQRead(unsigned char Addr)
{
// 选择SMCLK为时钟源,连续模式
TACTL = TASSEL_2 + MC_2;
// P1.1为输出
P1DIR |= 0x02;
// 总线Break
HDQBreak();
// 发送地址
HDQBasicWrite(Addr);
// P1.1为输入
P1DIR &= ~0x02;
// 设置数据为8位
BitCnt = 8;
// 设置中断服务为读模式
ISRMode = imRead;
// 在P1.1管脚捕获下降沿
TACCTL0 = CM_2 + CCIS_0 + SCCI + CAP + CCIE;
// 设置超时时间
TACCR1 = TAR + tTO;
// 使能中断
TACCTL1 = CCIE;
// 进入低功耗
_BIS_SR(LPM0_bits);
// 停止Timer_A
TACTL = 0;
// 判断数据是否有效
if (BitCnt)
return 0xffff;
else
return Xfer;
}
void Init_CLK(void)
{
unsigned int i;
//将寄存器的内容清零
//XT2震荡器开启
//LFTX1工作在低频模式
//ACLK的分频因子为1
BCSCTL1 = 0X00;
do
{
// 清除OSCFault标志
IFG1 &= ~OFIFG;
for (i = 0x20; i > 0; i--);
}
while ((IFG1 & OFIFG) == OFIFG);
BCSCTL2 = 0X00;
//MCLK的时钟源为TX2CLK,分频因子为4
BCSCTL2 += SELM1 + DIVM_2;
//SMCLK的时钟源为TX2CLK,分频因子为4
BCSCTL2 += SELS + DIVS_2;
}
interrupt [TIMERA0_VECTOR] void Timer_A0_ISR(void)
{
switch (ISRMode)
{
case imWrite :
if (--BitCnt)
{
// 设置时间
TACCR0 = Ticks + tCYCH;
ISRMode = imWriteE;
}
else
{
// 设置OUT0,禁止中断
TACCTL0 = OUTMOD_0 + OUT;
// 返回激活状态
_BIC_SR(LPM0_bits);
}
break;
case imWriteE :
// 位开始时间戳
Ticks = TACCR0;
if ((Xfer >>= 1) & 0x01)
// “1”
TACCR0 += tHW1;
else
// “0”
TACCR0 += tHW0;
ISRMode = imWrite;
break;
case imRead :
// 停止超时
TACCTL1 = 0;
// 在位的中央采样
TACCR0 += (tDW0 + tDW1) / 2;
// 捕获模式
TACCTL0 &= ~CAP;
ISRMode = imReadE;
break;
case imReadE :
Xfer >>= 1;
// 检查Timer_A的锁存
if (TACCTL0 & SCCI)
Xfer |= 0x80;
if (--BitCnt)
{
// 捕获模式
TACCTL0 |= CAP;
// 设置超时
TACCR1 = TAR + tTO;
// 使能中断
TACCTL1 = CCIE;
// 读模式
ISRMode = imRead;
}
else
{
// 设置OUT0,禁止中断
TACCTL0 = OUTMOD_0 + OUT;
// 返回激活状态
_BIC_SR(LPM0_bits);
}
break;
case imDelay :
// 禁止中断
TACCTL0 &= ~CCIFG;
// 返回激活状态
_BIC_SR(LPM0_bits);
break;
}
}
interrupt [TIMERA1_VECTOR] void Timer_A1_ISR(void)
{
if (TAIV == 0x02)
{
TACCTL0 = 0;
TACCTL1 = 0;
// 返回激活状态
_BIC_SR(LPM0_bits);
}
}