历史上的今天
返回首页

历史上的今天

今天是:2025年01月29日(星期三)

2018年01月29日 | MSP430单片机按键中断程序

2018-01-29 来源:eefocus

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


IRRemote.h

#include  "MSP430x21x1.h" 

#define   noKey       0x001 
#define   noMatch     0x002 
#define   heldDown    0x001 
#define   toggle      0x002 
#define   RETRANSMIT  1 
#define   ENDTRANSMIT 0 

// 按键查询表 
const char KeyTab[6] = { 
  0x11,     // 按键 0 
  0x21,     // 按键 1 
  0x12,     // 按键 2 
  0x22,     // 按键 3 
  0x14,     // 按键 4 
  0x24      // 按键 5 
}; 

// 函数查询表 
const char FuncTab[6] = { 
  0x0C,   // 按键 0 - 电源 
  0x0D,   // 按键 1 - 静音 
  0x20,   // 按键 2 - 频道+ 
  0x10,   // 按键 3 - 音量+ 
  0x21,   // 按键 4 - 频道- 
  0x11    // 按键 5 - 音量- 
}; 

unsigned int RowMask; 
unsigned int KeyHex; 
unsigned int KeyVal; 
unsigned int KeyPressed; 
unsigned int Command; 
unsigned int Trans_Flags; 
unsigned int Error_Flags;                     

void Initialize(void); 
void SetForPress(void); 
void Debounce(void); 
void KeyScan(void); 
void KeyLookup(void); 
void SetupForRelease(void); 
void DetermineRelease(void); 
void Transmit(void); 
unsigned int TestRetransmit(void); 
void DelayToNextTransmit(void); 
void OutputHigh(unsigned int); 
void OutputLow(unsigned int); 


推荐阅读

史海拾趣

E-Mark Inc公司的发展小趣事

JKL公司是一家创新型电子企业,专注于研发新能源汽车电子控制系统。为了推动新能源汽车的发展并满足欧洲市场的需求,JKL公司决定对其产品进行E-Mark认证。在认证过程中,JKL公司积极投入研发资源,不断创新技术,提升产品的智能化和安全性。最终,JKL公司的产品成功获得了E-Mark认证,并在欧洲市场得到了广泛应用和认可。这一认证不仅加速了JKL公司新能源汽车技术的市场推广速度,也提升了公司在国际市场的竞争力。

API Technologies公司的发展小趣事

API Technologies一直将品质管理作为公司的核心竞争力之一。公司建立了完善的质量管理体系,从原材料采购到产品生产的每一个环节都进行严格的质量控制。同时,公司还注重持续改进和优化生产流程,提高生产效率和产品质量。这些措施使得API Technologies的产品在市场上具有极高的口碑和竞争力。

APX Technologies公司的发展小趣事

APX Technologies在追求经济效益的同时,也积极履行社会责任。公司注重环保和可持续发展,致力于研发和生产低能耗、低污染的电子产品。此外,APX Technologies还积极参与社会公益活动,为社会的和谐发展贡献自己的力量。这些举措不仅提升了公司的品牌形象,也赢得了社会各界的广泛赞誉。

以上五个故事均基于虚构的APX Technologies公司的发展情况,旨在展示一个电子行业公司可能经历的不同发展阶段和面临的挑战。这些故事并不代表任何真实情况,仅供参考和启发。

强盛电子(AEC)公司的发展小趣事

面对国内市场的饱和,AEC决定实施国际化战略,拓展海外市场。公司首先在欧洲设立了研发中心,随后在北美和亚洲等地建立了销售网络和生产基地。通过不断优化产品结构和提升服务质量,AEC逐渐在国际市场上树立起了良好的品牌形象,成为一家具有全球影响力的电子企业。

AMSCO [Austria micro systems AG]公司的发展小趣事

强盛电子(AEC)自成立以来,一直致力于电子技术的研发与创新。公司研发团队经过数年的努力,成功开发出一款具有颠覆性的新型芯片,这款芯片在性能上远超当时的同类产品,引起了市场的广泛关注。随着这款芯片的量产和上市,AEC的市场份额迅速扩大,成为行业内的佼佼者。

Apacer公司的发展小趣事

随着科技的不断发展,Apacer宇瞻科技紧跟时代步伐,不断创新产品。2006年,公司推出了存储容量高达2GB的microSD卡,这款数码卡体积仅为普通SD卡的四分之一,但存储容量却与之不相上下。这一创新产品不仅满足了市场对高容量、小型化存储设备的需求,也进一步巩固了宇瞻科技在市场上的地位。

问答坊 | AI 解惑

数字电路非常基础的教材

数字电路非常基础的教材…

查看全部问答>

来讨论下VHDL里边的库吧

最近用VHDL编程,发现有很多时候遇到《Error (10327): VHDL error at and2.vhd(11): can\'t determine definition of operator \"\"+\"\" -- found 0 possible definitions》这样的问题,开始不知道为什么,后来在知道不同的数据类型的运算是定义在 ...…

查看全部问答>

为什么9650预览的图像很红?

原来我的9650输出图像时30万像素的,可以正常显示图像。 可是我从代理要到了130万像素的配置后,图像发红,而且是很红。 不知道有没有遇到这种情况的?是如何解决的?…

查看全部问答>

做一个受欢迎的提问者

要想让你的问题尽快得到解答,我想以下几条是你应该注意的: 1.首先说清楚你使用的软,硬件平台。比如:我使用wince5.0在 2440上做开发... 2.问题要尽量具体,不要问诸如:我要做一个什么项目,该怎么做?或者我要做一个什么软件,该怎么做这类的 ...…

查看全部问答>

向大家请教一下!

#define TRANDATA_TOGSM_TIMES 0350h #define UP_3mA 0352h #define UP_10mA 035Eh ;这是一个6个字长的数组,放置峰值大于10mA的数量 ;该数组占据的地址空间为35E/360/362/364/366/368 #define Rain_Counter_Day 0400 ...…

查看全部问答>

生产厂家规范的-- LED驱动电源测试报告范例

replyreload += \',\' + 1365593;这份报告是基于一个8W LED驱动电源临时做的一个基本范例,是考虑有公司商业机密的问题,略作修改: 1.不对版权负责,只供参考. 2.不对内容负责,不做解释.每家公司各不相同,难于解释不同.敬请谅解. Timson,如果您要 ...…

查看全部问答>

[转贴]实施DDR 2 / mddr布局的tms320dm35x dmsoc 大家可以参考一下!很有用!!

摘要:         该tms320dm35x数字媒体系统芯片(dmsoc)装置。该方法来指定接口时序的DDR 2 / mddr接口是完全不同的,比以前的设备。         前一种方法指定计时装置在数据表规格 ...…

查看全部问答>

ad测量通过串口发出的程序,只能发出FF

我用AD采样,然后想通过串口发出,结果只能得到FF。大家帮我看看那里出现了问题,谢谢 #include  \"msp430g2553.h\" #define uchar unsigned char long temp; void uart_init(void) {         BCSCTL1 = CAL ...…

查看全部问答>

鍵盤A鍵和B鍵交替輸入效果

將鍵盤上A鍵和B鍵的4個接觸點伸延出來(因為是接觸按鍵,所以每個按鍵都有2個接觸點), 我想透過一組電子零件來接駁伸延出的4個接觸點, 啟動該製成品後在顯示螢幕上出現ABABABAB...連續按鍵的效果。 當然如果使用軟件來達成簡直是易如反掌,但我 ...…

查看全部问答>