历史上的今天
今天是: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);
下一篇:MSP430单片机按键程序
史海拾趣
|
最近用VHDL编程,发现有很多时候遇到《Error (10327): VHDL error at and2.vhd(11): can\'t determine definition of operator \"\"+\"\" -- found 0 possible definitions》这样的问题,开始不知道为什么,后来在知道不同的数据类型的运算是定义在 ...… 查看全部问答> |
|
原来我的9650输出图像时30万像素的,可以正常显示图像。 可是我从代理要到了130万像素的配置后,图像发红,而且是很红。 不知道有没有遇到这种情况的?是如何解决的?… 查看全部问答> |
|
要想让你的问题尽快得到解答,我想以下几条是你应该注意的: 1.首先说清楚你使用的软,硬件平台。比如:我使用wince5.0在 2440上做开发... 2.问题要尽量具体,不要问诸如:我要做一个什么项目,该怎么做?或者我要做一个什么软件,该怎么做这类的 ...… 查看全部问答> |
|
replyreload += \',\' + 1365593;这份报告是基于一个8W LED驱动电源临时做的一个基本范例,是考虑有公司商业机密的问题,略作修改: 1.不对版权负责,只供参考. 2.不对内容负责,不做解释.每家公司各不相同,难于解释不同.敬请谅解. Timson,如果您要 ...… 查看全部问答> |
|
[转贴]实施DDR 2 / mddr布局的tms320dm35x dmsoc 大家可以参考一下!很有用!! 摘要: 该tms320dm35x数字媒体系统芯片(dmsoc)装置。该方法来指定接口时序的DDR 2 / mddr接口是完全不同的,比以前的设备。 前一种方法指定计时装置在数据表规格 ...… 查看全部问答> |
|
我用AD采样,然后想通过串口发出,结果只能得到FF。大家帮我看看那里出现了问题,谢谢 #include \"msp430g2553.h\" #define uchar unsigned char long temp; void uart_init(void) { BCSCTL1 = CAL ...… 查看全部问答> |
|
將鍵盤上A鍵和B鍵的4個接觸點伸延出來(因為是接觸按鍵,所以每個按鍵都有2個接觸點), 我想透過一組電子零件來接駁伸延出的4個接觸點, 啟動該製成品後在顯示螢幕上出現ABABABAB...連續按鍵的效果。 當然如果使用軟件來達成簡直是易如反掌,但我 ...… 查看全部问答> |




