74HC595芯片工作原理解析与跑马灯数码管应用程序详解
74HC595芯片应用—–day2
1.CMOS移位寄存器–74HC595
可串行输出控制下一级级联芯片。是移位寄存器清零端。0时会将数据清0,发送数据时需要置高。
依次完成8位数据移动,Q7’级联下一级输出用原理相同,OE为数据输出使能,高电平有效。
STC为时钟控制,当8位数据或者16位数据发送完成后使能高电平完成整个数据发送流程。
级联如下图所示:
U17的SQH输出脚连接U13的A输入脚位上。
一次输入16位数据。
时序图如下所示:
级联后的HC595为最先接收发送数据的位置。占数组的第一位值即QA ,依次为QH/QG/QF/QE/QD/QC/QB/QA共8位 前一级为QH/QG/QF/QE/QD/QC/QB/QA
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0x8000表示点亮第一个D9 —– QH的灯。
QH/QG/QF/QE/QD/QC/QB/QA共8位 前一级为QH/QG/QF/QE/QD/QC/QB/QA
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0x0100表示点亮第一个D2 —– QA的灯。
程序如下:
sbit HC595_SCK = P0^5;
sbit HC595_RCK = P0^6;
sbit HC595_DATA = P0^7;
code unsigned int Led8_One_Array[16] = {0x8000,0x4000,0x2000, 0x1000, 0x0800, 0x0400,0x0200,0x0100,0x0080,0x0040,0x0020,0x0010,0x0008,0x0004,0x0002,0x0001,};
void Send_Data(unsigned int Led8_One)
{
unsigned char i;
HC595_RCK = 0;
for(i = 0; i < 16;i ++)
{
HC595_SCK = 0;
if(0 != (Led8_One & 0x8000)) //0X80 = 0B1000 0000 二合一每个输入数据为16位数组。
{
HC595_DATA = 1;
}
else
{
HC595_DATA = 0;
}
Led8_One = Led8_One<<1;
HC595_SCK = 1;
}
// for(i = 0; i < 8;i ++)
// {
// HC595_SCK = 0;
// if(0 != (Led8_Two & 0x80)) //0X80 = 0B1000 0000
// {
// HC595_DATA = 1;
// }
// else
// {
// HC595_DATA = 0;
// }
//
// Led8_Two = Led8_Two<<1;
// HC595_SCK = 1;
// }
HC595_RCK = 1; //发送一个16位数据后将数据输出到端口。
}
void delay_1ms(int i)
{
int j;
for( ;i>0;i--)
{
for(j = 0;j < 110;j++)
{}
}
}
void main()
{
unsigned char k;
while(1)
{
for(k = 0;k < 16;k ++)
{
Send_Data(Led8_One_Array[k]);
delay_1ms(1000);
}
}
}
上述程序可应用为数码管或者扩单片机IO扩展。数码管时需要级联。
流水灯,两边往中间跑,汇合后在往两边跑依次循环进行,纯属娱乐。
哈哈哈。有趣
unsigned char j=0;
sbit HC595_SCK = P0^5;
sbit HC595_RCK = P0^6;
sbit HC595_DATA = P0^7;
unsigned char k=0;
code unsigned char Led8_One_Array[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
code unsigned char Led8_One_Array2[8] = {0x80,0x40,0x20, 0x10, 0x08, 0x04,0x02,0x01};
void Send_Data(unsigned char Led8_One,unsigned char Led8_Two)
{
unsigned char i;
HC595_RCK = 0;
for(i = 0; i < 8;i ++)
{
HC595_SCK = 0;
if(0 != (Led8_One & 0x80)) //0X80 = 0B1000 0000
{
HC595_DATA = 1;
}
else
{
HC595_DATA = 0;
}
Led8_One = Led8_One<<1;
HC595_SCK = 1;
}
for(i = 0; i < 8;i ++)
{
HC595_SCK = 0;
if(0 != (Led8_Two & 0x80)) //0X80 = 0B1000 0000
{
HC595_DATA = 1;
}
else
{
HC595_DATA = 0;
}
Led8_Two = Led8_Two<<1;
HC595_SCK = 1;
}
HC595_RCK = 1;
}
void delay_1ms(int i)
{
int j;
for( ;i>0;i--)
{
for(j = 0;j < 110;j++)
{}
}
}
void main()
{
while(1)
{
if(k<8)
{
for(k = 0;k < 8;k ++)
{
Send_Data(Led8_One_Array[k],Led8_One_Array2[k]);
delay_1ms(500);
}
j=k-1;
}
else{
for(;j < 8;)
{ j -- ;
Send_Data(Led8_One_Array[j],Led8_One_Array2[j]);
delay_1ms(100);
if(j==0)break;
}
if(j==0) k=0;
}
}
}
HC595驱动数码管:
数码管分类:数码管分为共阴极与共阳极两种。
内部原理如下图所示:
硬件设计部分如下:采用共阴极接法。
编码实现:
段编码:
0 1 2 3 4 5 6 7 8 9
0x3f 0x06 0x5b , 0x4f ,0x66 ,0x6d ,0x7d,0x07 0x7f 0x6f
A B C D E F 无显示 P
0x77 0x7c 0x39 0x5e 0x79 0x71 0x00 0x73
位编码:
数码管的工作方式有两种:
静态显示与动态显示方式。
静态显示:每个数码管的段选必须接一个8位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。静态显示成本高,硬件电路复杂。
动态显示方式:将所有数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用使人感觉好像各位数码管同时都在显示。
设计思路:
1.确定位选显示的字符,编码方式。
2.确定要使能哪个段选。
3.送显示。
实现代码如下:
#include<reg52.h>
code unsigned char ShU_Duan_Data[20] = {0x3f,0x06,0x5b ,0x4f ,0x66 ,0x6d ,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x73 };//0-F 无显示 P
code unsigned char ShU_Wei_Data[8] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};//位选择端
sbit HC595_RCK = P1^0;
sbit hc595_SCK = P1^1;
sbit HC595_DATA = P1^4;
void Delay_1MS(unsigned int i)
{
unsigned char j;
for(;i >0;i--)
{
for(j=0;j < 110;j++);
}
}
void Shu_Ma_Data(unsigned char Shu_Data_One,unsigned char Shu_Data_Two)
{
unsigned char i;
HC595_RCK = 0;
for(i=0; i<8;i++)
{
hc595_SCK = 0;
if(0 != (Shu_Data_One & 0x80))
{
HC595_DATA = 1;
}
else
{
HC595_DATA = 0;
}
Shu_Data_One = Shu_Data_One<<1;
hc595_SCK = 1;
}
for(i=0; i<8;i++)
{
hc595_SCK = 0;
if(0 != (Shu_Data_Two & 0x80))
{
HC595_DATA = 1;
}
else
{
HC595_DATA = 0;
}
Shu_Data_Two = Shu_Data_Two << 1;
hc595_SCK = 1;
}
HC595_RCK = 1;
}
//两路数码管分别控制显示
void display1(unsigned int data_s)
{
unsigned char data_u,data_t,data_h,data_th;
data_u=data_s%10;
data_t = data_s/10%10;
data_h = data_s/100%10;
data_th = data_s/1000;
Shu_Ma_Data(ShU_Duan_Data[data_u],ShU_Wei_Data[3]);
Shu_Ma_Data(ShU_Duan_Data[data_t],ShU_Wei_Data[2]);
Shu_Ma_Data(ShU_Duan_Data[data_h],ShU_Wei_Data[1]);
Shu_Ma_Data(ShU_Duan_Data[data_th],ShU_Wei_Data[0]);
}
void display(unsigned int data_s)
{
unsigned char data_u,data_t,data_h,data_th;
data_u=data_s%10;
data_t = data_s/10%10;
data_h = data_s/100%10;
data_th = data_s/1000;
Shu_Ma_Data(ShU_Duan_Data[data_u],ShU_Wei_Data[7]);
Shu_Ma_Data(ShU_Duan_Data[data_t],ShU_Wei_Data[6]);
Shu_Ma_Data(ShU_Duan_Data[data_h],ShU_Wei_Data[5]);
Shu_Ma_Data(ShU_Duan_Data[data_th],ShU_Wei_Data[4]);
}
void display_none(void)
{
Shu_Ma_Data(ShU_Duan_Data[16],ShU_Wei_Data[3]);
Shu_Ma_Data(ShU_Duan_Data[16],ShU_Wei_Data[2]);
Shu_Ma_Data(ShU_Duan_Data[16],ShU_Wei_Data[1]);
Shu_Ma_Data(ShU_Duan_Data[16],ShU_Wei_Data[0]);
Shu_Ma_Data(ShU_Duan_Data[16],ShU_Wei_Data[7]);
Shu_Ma_Data(ShU_Duan_Data[16],ShU_Wei_Data[6]);
Shu_Ma_Data(ShU_Duan_Data[16],ShU_Wei_Data[5]);
Shu_Ma_Data(ShU_Duan_Data[16],ShU_Wei_Data[4]);
}
void main()
{
unsigned int k=100;
display_none(); //清显示。
while(1)
{
display1(k);
display(k+5);
k++;
if(k>9999)
k=0;
Delay_1MS(3);
}
}
``
哈哈哈,就到这吧595可以灵活应用的。以上都已验证