- #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);
- }
- }