使用51单片机,2个74HC595和2个共阴数码管实现上电后从00到99显示,间隔1秒。
需要有电路连接图,C语言代码和整体电路的解读
首先你要知道74HC595的引脚功能,确立它的连接方式
DS:14脚,串行数据输入引脚,级联的话接上一级的Q7’。
OE:13脚,输出使能控制脚,它是低电才使能输出,所以接GND
ST_CP:12脚,存储寄存器时钟输入引脚。上升沿时,数据从移位寄存器转存带存储寄存器。
SH_CP:11脚,移位寄存器时钟引脚,上升沿时,移位寄存器中的数据整体后移,并接受新的数据(从DS输入)。
MR:10脚,低电平时,清空移位寄存器中已有的数据,一般不用,接高电平即可。
Q7’:9脚,串行数据输出引脚。当移位寄存器中的数据多于8位时,会把已有的位“挤出去”,就是从这里出去的。用于595的级联,将它接下一个74HC595的DS端。
Q1-Q7:1到7脚,并行输出引脚
————————————————
74HC595功能部分文章参考CSDN博主「牧子川」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_48764574/article/details/118463276
对应的电路图接法如下:
上图中,SDI、LOAD、SCLK分别是单片机的3个控制IO口(可以通过程序控制输出高、低电平即可),对应的是74HC595的数据输入端DS、装载时钟ST_CP、以及移位时钟SH_CP,附上简单的控制代码。
思路是对51单片机而言只用sbit定义3个控制端口即可,在100个循环内,得到0-99的个位、十位的段码数值,通过串行数据输入端DS、移位时钟SH_CP,将要输入的16位段码(个位8位+十位8位)存入两个74HC595的移位存储器,然后通过装载时钟ST_CP上升沿将十六位数据加载显示。
直接上代码:
#include "reg51.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义74HC595控制管脚
sbit SRCLK=P3^6; //移位寄存器时钟输入
sbit RCLK=P3^5; //存储寄存器时钟输入
sbit SER=P3^4; //串行数据输入
//共阴不带小数点0-F段码
u8 LED_table2[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//要传输的16位段码
u16 LED_table;
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ms:ms延时时间
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
/*******************************************************************************
* 函 数 名 : hc595_write_data(u8 dat)
* 函数功能 : 向74HC595写入一个字节的数据
* 输 入 : dat:数据
* 输 出 : 无
*******************************************************************************/
//传一个74HC595数据
void hc595_write_data(u8 dat)
{
u8 i=0;
for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中
{
SER=dat>>7;//优先传输一个字节中的高位
dat<<=1;//将低位移动到高位
SRCLK=0;
delay_10us(1);
SRCLK=1;
delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中
}
RCLK=0;
delay_10us(1);
RCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}
//传两个74HC595数据
void hc595_write_data2(u16 dat)
{
u8 i=0;
for(i=0;i<16;i++)//循环16次即可将两个字节写入寄存器中
{
SER=dat>>15;//优先传输两个字节中的高位
dat<<=1;//将低位移动到高位
SRCLK=0;
delay_10us(1);
SRCLK=1;
delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中
}
RCLK=0;
delay_10us(1);
RCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
u8 i=0;
u8 i1; //i的个位
u8 i2; //i的十位
u8 n=0;
while(1)
{
for(i=0;i<100;i++)//循环8次扫描8行、列
{
//每次循环先得到i的个位、十位段码
i1=i%10;
i2=i/10;
for(n=0;n<16;n++)
{
//先传十位段码,后传个位段码
LED_table=(LED_table2[i2]<<8|LED_table2[i1]); //括号加与不加都行
}
hc595_write_data2(LED_table);
delay_ms(1000); //1s延迟
}
if(i==100) i=0; //回到初值
}
}
以此将2个74HC595和2个共阴数码管实现上电后从00到99显示,间隔1秒。
你可以循环让一个计数器不断+1,同时io控制数码管
这个程序使用了一个 display 函数来输出数码管的数据。该函数接受两个参数,分别是需要显示的两个数字。在函数内部,我们首先输出第二个数码管的数据,然后输出第一个数码管的数据,最后锁存数据。在主函数中,我们使用两个循环来遍历数字 00 到 99,并调用 display 函数输出数据。每次输出后,我们使用 delay 函数延迟 1 秒,以实现显示间隔。
#include <reg51.h>
#define DATA_PIN P2_0
#define LATCH_PIN P2_1
#define CLK_PIN P2_2
unsigned char code LEDChar[] = {
0xC0, // '0'
0xF9, // '1'
0xA4, // '2'
0xB0, // '3'
0x99, // '4'
0x92, // '5'
0x82, // '6'
0xF8, // '7'
0x80, // '8'
0x90, // '9'
};
void delay(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 125; j++);
}
}
void display(unsigned char data1, unsigned char data2) {
unsigned char i;
// 先输出第二个数码管的数据
DATA_PIN = LEDChar[data2 % 10];
CLK_PIN = 0;
CLK_PIN = 1;
DATA_PIN = LEDChar[data2 / 10];
CLK_PIN = 0;
CLK_PIN = 1;
// 输出第一个数码管的数据
DATA_PIN = LEDChar[data1 % 10];
CLK_PIN = 0;
CLK_PIN = 1;
DATA_PIN = LEDChar[data1 / 10];
CLK_PIN = 0;
CLK_PIN = 1;
// 输出完成,锁存数据
LATCH_PIN = 0;
LATCH_PIN = 1;
}
void main() {
unsigned char i, j;
while (1) {
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
display(i, j);
delay(1000);
}
}
}
}
以下提供了一点使用51单片机、2个74HC595和2个共阴数码管实现上电后从00到99显示,间隔1秒的代码:
#include <reg51.h>
sbit latch = P2^0; // 74HC595锁存端口
sbit clock = P2^1; // 74HC595时钟端口
sbit data = P2^2; // 74HC595数据端口
unsigned char code num[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; // 共阴数码管的数字编码表,依次对应0-9
void delay(unsigned int t)
{
unsigned int i, j;
for(i = t; i > 0; i--)
for(j = 110; j > 0; j--); // 微秒级延时函数
}
void send(unsigned char dat)
{
unsigned char i;
for(i = 0; i < 8; i++) {
clock = 0;
data = dat & 0x80; // 取出最高位
dat <<= 1; // 左移一位,处理下一位数据
clock = 1;
}
}
void display(unsigned char num1, unsigned char num2)
{
latch = 0;
send(num[num2]); // 发送第二个数码管的数据
send(num[num1]); // 发送第一个数码管的数据
latch = 1; // 送出数据
}
void main()
{
unsigned char i, j;
for(i = 0; i < 100; i++) {
for(j = 0; j < 50; j++) { // 等待1秒,通过50次延时实现
display(i / 10, i % 10); // 显示当前数字
delay(10); // 延时20微秒,共500次,等待1秒
}
}
}
说明:
代码中使用了三个端口,P2.0作为74HC595锁存端口,P2.1作为74HC595时钟端口,P2.2作为74HC595数据端口,可根据实际连接情况修改。
共阴数码管的数字编码表为 num[],根据具体型号可自行修改。
在主函数中使用两层循环,外层循环100次,内层循环50次,通过20微秒的延时等待实现1秒的效果,实现从00到99的循环显示。
在循环中通过 display() 函数实现显示,传入的两个参数分别为两个数码管要显示的数字。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
下面是题目所需的电路连接图:
; // 延时函数
void hc595_send_byte(unsigned char dat); // 发送字节到74HC595
void main() {
unsigned char i, j;
LATCH_PIN = 1; // 和74HC595通信的IO初始化
CLOCK_PIN = 0;
DATA_PIN = 0;
while (1) {
for (i = 0; i < 10; i++) { // 十位数字
for (j = 0; j < 10; j++) { // 个位数字
hc595_send_byte(LED_TAB[i]); // 发送十位数字到74HC595
hc595_send_byte(LED_TAB[j]); // 发送个位数字到74HC595
LATCH_PIN = 0; // 上升沿锁存数据
LATCH_PIN = 1;
delay_ms(1000); // 间隔1秒
}
}
}
}
void delay_ms(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 114; j++); // 1毫秒的延时
}
}
void hc595_send_byte(unsigned char dat) {
unsigned char i;
for (i = 0; i < 8; i++) {
CLOCK_PIN = 0;
DATA_PIN = dat & 0x80
注释说明:
定义LED_PORT为P0口,用于控制数码管的LED灯;
定义LATCH_PIN为P2.5口,用于控制74HC595的锁存信号;
定义CLOCK_PIN为P2.3口,用于控制74HC595的时钟信号;
定义DATA_PIN为P2.4口,用于控制74HC595的数据信号;
定义LED_TAB数组,用于存储数字0~9的LED显示数据;
delay_ms函数用于实现毫秒级延时;
hc595_send_byte函数用于将一个字节发送到74HC595中;
在主程序中,使用两个for循环分别控制十位数字和个位数字,将它们分别发送到74HC595中,然后通过锁存信号将数据写入寄存器,最后延时1秒钟,实现数字的循环显示。
此程序需要使用Keil C编译器进行编译。同时,还需要连接上2个74HC595和2个共阴数码管等硬件设备,通过对应的引脚连接进行电路的搭建。
参考GPT和自己的思路,下面是使用51单片机、2个74HC595和2个共阴数码管实现上电后从00到99显示,间隔1秒的电路连接图和C语言代码:
电路连接图:
其中,P3.4、P3.5和P3.6分别连接到74HC595芯片的SER、RCLK和SRCLK引脚,P1.0~P1.4分别连接到共阴数码管的D1_Segment、D1_Digit、D2_Segment、D2_Digit引脚上,共阴数码管中的两个数码管并联连接到74HC595芯片的输出引脚上。
C语言代码:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit SRCLK = P3^6;
sbit RCLK = P3^5;
sbit SER = P3^4;
uchar code LED_DuanMa[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
void delay_ms(uint x)
{
uint i,j;
for(i=x;i>0;i--)
{
for(j=114;j>0;j--);
}
}
void HC595SendByte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
SRCLK = 0;
SER = dat&0x80;
dat <<= 1;
SRCLK = 1;
}
RCLK = 0;
RCLK = 1;
}
void main()
{
uchar i,j;
while(1)
{
for(i=0;i<10;i++)
{
for(j=0;j<10;j++)
{
HC595SendByte(LED_DuanMa[i]);
HC595SendByte(LED_DuanMa[j]);
delay_ms(1000);
}
}
}
}
代码解读
1.定义了单片机的IO口和需要用到的数据类型。
2.定义了共阴数码管显示0-9的段码。
3.定义了一个延时函数delay_ms,用来实现1秒的延时。
4.HC595SendByte函数用于向74HC595芯片发送一个字节的数据。通过SER和SRCLK分别向74HC595芯片的串行输入和时钟输入发送数据,再通过RCLK向74HC595芯片的存储器时钟输入发送数据。
5.在主函数中,用两个循环嵌套来实现00-99的显示。每次循环中,先向第一个数码管发送十位数的段码,然后向第二个数码管发送个位数的段码,完成一次数字的显示。然后延时1秒钟,进入下一个循环。
【C语言代码】
```c
#include<reg52.h>
//*************************************
#define uint unsigned int
#define uchar unsigned char
//**************************************
sbit WREN=P3^5; //写使能
sbit WR=P3^6; //写
sbit CE=P3^7; //片选使能
uchar code data_char[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, //数码管0~9的显示段码
0x7F,0x67,0x77,0x7C,0x39,0x5E,
0x79,0x71};
//**************************************
void delayms(uint);
void write_data(uchar);
//***************************************
void main()
{
CE=1;
WREN=0;
WR=1;
while(1)
{
for(int i=0;i<100;i++) //i为计数器,值从0~99进行变换之后刷新到LED上。
{
for(int j=0;j<8;j++) //j为控制位选和段选的一个变量,值从0-1之间变换。
{
if(j==0)
{
write_data(i%10); //将i的个位数存入移位寄存器中
CE=0;
CE=1;
}
else
{
write_data((i/10)%10); //将i的十位数存入移位寄存器中
CE=0;
CE=1;
}
P2=0xff; //将P2口的值赋为1ffff,则对应的数码管就会亮
P0=data_char[i%10]; //data_char[]数组定义了相应的该值所对应的数字
delayms(1); //延时1ms,以保证能看到动态效果。
P2=0x00; //每关闭一位数码管,这里将P2口的值设置为0,则数码管关闭
delayms(1);
}
}
}
}
void delayms(uint x) //延迟x毫秒
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
void write_data(uchar dat)
{
uchar mask; //使用位操作的方法,逐次给595写入数据。
mask=0x80; //mask初始值为0x80,即二进制下最左边为1,其余为0。
for(int i=0;i<8;i++) //对应8位二进制的数据调用for循环,进行2进制位操作
{
WR=1;
if(dat&mask)
P2=1;
else
P2=0;
mask=mask>>1; //每次右移一位,以便将整个数据都传入输出引脚
WR=0;
WR=1;
}
}
```
【整体电路的解读】
该电路分为两部分:主控板电路和数码管驱动电路。其中,主控板采用单片机AT89C51进行控制,通过 #include<reg52.h> 引入头文件实现对寄存器的操作。数码管驱动电路采用74HC595芯片进行驱动,将P0口和P2口分别接到8位串行输入、并行输出的移位存储寄存器。其中,P2口用来控制位选,P0口用来控制段选,通过不同的二进制代码,对应不同的数码管显示。同时,由于采用的是共阴连接方式的数码管,需要在控制端将高电平控制为低电平有效,即置0。
该程序中的delayms()函数用于进行时间延时,以实现数码管动态显示效果。delayms()函数具有两个参数,第一个参数为要延迟的时间(毫秒),第二个参数为控制时间精度的变量。在本程序中,固定为110,以保证在单片机频率为11.0592MHz的情况下,延时1毫秒。
在主程序中使用了两层for循环,第一层对应099的所有数字,第二层对应位选和段选。具体来说,由于74HC595芯片的存储字节为8位,因此在位选和段选中均需要将需要显示的数字拆分成两个数位,分别存入寄存器中。其中,i为计数器,值从099进行变换之后刷新到LED上。j为控制位选和段选的一个变量,值从0-1之间变换。
最终实现的效果是,数码管上的数值从00开始,以1的速度持续地增加,直至99后又从00开始,不断循环显示。
不知道你这个问题是否已经解决, 如果还没有解决的话:你需要实现的就是一个串入并处的功能,间隔1秒更新一组数字实现显示数字的变化,循环往复即可