⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irremote.c

📁 MSP430单片机常用模块与综合系统实例精讲D第5章程序源码
💻 C
字号:

#include "IRRemote.h"

void main(void)
{
    //初始化
    Initialize();                            
    
    //死循环
    while(1)
    {
        unsigned int transmit;
        //初始化变量
        transmit = ENDTRANSMIT;
        //等待按键按下
        SetForPress();
        //进入LPM4模式
        LPM4;
        
        Debounce(); 
        //扫描键盘
        KeyScan(); 
        //键盘处理
        KeyLookup(); 
        if (Error_Flags == 0) 
        {                 
            //有键按下的情况
            SetupForRelease();
            do 
            { 
                //传输数据(RC5码)
                Transmit();
                
                transmit = TestRetransmit();
                //延时
                DelayToNextTransmit(); 
            } while (transmit == RETRANSMIT);
        }
    }
}

void Initialize(void)
{
    //停止看门狗
    WDTCTL = WDTPW+WDTHOLD;
    //P2口为输出
    P2DIR = 0xFF;
    //P2.3为TA1功能管脚
    P2SEL = 0x08;
    //清除P2口的输出
    P2OUT = 0;
    //设置DCO频率为1MHz
    DCOCTL = CALDCO_1MHZ;
    BCSCTL1 = CALBC1_1MHZ;
    //使能中断
    _EINT(); 
}

void SetForPress(void)
{
    //P1.0和P1.1为输入
    P1DIR = 0xFC;
    //清除P1口的输出,下拉
    P1OUT = 0;
    //使能P1.0和P1.1的电阻
    P1REN |= 0x03; 
    //使能键盘
    P2OUT |= 0x07; 
    //低到高中断方式
    P1IES &= ~0x03;
    //清除中断标志
    P1IFG = 0;
    //使能中断
    P1IE |= 0x03;
    //清除错误标志
    Error_Flags = 0;
    //清除传输标志
    Trans_Flags = 0;
}

void Debounce(void)
{
    //SMCLK/8,清除TA
    TACTL = TASSEL1+TACLR+ID0+ID1;
    //使能CCR0中断
    TACCTL0 = CCIE; 
    //设置延时的值
    TACCR0 = 5000 - 1; 
    //开始UP模式
    TACTL |= MC0;
    //进入LPM0模式
    LPM0;
    //停止并清除TA
    TACTL = TACLR;
    //清除CCTL0寄存器
    TACCTL0 = 0;
}

void KeyScan(void)
{
    unsigned int i;
    
    //初始化行
    RowMask = 0x01;
    KeyHex = 0;
    //清除行的值
    P1OUT &= ~0x03; 
    
    for (i=0; i < 3; i++) 
    {                    
        P2OUT &= ~0x07;
        P1DIR |= 0x03; 
        P1OUT &= ~0x03;
        P1DIR &= ~0x03;
        P2OUT = RowMask;
        if (P1IN & 0x03) 
        {                      
            //是否有键按下
            KeyHex |= RowMask;
            //处理值
            KeyHex |= (P1IN & 0x03) << 4;
        }
        //下一行
        RowMask = RowMask << 1;
    }
    if (KeyHex == 0) 
    {                      
        //设置标志
        Error_Flags |= noKey;
    }
    P2OUT |= 0x07;
}

void KeyLookup(void)
{
    unsigned int i;
  
    //初始化值
    KeyPressed = 99;
    for (i = 0; i < 6; i++) 
    {                     
        //查表
        if (KeyTab[i] == KeyHex) 
        {             
            KeyPressed = i; 
        }
    }
    if (KeyPressed == 99) 
    {                  
        //没有找到值
        //设置标志
        Error_Flags |= noMatch;
    }
}

void SetupForRelease(void)
{
    //设置方向
    P1DIR |= 0x03;
    P1OUT |= 0x03;
    //键被按下
    Trans_Flags |= heldDown;
}

void DetermineRelease(void)
{
    //设置输入下拉
    P1OUT &= ~0x03;
    P1DIR &= ~0x03; 
    if (P1IN & 0x03) 
    {
        SetupForRelease(); 
    } 
    else 
    {
        Trans_Flags &= ~heldDown;
    }
}

void Transmit(void)
{
    unsigned int i;
    
    //得到命令码
    Command = FuncTab[KeyPressed];
    //增加两个位的起始位
    Command = Command + 0x3000; 
    if (Trans_Flags & toggle) 
    {               
        // 切换位
        Command = Command + 0x0800;
    }
    
    //左移
    Command = Command << 2; 
    
    //CCR1 PWM参数
    TACCR1 = 7;
    //使能CCR0中断
    TACCTL0 = CCIE;
    for (i=0; i < 14; i++) 
    {        
        //判断是1还是0
        if (Command & 0x8000) 
        {
            //先发送780us的低
            OutputLow(780);                      
            //然后高,记数32个中断
            OutputHigh(32); 
        } 
        else 
        {
            //先高,记数35个中断
            OutputHigh(35);                      
            OutputLow(765);
        }
        //下一个位
        Command = Command << 1;
    }
    //停止并清除TA
    TACTL = TACLR;
}

unsigned int TestRetransmit(void)
{
    //P1是否有输入
    if (P1IFG == 0) 
    {
        //没有输入的情况下
        return RETRANSMIT;
    } 
    else 
    {    
        //有输入的情况下
        //是否有按键按下
        DetermineRelease();
        if (Trans_Flags & heldDown) 
        {          
            //有的情况下
            return RETRANSMIT;
        } 
        else 
        { 
            // 没有的情况下,返回主程序
            //清除CCTL0寄存器
            TACCTL0 = 0;
            //清除CCTL1寄存器
            TACCTL1 = 0;
            //清除切换位
            Trans_Flags &= ~toggle;
            return ENDTRANSMIT;
        }
    }
}

void DelayToNextTransmit(void)
{
    //SMCLK/8 清除TA
    TACTL = TASSEL1+TACLR+ID0+ID1; 
    //89ms的中断
    TACCR0 = 11125 - 1;
    //使能CCR0中断
    TACCTL0 = CCIE; 
    //TA开始UP模式
    TACTL |= MC0;
    //延时
    LPM0;
    //停止并清除TA
    TACTL = TACLR; 
    //切换切换位
    Trans_Flags ^= toggle;
}

void OutputHigh(unsigned int val)
{
    unsigned int j;
    //CCR1 RESET/SET
    TACCTL1 = OUTMOD_7; 
    //PWM周期(40kHz)
    TACCR0 = 25 - 1;
    //清除TA
    TACTL = TASSEL1+TACLR;
    //TA开始UP模式
    TACTL |= MC0;
    for (j = val; j > 0; j--) 
    {   
        // 中断记数
        //周期40kHz时,每个中断的时间为25us
        LPM0; 
    } 
}

void OutputLow(unsigned int val)
{
    // 设置CC1的输出为0
    TACCTL1 = OUTMOD_0;
    //清TA
    TACTL = TASSEL1+TACLR;
    //延时
    TACCR0 = val; 
    //设置TA为UP模式
    TACTL |= MC0; 
    //进入LPM0模式,等待CCR0中断
    LPM0;
}

// P1.x 中断服务程序
#if __VER__ < 200
    interrupt [PORT1_VECTOR] void P1_ISR(void)
#else
    #pragma vector=PORT1_VECTOR
    __interrupt void P1_ISR(void)
#endif
{
    //退出LPM4低功耗模式
    LPM4_EXIT; 
    //清除中断标志
    P1IFG = 0;
    //中断不使能
    P1IE = 0;
}

// CCR0 中断服务程序
#if __VER__ < 200
    interrupt [TIMERA0_VECTOR] void CCR0_ISR(void)
#else
    #pragma vector=TIMERA0_VECTOR
    __interrupt void CCR0_ISR(void)
#endif
{
    //退出LPM0低功耗模式
    LPM0_EXIT; 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -