MSP430G2553两位按键控制两位数码管显示(中断操作,串行数据传输)

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文件。

在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现基于 MSP430G2553 的四数码管动态显示数字 21010814,可以使用定时器和中断实现。下面是一个简单的代码示例,可以实现这个功能: ``` #include <msp430g2553.h> unsigned char num[4] = {2, 1, 0, 8}; // 数码管显示的数字 unsigned char seg[17] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E, 0xBF}; // 数码管段选数据 unsigned char cnt = 0; // 计数器,用于控制数码管显示数 void main() { WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗 P1DIR = 0xFF; // P1口输出 P2DIR |= BIT1 + BIT2 + BIT4 + BIT5; // P2.1~P2.5输出 P2SEL &= ~(BIT1 + BIT2); // P2.1和P2.2设置为GPIO P2OUT &= ~(BIT1 + BIT2 + BIT4 + BIT5); // 数码管选通端口初始化为低电平 TA0CTL = TASSEL_2 + MC_1 + ID_3; // 选择ACLK作为时钟源,计数器模式,分频系数为8 TA0CCR0 = 32768 / 2 - 1; // 定时器周期为0.5秒 TA0CCTL0 = CCIE; // 允许定时器中断 __enable_interrupt(); // 允许中断 while (1) { } } #pragma vector = TIMER0_A0_VECTOR // 定时器中断服务程序 __interrupt void Timer_A(void) { P2OUT = 0x00; // 关闭所有数码管 P1OUT = seg[num[cnt]]; // 显示数字 switch (cnt) // 选择要显示数码管 { case 0: P2OUT = BIT1; break; case 1: P2OUT = BIT2; break; case 2: P2OUT = BIT4; break; case 3: P2OUT = BIT5; break; } cnt++; // 计数器加1 if (cnt >= 4) cnt = 0; // 循环显示数码管 } ``` 该代码中,num 数组存储了数码管显示的数字,seg 数组存储了数码管段选数据。在主函数中,使用定时器 TA0 来定时中断,每次中断时,显示 num 数组中的一个数字。使用 cnt 计数器来控制数码管显示数,每次中断时,cnt 加1,当 cnt 大于等于 4 时,将其重置为 0,以实现循环显示数码管。使用 P1OUT 驱动数码管,使用 P2OUT 选择要显示数码管,每次中断时,先将所有数码管关闭,再根据 cnt 的值选择要显示数码管

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值