打印

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

[复制链接]
1058|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
人丑没人疼|  楼主 | 2016-11-15 23:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

最近喜欢上了单片机,课程设计做的是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)更新显示数据。




相关帖子

沙发
人丑没人疼|  楼主 | 2016-11-15 23:50 | 只看该作者
例程:

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;
        //}

}




来自CODE的代码片main.c



更新:目前已经实现了通过一个按键的长按与短按来调整时间。由于本文主要是让大家理解串行LED屏的工作原理,故不再上传更新后的代码。有需要的亲联系我吧。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

55

主题

97

帖子

0

粉丝