【转】MSP430 G2553 实现用两块 74HC595 级联控制4位LED

2019-07-20 14:34发布

最近喜欢上了单片机,课程设计做的是STM32的触屏版的万年历。之前一直在专注的学习C语言还有Java,话说这Java居然是在学完Android之后才去深入学的,自己也是醉了。课程设计做起了跟硬件搭点边的东西,真是深感其牛(*)之处(自动屏蔽不雅用词)。此处请各位玩儿硬件长大的,模电电路工程师,数电工程师接下我的各种崇拜。。。你们太牛(*)了。。。
好了,言归正传:手里有一套别人送给我的 MSP430 LanchPad,总是想着不能就那么浪费了,从某宝买来了一些外设,先拿个LED开刀了。

盗张图,无意做宣传,请忽略
串行输入4位LED。输入:Vcc,GND就不说了;SCLK,更新显示。RCLK,数据移位。DIO,数据位。
也看到了,真正的数据线只有三根。
硬件原理图如下图所示:
U1与U2都是74HC595芯片,U2作为段选(用于选择当前是哪一个数码管显示),U1作为片选(用于控制数码管
上的LED显示数字)。
工作原理:1)首先读入8位的数字字模数据,依次移位,现在U2已经保存了数字数据。
2)再次录入8位的段选数据,用来控制当前数字由几号数码管显示。此时,U2保存的是段选数据,而刚刚的片选数据已经通过U2的Q7‘依次传到了U1上。
3)更新显示数据。


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
1条回答
人丑没人疼
1楼-- · 2019-07-20 14:57
例程:

RCLK上升沿触发,将DIO口数据向寄存器中移位。
SCLK上升沿触发,将寄存器中数据读入锁存器,也就是更新显示内容了。

每次只显示一个数码管上的数字,多次遍历刷新。我们就看到了四位不变的数字。

下面的程序代码我已经实现了一个时钟功能,但是还没有添加调整时间的功能,大家可以自己研究一下。


   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148#include <msp430.h>

#define SCLK BIT4
#define RCLK BIT5
#define DIO  BIT7

        // LED字模表
unsigned char LED_0F[] =
{// 0         1          2           3        4         5          6           7        8         9          A           b        C    d          E    F    -    .
        0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf,0x7F
};

// 全局变量
unsigned char LED[6];        //用于LED的8位显示缓存
unsigned int icount=0;
unsigned char isPot=0;

void LED4_Display (void);                        // LED显示
void LED_OUT(unsigned char X);                // LED单字节串行移位函数
void S_Shift(void);
void R_Shift(void);
void CLK_init(void);

void S_Shift(void)
{
        P1OUT &= ~SCLK;
        P1OUT |= SCLK;
}
void R_Shift(void)
{
        P1OUT &= ~RCLK;
        P1OUT |= RCLK;
}


int main(void) {
    WDTCTL = WDTPW | WDTHOLD;         // Stop watchdog timer
        LED[0]=0;
        LED[1]=0;//sec
        LED[2]=0;
        LED[3]=0;//min
        LED[4]=0;
        LED[5]=0;//hour
    P1DIR |=BIT0+SCLK+RCLK+DIO;  //初始化端口
    P1OUT=0;//全部关闭

    BCSCTL3 |= LFXT1S_2;         // Set LFXT1为vol时钟即12kHZ
    CCTL0|= CCIE;                //设置捕获/比较控制寄存器,CCIE=0x0010,使能捕获比较中断
    CCR0 =12000;                 //设置捕获/比较寄存器,初始值为12000,对于ACLK时钟频率为12khz的频率,相当于1s
    TA0CTL = TASSEL_1 +TACLR+MC_1; // 设置定时器A控制寄存器,
    _EINT();


        while(1)
        {
                LED4_Display ();
        }
        return 0;
}


void LED4_Display (void)
{
        unsigned char ichar=0;
        unsigned char led_table;          // 暂存信息
        unsigned char ishift=1;
        for(ichar=2;ichar<6;ichar++){
                //第四位是时间的分隔符
                if(ichar==4) led_table = isPot? LED_0F[LED[ichar]]:LED_0F[LED[ichar]]&LED_0F[17];
                else led_table=LED_0F[LED[ichar]];
                LED_OUT(led_table);
                //移位
                LED_OUT(ishift<<ichar-2);
                R_Shift();
        }
}

void LED_OUT(unsigned char X)
{
        unsigned char i;
        for(i=8;i>=1;i--)
        {
                if (X&0x80)
                        P1OUT |= DIO;
                else
                        P1OUT &= ~DIO;

                X<<=1;
                S_Shift();
        }
}

void s(void)
{
        unsigned int sec=LED[0]+LED[1]*10;
        if(sec<59){
                sec++;
                LED[0]=sec%10;
                LED[1]=sec/10;
        }else{
                sec=0;
                LED[0]=sec%10;
                LED[1]=sec/10;
                m();
        }
}

void m(void)
{
        unsigned int min=LED[2]+LED[3]*10;
                if(min<59){
                        min++;
                        LED[2]=min%10;
                        LED[3]=min/10;
                }else{
                        min=0;
                        LED[2]=min%10;
                        LED[3]=min/10;
                        h();
                }
}

void h(void)
{
        unsigned int hour=LED[4]+LED[5]*10;
                        if(hour<23){
                                hour++;
                                LED[4]=hour%10;
                                LED[5]=hour/10;
                        }else{
                                hour=0;
                                LED[4]=hour%10;
                                LED[5]=hour/10;
                                h();
                        }
}

#pragma vector=TIMER0_A0_VECTOR//固定的格式
__interrupt void Timer_A (void) //定时器A的CC0中断处理程序 必须是没有返回值的
{
        //if(icount++==2){
                if(isPot)isPot=0; else isPot=1; //显示小数点
                 s();
                 //P1OUT^=BIT0;
                 //icount=0;
        //}

}

一周热门 更多>