MSP430G2553两位按键控制两位数码管显示(中断操作)
一、设计要求
基于MSP430G2553单片机,通过串行数据传输,利用两个按键实现两位数码管的加减显示。(笔者是小白,若有错误请原谅并指出,本篇文章基本上涵盖了前几篇文章的基础知识,所以在此稍微写详细一点,做个综合内容)
软件:CCS、Proteus
二、电路设计
搭建MSP430G2553的最小系统,将P2.6作为时钟输出口,P2.7作为数据输出口,P2.3和P2.4作为中断操作控制端口。将两个74HC164驱动芯片串行连接,CLK采用并行连接,保证具有相同的时钟信号。按键没有做硬件消抖处理,后续做一个简单的软件消抖处理。
三、代码设计
1、数码管数据数组
根据数码管的连接方式,确定BIT0-BIT6对应的数码管显示位置,从而确定数字0-9的显示方法。
对应关系如下:
unsigned char code_seg7[10]={
BIT0+BIT1+BIT2+BIT3+BIT4+BIT5,//0
BIT1+BIT2,//1
BIT0+BIT1+BIT3+BIT4+BIT6,//2
BIT0+BIT1+BIT2+BIT3+BIT6,//3
BIT1+BIT2+BIT5+BIT6,//4
BIT0+BIT2+BIT3+BIT5+BIT6,//5
BIT0+BIT2+BIT3+BIT4+BIT5+BIT6,//6
BIT0+BIT1+BIT2,//7
BIT0+BIT1+BIT2+BIT3+BIT4+BIT5+BIT6,//8
BIT0+BIT1+BIT2+BIT3+BIT5+BIT6//9
};
2、子函数创建
(1)延时函数
void delay_ms(int ms)//延时函数
{
for(;ms>0;ms--) __delay_cycles(1000);
}
(2)74HC164驱动函数
根据74HC164移位寄存器的时序图编写驱动函数,先写入高位数据D7,当下降沿到来时,实现数据左移。
void seg72ms_low(unsigned char seg71_data)//74HC164低位驱动函数
{
signed char i;
unsigned char seg71_code; //声明显示代码变量
unsigned char BIT_seg7[8]={BIT7,BIT6,BIT5,BIT4,BIT3,BIT2,BIT1,BIT0};//循环对比变量
seg71_code = code_seg7[seg71_data];//数据译码
P2OUT &= ~BIT6; //串行数据接口初始化
P2OUT &= ~BIT7;
for(i = 0; i < 8; i++)
{
if(seg71_code & BIT_seg7[i]) //输出显示代码第七位
{
P2OUT |= BIT7; //置1
}
else
{
P2OUT &= ~BIT7; //置0
}
P2OUT |= BIT6; //产生脉冲上升沿
P2OUT &= ~BIT6; //产生下降沿
}
}
void seg72ms_high(unsigned char seg71_data)//74HC164高位驱动函数
{
signed char i;
unsigned char seg71_code; //声明显示代码变量
unsigned char BIT_seg7[8]={BIT7,BIT6,BIT5,BIT4,BIT3,BIT2,BIT1,BIT0};//循环对比变量
seg71_code = code_seg7[seg71_data];//数据译码
P2OUT &= ~BIT6; //串行数据接口初始化
P2OUT &= ~BIT7;
for(i = 0; i < 8; i++)
{
if(seg71_code & BIT_seg7[i]) //输出显示代码第七位
{
P2OUT |= BIT7; //置1
}
else
{
P2OUT &= ~BIT7; //置0
}
P2OUT |= BIT6; //产生脉冲上升沿
P2OUT &= ~BIT6; //产生下降沿
}
}
void seg72ms_2(unsigned char seg71_data1,unsigned char seg71_data2) //调用高低位驱动函数
{
seg72ms_high(seg71_data1);
seg72ms_low(seg71_data2);
}
(3)函数声明和全局变量创建
//函数声明
void delay_ms(int ms); //延时函数
void seg72ms_low(unsigned char seg71_data);//低位驱动函数
void seg72ms_high(unsigned char seg71_data);//高位驱动函数
void seg72ms_2(unsigned char seg71_data1,unsigned char seg71_data2);//高低位驱动函数调用
signed char data_key; //声明按键变量
signed char data_seg7_high;//数码管高位数据
signed char data_seg7_low; //数码管低位数据
(4)中断函数
使用的单片机的P2端口,所以中断向量为PORT2_VECTOR。
注:延时时间不能太长,否则会出现中断还未执行完,而下一次按键已经触发,导致系统无反应的情况
#pragma vector=PORT2_VECTOR //设置中断向量
__interrupt void PORT2_Key(void)//按键增加中断
{
_DINT();//关闭全局中断
if(P2IFG & BIT3) //如果按下电路图中下方的按键
{
data_key++; //按键变量增加
if(data_key > 0 && data_key < 23)//限制按键变量的范围
{
data_seg7_high = data_key / 10; //获得高位数据
data_seg7_low = data_key % 10; //获得低位数据
seg72ms_2(data_seg7_high,data_seg7_low); //数码管显示当前数值
delay_ms(20); //延时函数
}
if(data_key > 22)//如果数据超出范围,将数据恢复到0初始值
{
data_key = 0;
seg72ms_2(0,0); // 数码管显示00
}
P2IFG=0x00; // 清除中断标志
}
else if(P2IFG & BIT4) //如果按下电路图中上方的按键
{
data_key--; //按键数据变量减少
if(data_key > 0)
{
data_seg7_high = data_key / 10; //获得高位数据
data_seg7_low = data_key % 10; //获得低位数据
seg72ms_2(data_seg7_high,data_seg7_low);// 数码管显示当前数值
delay_ms(20); // 延时函数
}
if(data_key < 0)
{
data_key = 22;
data_seg7_high = data_key / 10; //获得高位数据
data_seg7_low = data_key % 10; //获得低位数据
seg72ms_2(data_seg7_high,data_seg7_low);// 数码管显示当前数值
delay_ms(20); // 延时函数
}
P2IFG=0x00; // 清除中断标志
}
}
(5)主函数
主函数中主要做端口的初始化配置
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer关闭看门狗
P2SEL &= ~BIT6;//功能选择寄存器
P2SEL2 &= ~BIT6;
P2DIR |= BIT6;//将P2设置为输出,P2DIR使P2口的方向寄存器
P2SEL &= ~BIT7;//功能选择寄存器
P2SEL2 &= ~BIT7;
P2DIR |= BIT7;//将P2设置为输出,P2DIR使P2口的方向寄存器
P2SEL &= ~BIT3; // 设置 P2.3 管脚为并行数字输入 / 输出管脚
P2SEL2 &= ~BIT3;
P2DIR &= ~BIT3; // 设置 P2.3 管脚为输入管脚
P2IE |= BIT3; // 使能 P2.3 管脚的中断
P2IES |= BIT3; // 设置 P2.3 下降沿中断
P2SEL &= ~BIT4; // 设置 P2.4 管脚为并行数字输入 / 输出管脚
P2SEL2 &= ~BIT4;
P2DIR &= ~BIT4; // 设置 P2.4 管脚为输入管脚
P2IE |= BIT4; // 使能 P2.4 管脚的中断
P2IES |= BIT4; // 设置 P2.4 下降沿中断
P2IFG = 0x00; // 清除中断标志
_EINT(); //开启全局中断
data_key = 0; //数据初始化
while(1)
{
}
return 0;
}
3、总工程代码
#include <msp430.h>
/**
* main.c
*/
unsigned char code_seg7[10]={
BIT0+BIT1+BIT2+BIT3+BIT4+BIT5,//0
BIT1+BIT2,//1
BIT0+BIT1+BIT3+BIT4+BIT6,//2
BIT0+BIT1+BIT2+BIT3+BIT6,//3
BIT1+BIT2+BIT5+BIT6,//4
BIT0+BIT2+BIT3+BIT5+BIT6,//5
BIT0+BIT2+BIT3+BIT4+BIT5+BIT6,//6
BIT0+BIT1+BIT2,//7
BIT0+BIT1+BIT2+BIT3+BIT4+BIT5+BIT6,//8
BIT0+BIT1+BIT2+BIT3+BIT5+BIT6//9
};
//函数声明
void delay_ms(int ms);
void seg72ms_low(unsigned char seg71_data);
void seg72ms_high(unsigned char seg71_data);
void seg72ms_2(unsigned char seg71_data1,unsigned char seg71_data2);
signed char data_key;//声明按键变量
signed char data_seg7_high;//数码管高位变量
signed char data_seg7_low;//数码管低位变量
#pragma vector=PORT2_VECTOR//设置中断向量
__interrupt void PORT2_Key(void)//按键增加中断
{
_DINT();//关闭全局中断
if(P2IFG & BIT3)
{
data_key++;
if(data_key > 0 && data_key < 23)
{
data_seg7_high = data_key / 10;
data_seg7_low = data_key % 10;
seg72ms_2(data_seg7_high,data_seg7_low);// 数码管显示当前数值
delay_ms(20); // 延时函数
}
if(data_key > 22)
{
data_key = 0;
seg72ms_2(0,0); // 数码管显示00
}
P2IFG=0x00; // 清除中断标志
}
else if(P2IFG & BIT4)
{
data_key--;
if(data_key > 0)
{
data_seg7_high = data_key / 10;
data_seg7_low = data_key % 10;
seg72ms_2(data_seg7_high,data_seg7_low);// 数码管显示当前数值
delay_ms(20); // 延时函数
}
if(data_key < 0)
{
data_key = 22;
seg72ms_2(data_seg7_high,data_seg7_low);// 数码管显示当前数值
delay_ms(20); // 延时函数
}
P2IFG=0x00; // 清除中断标志
}
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer关闭看门狗
P2SEL &= ~BIT6;//功能选择寄存器
P2SEL2 &= ~BIT6;
P2DIR |= BIT6;//将P2设置为输出,P2DIR使P2口的方向寄存器
P2SEL &= ~BIT7;//功能选择寄存器
P2SEL2 &= ~BIT7;
P2DIR |= BIT7;//将P2设置为输出,P2DIR使P2口的方向寄存器
P2SEL &= ~BIT3; // 设置 P2.3 管脚为并行数字输入 / 输出管脚
P2SEL2 &= ~BIT3;
P2DIR &= ~BIT3; // 设置 P2.3 管脚为输入管脚
P2IE |= BIT3; // 使能 P2.3 管脚的中断
P2IES |= BIT3; // 设置 P2.3 下降沿中断
P2SEL &= ~BIT4; // 设置 P2.4 管脚为并行数字输入 / 输出管脚
P2SEL2 &= ~BIT4;
P2DIR &= ~BIT4; // 设置 P2.4 管脚为输入管脚
P2IE |= BIT4; // 使能 P2.4 管脚的中断
P2IES |= BIT4; // 设置 P2.4 下降沿中断
P2IFG = 0x00; // 清除中断标志
_EINT(); //开启全局中断
data_key = 0; //数据初始化
while(1)
{
}
return 0;
}
void delay_ms(int ms)//延时函数
{
for(;ms>0;ms--) __delay_cycles(1000);
}
void seg72ms_low(unsigned char seg71_data)//74HC164驱动函数
{
signed char i;
unsigned char seg71_code; //声明显示代码变量
unsigned char BIT_seg7[8]={BIT7,BIT6,BIT5,BIT4,BIT3,BIT2,BIT1,BIT0};//循环对比变量
seg71_code = code_seg7[seg71_data];//数据译码
P2OUT &= ~BIT6; //串行数据接口初始化
P2OUT &= ~BIT7;
for(i = 0; i < 8; i++)
{
if(seg71_code & BIT_seg7[i]) //输出显示代码第七位
{
P2OUT |= BIT7; //置1
}
else
{
P2OUT &= ~BIT7; //置0
}
P2OUT |= BIT6; //产生脉冲上升沿
P2OUT &= ~BIT6; //产生下降沿
}
}
void seg72ms_high(unsigned char seg71_data)//74HC164驱动函数
{
signed char i;
unsigned char seg71_code; //声明显示代码变量
unsigned char BIT_seg7[8]={BIT7,BIT6,BIT5,BIT4,BIT3,BIT2,BIT1,BIT0};//循环对比变量
seg71_code = code_seg7[seg71_data];//数据译码
P2OUT &= ~BIT6; //串行数据接口初始化
P2OUT &= ~BIT7;
for(i = 0; i < 8; i++)
{
if(seg71_code & BIT_seg7[i]) //输出显示代码第七位
{
P2OUT |= BIT7; //置1
}
else
{
P2OUT &= ~BIT7; //置0
}
P2OUT |= BIT6; //产生脉冲上升沿
P2OUT &= ~BIT6; //产生下降沿
}
}
void seg72ms_2(unsigned char seg71_data1,unsigned char seg71_data2)
{
seg72ms_high(seg71_data1);
seg72ms_low(seg71_data2);
}
四、CCS生成.hex文件
在工程文件中右键,在属性栏中选择----->Properties
使能MSP430 Hex Utility
点击左侧的Output Format Options,将Output format设置为 Intel hex(–intel,-i)
最后重新编译代码,即可在左侧工程Debug文件中找到.hex文件。