找回密码
 立即注册
查看: 555|回复: 14

擎天柱Ai8051U转89C52-DIP40核心板采用模拟时序驱动74HC164

[复制链接]
已绑定手机

13

主题

17

回帖

389

积分

中级会员

积分
389
发表于 2026-7-9 18:27:45 | 显示全部楼层 |阅读模式
    有不少开发者使用串并驱动CMOS集成电路74HC164时,都反映存在鬼影(不该亮的段也略发光),不如改为74HC595,其实使用74HC164驱动数码管时,也可以做到无鬼影,使用AI8051U单片机驱动就可以实现无鬼影,达到很好的显示效果。AI8051U单片机兼容8bit和32bit方式,这里采用32bit方式。

     74HC164是CMOS电路,2V至6V的供电电压范围,而74LS164芯片是TTL电路,适用于4.75V至5.25V的供电电压范围,所以前者更适合3.3V供电系统。如果手头只有一只74HC164,另一只是74LS164也没关系,当采用8位共阴数码管时,段码用74HC164驱动输出较高的高电平,扫描位码用74LS164驱动,也可以获得正常亮度;而驱动8位共阳数码管,两只164的位置对调一下,仍然可以获得正常亮度的显示效果。
  模拟时序控制74HC164,只占用单片机的3个IO口,原理图如下,由于没有AI8051的Proteus仿真件,这里用了AT89C52,注意两只74HC164的引脚与数码管段位的接法。
164.png
源代码:
  1. //模拟时序控制74HC164驱动8位集成数码管显示数字
  2. /*************  功能说明    **************
  3. 本例程基于AI8051U为主控芯片的实验箱进行编写测试.
  4. 使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
  5. edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
  6. 下载时, 选择时钟 24MHZ (用户可自行修改频率).
  7. ******************************************/
  8. #include "AI8051U.h"    //AI8051U-32bit serices  
  9. #include "stdio.h"
  10. #include "intrins.h"
  11. typedef         unsigned char        u8;
  12. typedef         unsigned int        u16;
  13. typedef         unsigned long        u32;
  14. #define MAIN_Fosc        24000000UL
  15. /*************  本地常量声明    **************/
  16. u8  SEG_CODE[] =  //共阳数码管0~9、灭的数字段码 ,正序;硬件数码管的段A~H对应74HC164的Q0~Q7
复制代码
这里奇怪的是Serial_Output((u8)(0x01<<k));           //先送扫描码 ,缺少强制转换会警告,
k取值在0~7间,0x01<<k 结果根本不会超出8位,为何会出现警告,同样的Keil C51则不会出现警告,这可能是Keil C251的一个缺陷吧。
显示视频如下:


  本例还可以改为定时器中断来完成显示,当然也可以采用同步串口来实现相同功能。




4b0d8501c963ab7e13357068291a5a2a.mp4

1.79 MB, 下载次数: 128

回复

使用道具 举报 送花

已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25428
发表于 2026-7-9 19:10:16 | 显示全部楼层
截图202607091909007359.jpg


截图202607091909516813.jpg

74HC595 便宜
回复

使用道具 举报 送花

已绑定手机

13

主题

17

回帖

389

积分

中级会员

积分
389
 楼主| 发表于 2026-7-9 21:09:23 | 显示全部楼层
代码粘贴有误,现补充完整。
//模拟时序控制74HC164驱动8位集成数码管显示数字

/************* 功能说明 **************

本例程基于AI8051U为主控芯片的实验箱进行编写测试.

使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。

edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。


下载时, 选择时钟 24MHZ (用户可自行修改频率).

******************************************/

#include "AI8051U.h" //AI8051U-32bit serices
#include "stdio.h"
#include "intrins.h"

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;

#define MAIN_Fosc 24000000UL


/************* 本地常量声明 **************/
u8 SEG_CODE[] =  //共阳数码管0~9、灭的数字段码 ,正序;硬件数码管的段A~H对应74HC164的Q0~Q7
{ 0xC0,0xF9,0xA4,0xB0,0x99,0x92, 0x82,0xF8,0x80,0x90,0xFF };
//共阳数码管0~9、灭的数字段码 ,逆序;硬件数码管的段A~H对应74HC164的Q7~Q0
//u8 Nixu_SEG_CODE[] =
//{ 0x03,0x9f,0x25,0x0d,0x99,0x49, 0x41,0x1f,0x01,0x09,0xFF };

//定义要显示的两组数据
const u8 tab[2][8]={{1,2,3,4,5,6,7,8}, //为何不能用code修饰
{1,7,10,0,4,10,2,0}};
/************* IO口定义 **************/
sbit HC164_RST = P1^0; //74HC164_Pin9 复位口
sbit HC164_DAT = P1^1; //74HC164_Pin1_2数据口,前一只74HC164的Q7接下一只的数据口
sbit HC164_CLK = P1^2; //74HC164_Pin8 时钟
/************* 本地变量声明 **************/

/************* 本地函数声明 **************/

void delay_ms(u8 ms); // 延时函数
void Serial_Output(u8 d); // 模拟时序向74HC164串行输出1字节数据
/**************** 外部函数声明和外部变量声明 *****************/


/******************** 主函数 **************************/
void main(void)
{
u8 i,j,k;
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度

P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口


while(1) //无限循环
{
for(i=0;i<2;i++) //2组数据
for(j=0;j<100;j++) //1屏重复100次
for(k=0;k<8;k++) //1屏需发送8个字段码和8个扫描码
{
HC164_RST = 0; //两只74HC164复位,输出为0
HC164_RST = 1; //拉高复位脚,允许74HC164输出
Serial_Output((u8)(0x01<<k));           //先送扫描码 ,缺少强制转换会警告
//Serial_Output(Nixu_SEG_CODE[tab[i][k]]); //后送段码
Serial_Output(SEG_CODE[tab[i][k]]); //后送段码
delay_ms(2);
}
}
}

//========================================================================
// 函数: void delay_ms(unsigned char ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
void delay_ms(u8 ms)
{
u16 i;
do{
i = MAIN_Fosc / 6000;
while(--i);
}while(--ms);
}
//-----------------------------------------------------------------
// 模拟时序向74HC164串行输出1字节数据
//-----------------------------------------------------------------
void Serial_Output(u8 d)
{
u8 i;
for(i = 0; i < 8; i++) //1个字节8位
{
HC164_CLK = 0; //时钟置0
d <<= 1; HC164_DAT = CY; //移出一位(高位优先)
HC164_CLK = 1; //时钟置1,上升沿数据移入74HC164
}
}
回复

使用道具 举报 送花

已绑定手机

52

主题

2901

回帖

3033

积分

荣誉版主

积分
3033
发表于 2026-7-9 21:47:36 | 显示全部楼层
无论是74HC164还是74HC595,在扫描时,必然是先关闭一个COM端,刷新了数据再开启下一个COM端,这样就不会有鬼影
只是74HC595的数据可以在扫描切换前先移入暂存器,刷新时再通过单个脉冲锁存到输出寄存器,而74HC164是“直肠子,暂存器就是输出寄存器,仅此而已
睁开眼睛做场梦~~~
回复

使用道具 举报 送花

83

主题

8317

回帖

1万

积分

超级版主

积分
17932
发表于 2026-7-9 22:22:30 | 显示全部楼层
74HC164输出一定是有闪烁的,只不过移位速度比较快,肉眼观察不到明显的鬼影而已。
而74HC595是先锁存在输出的,所以,从硬件及原理上已经杜绝了鬼影。
回复

使用道具 举报 送花

已绑定手机

13

主题

17

回帖

389

积分

中级会员

积分
389
 楼主| 发表于 2026-7-9 22:34:55 | 显示全部楼层
梁*** 发表于 2026-7-9 22:22
74HC164输出一定是有闪烁的,只不过移位速度比较快,肉眼观察不到明显的鬼影而已。
而74HC595是先锁存在输 ...

HC164_RST = 0; //两只74HC164复位,输出为0
HC164_RST = 1; //拉高复位脚,允许74HC164输出
这两句的作用使74HC164无鬼影,用STC89C52下载实验都无鬼影。

点评

复位,仅仅是将输出全部变成0. 由于164是直接移位输出的,比如要输出8位二进制为10000000: 先移出高位bit7=1,这样1-->Q0-->Q7移一位,Q0=1,其余Qn=0; 其次移出bit6=0,这样0-->Q0-->Q7移一位,Q1=1,其余Qn=0;  详情 回复 发表于 2026-7-10 10:41
理论上,使用复位消鬼影是不成立的, 复位脚拉低时输出均为低电平,暂存器也都清零,要改变输出状态必须移位,只要移位必然有鬼影,Proteus仿真毕竟是仿真,和实物运行有一定差距。  详情 回复 发表于 2026-7-9 23:11
回复

使用道具 举报 送花

已绑定手机

52

主题

2901

回帖

3033

积分

荣誉版主

积分
3033
发表于 2026-7-9 23:11:00 | 显示全部楼层
yyq_*** 发表于 2026-7-9 22:34
HC164_RST = 0; //两只74HC164复位,输出为0
HC164_RST = 1; //拉高复位脚,允许74HC164输出
这两句的作 ...

理论上,使用复位消鬼影是不成立的,
复位脚拉低时输出均为低电平,暂存器也都清零,要改变输出状态必须移位,只要移位必然有鬼影,Proteus仿真毕竟是仿真,和实物运行有一定差距。
睁开眼睛做场梦~~~
回复

使用道具 举报 送花

已绑定手机

74

主题

1019

回帖

3775

积分

论坛元老

初出茅庐&无甚本事

积分
3775
发表于 2026-7-10 06:40:06 | 显示全部楼层
晓*** 发表于 2026-7-9 23:11
理论上,使用复位消鬼影是不成立的,
复位脚拉低时输出均为低电平,暂存器也都清零,要改变输出状态必须 ...

仿真可以做部分验证
而往往实物还需要调试调整
偶尔看看玩玩
回复

使用道具 举报 送花

已绑定手机

74

主题

1019

回帖

3775

积分

论坛元老

初出茅庐&无甚本事

积分
3775
发表于 2026-7-10 06:42:54 | 显示全部楼层
晓*** 发表于 2026-7-9 21:47
无论是74HC164还是74HC595,在扫描时,必然是先关闭一个COM端,刷新了数据再开启下一个COM端,这样就不会有 ...

技术问题类比
非常形象而“直观”
让抽象的描述变具体
对于入门的朋友方便了解
偶尔看看玩玩
回复

使用道具 举报 送花

已绑定手机

74

主题

1019

回帖

3775

积分

论坛元老

初出茅庐&无甚本事

积分
3775
发表于 2026-7-10 06:47:51 | 显示全部楼层
梁*** 发表于 2026-7-9 22:22
74HC164输出一定是有闪烁的,只不过移位速度比较快,肉眼观察不到明显的鬼影而已。
而74HC595是先锁存在输 ...

之前没了解
抽丝剥茧分析
几十Hz好像就行

点评

显示跟你刷新速度关系不大,跟你发送的时钟速度有关,速度越高,闪烁时间越短,人眼越不容易觉察。  详情 回复 发表于 2026-7-10 10:32
偶尔看看玩玩
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-7 14:11 , Processed in 0.083089 second(s), 93 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表