单片机:MSP430f149
实现功能:按下一个按键,计时开始,再次按下该按键计时暂停,即由一个按键实现暂停看开始功能,设置另一个按键,按下该按键三秒以上,秒表清零。要求计时精度,10毫秒。
该实验用到了MSP430单片机的timerA的定时功能,显示设备而用到了LCD1602.
代码如下:
#include
#include "Config.h"
int second = 0, minute = 0, count = 0, flag = 0, a = 0, b = 0, c = 0;
unsigned char FlagLcd;
//*************************************************************************
// 初始化IO口子程序
//*************************************************************************
void Port_init()
{
P4SEL = 0x00;
P4DIR = 0xFF; //数据口输出模式
P5SEL = 0x00;
P5DIR|= BIT5 + BIT6 + BIT7; //控制口设置为输出模式
P1SEL = 0x00; //P1普通IO功能
P1DIR = 0xF0; //P10~P13输入模式,外部电路已接上拉电阻
P1IE = 0x0f; //开启 位中断
P1IES = 0x00; //上升沿触发中断
P1IFG = 0x00; //软件清零中断标志寄存器
}
//***********************************************************************
// 显示屏命令写入函数
//***********************************************************************
void LCD_write_com(unsigned char com)
{
RS_CLR;
RW_CLR;
EN_SET;
DataPort = com; //命令写入端口
delay_ms(5);
EN_CLR;
}
//***********************************************************************
// 显示屏数据写入函数
//***********************************************************************
void LCD_write_data(unsigned char data)
{
RS_SET;
RW_CLR;
EN_SET;
DataPort = data; //数据写入端口
delay_ms(5);
EN_CLR;
}
//***********************************************************************
// 显示屏清空显示
//***********************************************************************
void LCD_clear(void)
{
LCD_write_com(0x01); //清屏幕显示
delay_ms(5);
}
//***********************************************************************
// 显示屏字符串写入函数
//***********************************************************************
void LCD_write_str(unsigned char x,unsigned char y,int w)
{
if (y == 0)
{
LCD_write_com(0x80 + x); //第一行显示
}
else
{
LCD_write_com(0xC0 + x); //第二行显示
}
LCD_write_data(48+w);
}
//***********************************************************************
// 显示屏单字符写入函数
//***********************************************************************
void LCD_write_char(unsigned char x,unsigned char y,unsigned char data)
{
if (y == 0)
{
LCD_write_com(0x80 + x); //第一行显示
}
else
{
LCD_write_com(0xC0 + x); //第二行显示
}
LCD_write_data( data);
}
//***********************************************************************
// 显示屏初始化函数
//***********************************************************************
void LCD_init(void)
{
LCD_write_com(0x38); //显示模式设置
delay_ms(5);
LCD_write_com(0x08); //显示关闭
delay_ms(5);
LCD_write_com(0x01); //显示清屏
delay_ms(5);
LCD_write_com(0x06); //显示光标移动设置
delay_ms(5);
LCD_write_com(0x0C); //显示开及光标设置
delay_ms(5);
}
//***********************************************************************
// TIMERA初始化,设置为UP模式计数
//***********************************************************************
void TIMERA_Init(void) //UP模式计数,计数周期为CCR0+1
{
TACTL |= TASSEL1 + TACLR + ID0 + ID1 + MC0 + TAIE; //SMCLK做时钟源,8分频,增加计数模式,开中断
TACCR0 = 9999; //CCR0=9999,10ms中断一次
}
//***********************************************************************
// 关闭计时,暂停计数
//***********************************************************************
void TimerA_end(void)
{
TACTL &= 0xfffd;
}
//**********************************************************************
// 扫描按键P1^2是否长按
//**********************************************************************
void GetKey()//长按,返回2;短按,返回1。
{
unsigned char keyRetu=0; //返回的按键值
static unsigned char s_keyState=0,keyTime=0; //按键状态,按键按下的时间
switch (s_keyState)
{
case 0:
{
if((P1IN&0x02)==0x00) //检测到有按键,转到状态1,相当于是消抖过程。
{
s_keyState=1;
}
}
break;
case 1:
{
if((P1IN&0x02)==0x00) //再次检测到有按键,转到状态2
{
s_keyState=2;
keyTime=0; //清零按键时间计数器
}
else
{
s_keyState=0; //没有检测到按键,说明状态0检测到是一个抖动,重新转到状态0
}
}
break;
case 2:
{
if((P1IN&0x02)==0x02) //检测到按键松开
{
s_keyState=0; //状态转到状态0
keyRetu=1; //输出1
}
else
{
if(++keyTime>=150) //按下时间>1s
{
s_keyState=3; //转到状态3
keyTime=0; //清零按键时间计数器
keyRetu=2; // 输出2
}
}
}
break;
case 3:
{
if((P1IN&0x02)==0x02) //检测到按键松开
{
s_keyState=0; //状态转到状态0
}
else
{
s_keyState=3; //转到状态3
}
}
break;
}
if(keyRetu==2)
{
a = 0;
b = 0;
c = 0;
count = 0;
second = 0;
minute = 0;
}
}
//***********************************************************************
// TIMERA中断服务程序,需要判断中断类型
//***********************************************************************
#pragma vector = TIMERA1_VECTOR
__interrupt void Timer_A(void)
{
switch(TAIV) //需要判断中断的类型
{
case 2:break;
case 4:break;
case 10:count++;break; //设置标志位Flag
}
if(count==100) //100次为1秒
{
second++;
count=0;
}
if(second == 60)
{
minute++;
second = 0;
}
GetKey();
}
//**********************************************************************
// P1口中断服务程序,需要判断
//**********************************************************************
#pragm
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』