找回密码
 立即注册
楼主: 王昱顺

深圳大学《单片机原理及接口技术》上机实验演示视频@Ai8051U

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2025-4-11 19:49:20 | 显示全部楼层
汇编语言 实验
15.6.1 深大--中断实验1(外部中断INTO/P3.2,INT1/P3.3 控制点灯并 USB 仿真)
h)实验程序汇编语言代码
截图202504111948361005.jpg

截图202504111949179704.jpg

截图202504112000342350.jpg

截图202504112001587546.jpg


;外部中断INT0和INT1控制点灯并USB仿真
$INCLUDE(AI8051U.INC)       ;包含AI8051U的头文件

;------------------------------------------------

    ORG     0000H           ;程序复位地址
    LJMP    RESET           ;跳转到复位地址开始运行程序

    ORG     0003H           ;INT0中断入口地址
    LJMP    INT0_ISR        ;跳转到INT0中断服务程序

    ORG     0013H           ;INT1中断入口地址
    LJMP    INT1_ISR        ;跳转到INT1中断服务程序

;------------------------------------------------

    ORG     0100H

INT0_ISR:                   ;INT0中断服务程序
    JNB     INT0,P32ISLOW   ;边沿中断,进入后再次判断电平从而判断是什么样的电平
P32ISHIGH:
    CLR     P0.0            ;判断为高电平,则当前为上升沿,点亮P00端口上的LED灯
    NOP                     ;可以在这里插入断点进行观察现象
    SETB    P0.0            ;关闭LED灯
    SJMP    INT0_ISR_EXIT   ;跳转到INT0中断程序返回的地方
P32ISLOW:
    CLR     P0.7            ;判断为低电平,则当前为下降沿,点亮P07端口上的LED灯
    NOP                     ;可以在这里插入断点进行观察现象
    SETB    P0.7            ;关闭LED灯
INT0_ISR_EXIT:
    RETI                    ;中断返回

;------------------------------------------------

INT1_ISR:                   ;INT1中断服务程序
    CLR     P0.4            ;点亮P04端口上的LED灯
    NOP                     ;可以在这里插入断点观察现象
    SETB    P0.4            ;关闭LED灯
    RETI                    ;中断返回

;------------------------------------------------

RESET:

    SETB    EAXFR           ;允许访问扩展的特殊寄存器,XFR
    MOV     WTST,#00H       ;设置取程序代码等待时间,赋值为 0 表示不等待,程序以最快速度运行
    MOV     CKCON,#00H      ;设置访问片内的 xdata 速度,赋值为 0 表示用最快速度访问,不增加额外的等待时间

    MOV     P0M0,#38H       ;设置P03、P04为推挽输出,P05为开漏输出,其余为准双向口模式
    MOV     P0M1,#20H
    MOV     P1M0,#00H       ;设置 P1 口为准双向口模式
    MOV     P1M1,#00H
    MOV     P2M0,#00H       ;设置 P2 口为准双向口模式
    MOV     P2M1,#00H
    MOV     P3M0,#00H       ;P32、P33设置为高阻输入(需要同步开启上拉电阻)
    MOV     P3M1,#0CH
    MOV     P4M0,#00H       ;设置 P4 口为准双向口模式
    MOV     P4M1,#00H
    MOV     P5M0,#00H       ;设置 P5 口为准双向口模式
    MOV     P5M1,#00H
    MOV     P6M0,#00H       ;设置 P6 口为准双向口模式
    MOV     P6M1,#00H
    MOV     P7M0,#00H       ;设置 P7 口为准双向口模式
    MOV     P7M1,#00H

    MOV     WR0,#WORD2 P3PU ;P32、P33打开上拉电阻
    MOV     WR2,#WORD0 P3PU
    MOV     A,#0CH
    MOV     @DR0,R11

    CLR     IT0             ;使能 INT0 上升沿和下降沿中断
;   SETB    IT0             ;使能 INT0 下降沿中断
    SETB    EX0             ;使能 INT0 中断

;   CLR     IT1             ;使能 INT1 上升沿和下降沿中断
    SETB    IT1             ;使能 INT1 下降沿中断
    SETB    EX1             ;使能 INT1 中断

    CLR     IE0             ;清INT0中断标志
    CLR     IE1             ;清INT1中断标志

    SETB    EA              ;打开总中断开关
    CLR     P40             ;打开LED灯供电

;------------------------------------------------

MAINLOOP:
    SJMP    MAINLOOP        ;主循环为空循环,所有内容都在中断中

;------------------------------------------------

    END





回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-04-14 15:13:34
已绑定手机

54

主题

53

回帖

1680

积分

管理员

积分
1680
发表于 2025-4-14 15:13:34 | 显示全部楼层
汇编语言 实验
2.18.6 深大-点灯实验4(使能Ai8051U内置 USB直接 仿真流水灯)
实验程序汇编语言代码
截图202504141510566068.jpg
截图202504141511231265.jpg
截图202504141512117613.jpg
截图202504141513051597.jpg

  1. ;以下是控制P6.0~P6.7引脚上一个LED灯循环亮灭跑马灯的汇编语言程序代码。
  2. ;特别注意延时子程序汇编语言写法。试通过每一条指令的所花的机器时钟周期计算一下软件延时时间。
  3. ;251汇编程序
  4. $INCLUDE(AI8051U.INC)
  5. STACK_POIRTER   EQU     0D0H    ;堆栈开始地址
  6.         ORG     0000H
  7.         LJMP    MAIN
  8.         ORG     0100H
  9. MAIN:
  10.         SETB    EAXFR           ;允许访问扩展的特殊寄存器,XFR
  11.         MOV     WTST,#00H       ;设置取程序代码等待时间,赋值为 0 表示不等待,程序以最快速度运行
  12.         MOV     CKCON,#00H      ;设置访问片内的 xdata 速度,赋值为 0 表示用最快速度访问,不增加额外的等待时间
  13.         MOV     SP, #STACK_POIRTER        ;堆栈栈顶设置
  14.         ;端口初始化
  15.         CLR                    A
  16.         MOV                P0M1, A         ;设置P0为准双向口
  17.         MOV                P0M0, A
  18.         MOV                P1M1, A         ;设置P1为准双向口
  19.         MOV                P1M0, A
  20.         MOV                P2M1, A         ;设置P2为准双向口
  21.         MOV                P2M0, A
  22.         MOV                P3M1, A
  23.         MOV                P3M0, A
  24.         MOV                P4M1, A
  25.         MOV                P4M0, A
  26.         MOV                P5M1, A
  27.         MOV                P5M0, A
  28.         MOV                P6M1, A
  29.         MOV                P6M0, A
  30.         MOV                P7M1, A
  31.         MOV                P7M0, A
  32.         MOV                 P0, #0FFH
  33.         ;变量初始化
  34.         CLR                P40                        ;流水灯总开关打开
  35. LOOP:
  36.         MOV                P0,#00H
  37.         ACALL   DELAY500MS        ;调用延时子程序
  38.         MOV                P0,#0FFH
  39.         ACALL   DELAY500MS        ;调用延时子程序
  40.         CLR                P00                  ;给P6^0清零,低电平时led亮
  41.         ACALL   DELAY500MS        ;调用延时子程序
  42.         SETB    P00                        ;给P6^0置1,高电平时led灭
  43.         CLR                P01
  44.         ACALL   DELAY500MS        ;调用延时子程序
  45.         SETB    P01
  46.        
  47.         CLR                P02
  48.         ACALL   DELAY500MS        ;调用延时子程序
  49.         SETB    P02
  50.        
  51.         CLR     P03
  52.         ACALL   DELAY500MS        ;500MS;调用延时子程序
  53.         SETB    P03
  54.        
  55.         CLR     P04
  56.         ACALL   DELAY500MS        ;调用延时子程序
  57.         SETB    P04
  58.        
  59.         CLR     P05
  60.         ACALL   DELAY500MS        ;调用延时子程序
  61.         SETB    P05
  62.        
  63.         CLR     P06
  64.         ACALL   DELAY500MS        ;调用延时子程序
  65.         SETB    P06       
  66.        
  67.         CLR                P07
  68.         ACALL   DELAY500MS
  69.         SETB    P07
  70.        
  71.         SJMP    LOOP                ;无条件跳转至LOOP处
  72. DELAY500MS:                                ;延时0.5S子程序@40.000MHz
  73.         PUSH        DR0                        ;保护现场,将双字寄存器DR0(即R0~R3)推入堆栈保存
  74.         MOV                WR0,#76         ;将WR0赋值76(思考R0=?R1=?)
  75.         MOV                WR2,#19262        ;将WR2赋值19262(思考R2=?R3=?)
  76. NEXT:
  77.         DEC                DR0,#1          ;DR0<-(DR0)-1
  78.         JNE                NEXT                ;(DR0)≠0,则跳至NEXT标号处即继续-1,知道等于0则执行下一条语句
  79.         POP                DR0                        ;恢复现场
  80.         RET                     ;子程序返回
  81.         ;-----------------
  82. END                                                ;汇编程序结束伪指令语句
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2025-4-14 15:33:51 | 显示全部楼层
C51语言如何嵌入汇编



嗯,我现在需要了解如何在C51语言中嵌入汇编代码。这个问题我之前没有接触过,所以得从头开始学。首先,我得回忆一下C51是什么。C51应该是指用于8051系列单片机的C语言编译器,对吧?那嵌入汇编通常是为了优化性能或者直接操作硬件,这在单片机编程中很常见。

那问题来了,如何在C51中嵌入汇编呢?根据我之前学过的其他编程语言,比如在GCC中使用内联汇编,可能C51也有类似的方法。不过不同的编译器可能有不同的语法,所以我得查一下C51的具体实现方式。

首先,我记得在C语言中嵌入汇编通常有两种方法:内联汇编和单独的汇编模块。在C51中,可能也是这两种方式。不过可能具体的语法会有所不同。比如,在Keil C51中,可能会有特定的关键字或者预处理指令来嵌入汇编代码。

然后,我需要考虑如何在函数内部插入汇编指令。比如,是否有类似于__asm关键字,或者需要用#asm和#endasm这样的预处理指令?比如,在Keil的文档中,可能会提到使用#pragma asm和#pragma endasm来包裹汇编代码,但需要设置编译器选项,比如在项目设置中启用SRC选项生成汇编源文件,然后再编译。

另外,嵌入汇编的时候需要注意寄存器的使用,是否会影响C代码的变量。例如,可能需要保存和恢复某些寄存器,或者使用特定的语法将C变量与汇编操作数绑定。例如,使用_ACC_来表示累加器A,或者直接通过变量名来访问。

另外,单独的汇编文件可能更复杂一些,需要将汇编代码写在独立的.asm文件中,然后在C代码中声明这些函数的原型,通过链接器将它们链接在一起。这可能涉及到调用约定、参数传递等问题,比如参数是通过寄存器还是堆栈传递,返回值如何存放等等。

举个例子,如果我想在C51的函数中插入一段汇编代码来操作端口,可能需要这样写:

void my_function() {
#pragma asm
MOV A, #0FFh
MOV P1, A
#pragma endasm
}

但可能需要在编译器选项中启用生成SRC文件,或者在项目设置里允许内联汇编。否则编译器可能会报错。

不过,我之前可能混淆了不同的编译器的语法。比如,有些编译器可能使用__asm { ... }这样的结构,而C51可能使用不同的方式。所以可能需要查阅Keil C51的手册或者相关资料,确认正确的语法。

另外,嵌入汇编时还需要考虑中断处理的问题,如果在中断服务例程中嵌入汇编,可能需要特别处理寄存器的保存,或者使用特定的编译器扩展。

还有,变量的访问,比如如何在汇编代码中使用C中定义的变量。可能需要使用特定的符号或者语法,例如用变量名前加下划线,或者通过DPTR来访问数据存储器中的变量。

比如,在汇编中访问C变量var,可能需要这样:

MOV A, _var

或者,如果var位于特定的存储区域,可能需要使用不同的指令。

总的来说,在C51中嵌入汇编的步骤可能包括:

1. 在C函数中使用特定的预处理指令包裹汇编代码,比如#pragma asm和#pragma endasm。
2. 配置编译器选项,允许生成汇编源文件,并正确编译。
3. 在汇编代码中正确使用寄存器和访问C变量,注意不要破坏C环境。
4. 处理函数调用时的参数传递和返回值。

不过具体的细节可能需要查阅C51的编译器手册,或者寻找相关的示例代码。例如,是否需要为嵌入的汇编代码保存和恢复某些寄存器,或者编译器是否自动处理这些。

另外,可能有一些限制,比如不能在所有的函数中嵌入汇编,或者某些优化选项可能与内联汇编冲突。

现在,我应该总结这些可能的步骤,并且给出一个具体的例子,说明如何在C51中嵌入汇编代码,同时提到需要注意的事项,比如编译器设置、寄存器使用、变量访问等。

比如,可能的步骤是:

1. 在C文件中使用#pragma asm和#pragma endasm包裹汇编代码。
2. 在Keil中,需要将源文件添加到工程,并右键点击该文件,设置Options,勾选Generate Assembler SRC File和Assemble SRC File选项。
3. 在汇编代码中,可以通过_ACC_访问累加器,通过变量名前加下划线访问C变量。
4. 注意寄存器的使用,避免影响C代码的执行。

例如,一个具体的例子:

#include <reg51.h>

void delay() {
#pragma asm
MOV R0, #100
LOOP:
DJNZ R0, LOOP
#pragma endasm
}

然后在项目设置中启用生成SRC文件,并确保编译器能够正确编译。

不过,可能还需要在文件开头包含某些头文件,或者声明寄存器的地址,比如reg51.h定义了P1等端口。

总结的话,嵌入汇编需要特定的编译器指令和项目设置,正确使用寄存器和变量,以及注意不要破坏C环境的状态。


在C51语言中嵌入汇编代码可以通过以下步骤实现,主要用于优化关键代码或直接硬件操作:
方法一:使用预处理指令内联汇编
  • 编写C函数并嵌入汇编代码
    使用#pragma asm和#pragma endasm指令包裹汇编代码:
    [backcolor=rgb(255, 255, 255) !important]c
    复制



    #include <reg51.h>  // 包含寄存器定义void port_control() {    #pragma asm    MOV A, #0FFh    ; 将立即数0xFF加载到累加器A    MOV P1, A       ; 将A的值输出到P1端口    #pragma endasm}

  • 配置编译器选项(Keil环境)
    • 右键点击C文件,选择“Options for File”。
    • 勾选“Generate Assembler SRC File”和“Assemble SRC File”,以允许生成并编译汇编代码。

  • 注意事项
    • 寄存器使用:避免随意修改可能被C代码使用的寄存器(如R0-R7),必要时保存恢复。
    • 变量访问:C变量在汇编中通过名称加下划线访问,如MOV A, _myVar。
    • 中断处理:在中断服务例程中嵌入汇编时,需手动保存受影响寄存器。


方法二:调用独立汇编模块
  • 编写独立汇编文件
    创建.asm文件并定义函数:
    [backcolor=rgb(255, 255, 255) !important]assembly
    复制



    ; delay.asmPUBLIC DELAY  ; 声明函数为公共DELAY SEGMENT CODERSEG DELAY    MOV R2, #100LOOP:    DJNZ R2, LOOP    RET

  • 在C中声明并调用函数
    [backcolor=rgb(255, 255, 255) !important]c
    复制



    extern void DELAY(void);  // 声明外部汇编函数void main() {    DELAY();  // 调用汇编函数}


关键注意事项
  • 参数传递:参数通过寄存器(如R7、R5)传递,返回值在ACC或寄存器中。
  • 内存模型:确保汇编代码与C代码的内存模型(SMALL、COMPACT、LARGE)匹配。
  • 优化冲突:高优化级别可能导致内联汇编错误,建议调试阶段关闭优化。

示例:混合C与汇编实现延时[backcolor=rgb(255, 255, 255) !important]c
复制



#include <reg51.h>void asm_delay(unsigned char count) {    #pragma asm    MOV R0, _count  ; 使用C参数countLOOP:    DJNZ R0, LOOP    #pragma endasm}void main() {    while(1) {        P1 = 0x00;      // C代码控制端口        asm_delay(255); // 调用内联汇编延时        P1 = 0xFF;        asm_delay(255);    }}

常见问题解决
  • 编译错误:未启用SRC生成选项导致#pragma asm不被识别。
  • 变量未定义:汇编中访问C变量时需确保已正确声明且作用域可见。
  • 寄存器冲突:在嵌入代码前后使用PUSH/POP保护关键寄存器(如PSW、ACC)。

通过上述方法,可在C51项目中高效结合C与汇编,兼顾开发效率与性能需求。


















回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2025-4-16 10:36:19 | 显示全部楼层
AiCube-可视化 图形 I/O配置 体验


利用 AiCube@AIapp-ISP V6.95M
智能配置开发工具启动程序框架自动生成器,实现如下的实验:
32位8051单片机入门第一个完整的C语言程序,printf_usb("Hello World !\r\n")

AiCube 实验一:  直接 printf_usb("Hello World !\r\n")
32位8051单片机入门第一个完整的C语言程序

AiCube 实验二:  查询方式,查询到电脑命令后,
                           printf_usb("Hello World !\r\n")或其他

AiCube 实验三:  中断方式单片机USB中断接收服务函数收到命令后,
                           printf_usb("Hello World !\r\n")或其他
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-4-21 14:46:35 | 显示全部楼层
通过IO口控制74HC595驱动8个共阴极数码管

截图202504211445132535.jpg
C语言:
  1. /*---------------------------------------------------------------------*/
  2. /* --- Web: www.STCAI.com ---------------------------------------------*/
  3. /*---------------------------------------------------------------------*/
  4. /*************  功能说明    **************
  5. 本例程基于AI8051U为主控芯片的实验箱进行编写测试.
  6. 使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
  7. edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
  8. 用STC的MCU的IO方式控制74HC595驱动8位数码管。
  9. 显示效果为: 数码时钟.
  10. 使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms.
  11. 下载时, 选择时钟 24MHZ (用户可自行修改频率).
  12. ******************************************/
  13. #include "..\..\comm\AI8051U.h"
  14. #include "stdio.h"
  15. #include "intrins.h"
  16. typedef         unsigned char        u8;
  17. typedef         unsigned int        u16;
  18. typedef         unsigned long        u32;
  19. #define MAIN_Fosc        24000000UL
  20. //==========================================================================
  21. #define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))       //Timer 0 中断频率, 1000次/秒
  22. #define DIS_DOT     0x20
  23. #define DIS_BLACK   0x10
  24. #define DIS_        0x11
  25. /*************  本地常量声明    **************/
  26. u8 code t_display[]={                       //标准字库
  27. //   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  28.     0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
  29. //black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
  30.     0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
  31.     0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
  32. u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
  33. /*************  IO口定义    **************/
  34. sbit    P_HC595_SER   = P3^4;   //pin 14    SER     data input
  35. sbit    P_HC595_RCLK  = P3^5;   //pin 12    RCLk    store (latch) clock
  36. sbit    P_HC595_SRCLK = P3^2;   //pin 11    SRCLK   Shift data clock
  37. /*************  本地变量声明    **************/
  38. u8  LED8[8];        //显示缓冲
  39. u8  display_index;  //显示位索引
  40. bit B_1ms;          //1ms标志
  41. u8  hour,minute,second;
  42. u16 msecond;
  43. /*************  本地函数声明    **************/
  44. /****************  外部函数声明和外部变量声明 *****************/
  45. /********************** 显示时钟函数 ************************/
  46. void DisplayRTC(void)
  47. {
  48.     if(hour >= 10)  LED8[0] = hour / 10;
  49.     else            LED8[0] = DIS_BLACK;
  50.     LED8[1] = hour % 10;
  51.     LED8[2] = DIS_;
  52.     LED8[3] = minute / 10;
  53.     LED8[4] = minute % 10;
  54.     LED8[5] = DIS_;
  55.     LED8[6] = second / 10;
  56.     LED8[7] = second % 10;
  57. }
  58. /********************** RTC演示函数 ************************/
  59. void RTC(void)
  60. {
  61.     if(++second >= 60)
  62.     {
  63.         second = 0;
  64.         if(++minute >= 60)
  65.         {
  66.             minute = 0;
  67.             if(++hour >= 24)    hour = 0;
  68.         }
  69.     }
  70. }
  71. /******************** 主函数 **************************/
  72. void main(void)
  73. {
  74.     u8  i,k;
  75.    
  76.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  77.     EAXFR = 1; //扩展寄存器(XFR)访问使能
  78.     CKCON = 0; //提高访问XRAM速度
  79.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
  80.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
  81.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
  82.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
  83.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
  84.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
  85.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
  86.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  87.     T0x12 = 1;  //Timer0 set as 1T, 16 bits timer auto-reload,
  88.     TH0 = (u8)(Timer0_Reload / 256);
  89.     TL0 = (u8)(Timer0_Reload % 256);
  90.     ET0 = 1;    //Timer0 interrupt enable
  91.     TR0 = 1;    //Tiner0 run
  92.     EA = 1;     //打开总中断
  93.    
  94.     display_index = 0;
  95.     hour   = 11;    //初始化时间值
  96.     minute = 59;
  97.     second = 58;
  98.     RTC();
  99.     DisplayRTC();
  100.    
  101. //  for(i=0; i<8; i++)  LED8[i] = DIS_BLACK;    //上电消隐
  102.     for(i=0; i<8; i++)  LED8[i] = i;    //显示01234567
  103.     k = 0;
  104.     while(1)
  105.     {
  106.         if(B_1ms)   //1ms到
  107.         {
  108.             B_1ms = 0;
  109.             if(++msecond >= 1000)   //1秒到
  110.             {
  111. //                P42 = !P42;
  112.                 msecond = 0;
  113.                 RTC();
  114.                 DisplayRTC();
  115.             }
  116.         }
  117.     }
  118. }
  119. /**************** 向HC595发送一个字节函数 ******************/
  120. void Send_595(u8 dat)
  121. {
  122.     u8  i;
  123.     for(i=0; i<8; i++)
  124.     {
  125.         dat <<= 1;
  126.         P_HC595_SER   = CY;
  127.         P_HC595_SRCLK = 1;
  128.         P_HC595_SRCLK = 0;
  129.     }
  130. }
  131. /********************** 显示扫描函数 ************************/
  132. void DisplayScan(void)
  133. {
  134.     Send_595(t_display[LED8[display_index]]);   //输出段码
  135.     Send_595(~T_COM[display_index]);            //输出位码
  136.     P_HC595_RCLK = 1;
  137.     P_HC595_RCLK = 0;
  138.     if(++display_index >= 8)    display_index = 0;  //8位结束回0
  139. }
  140. /********************** Timer0 1ms中断函数 ************************/
  141. void timer0 (void) interrupt 1
  142. {
  143.     DisplayScan();  //1ms扫描显示一位
  144.     B_1ms = 1;      //1ms标志
  145. }
复制代码


汇编:
  1. ;/*---------------------------------------------------------------------*/
  2. ;/* --- Web: www.STCAI.com ---------------------------------------------*/
  3. ;/*---------------------------------------------------------------------*/
  4. ;*************  功能说明    **************
  5. ;本例程基于AI8051U为主控芯片的实验箱进行编写测试。
  6. ;使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
  7. ;data建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
  8. ;用STC的MCU的IO方式控制74HC595驱动8位数码管。
  9. ;显示效果为: 数码时钟.
  10. ;使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms.
  11. ;下载时, 选择时钟 24MHZ (用户可自行修改频率).
  12. ;******************************************/
  13. $include (../../comm/AI8051U.INC)
  14. ;/****************************** 用户定义宏 ***********************************/
  15. Fosc_KHZ    EQU 24000   ;24000KHZ
  16. STACK_POIRTER   EQU     0D0H    ;堆栈开始地址
  17. Timer0_Reload   EQU     (65536 - Fosc_KHZ)  ; Timer 0 中断频率, 1000次/秒
  18. DIS_DOT         EQU     020H
  19. DIS_BLACK       EQU     010H
  20. DIS_            EQU     011H
  21. ;*******************************************************************
  22. ;*******************************************************************
  23. ;*************  IO口定义    **************/
  24. P_HC595_SER     BIT     P3.4  ;   //pin 14    SER     data input
  25. P_HC595_RCLK    BIT     P3.5  ;   //pin 12    RCLk    store (latch) clock
  26. P_HC595_SRCLK   BIT     P3.2  ;   //pin 11    SRCLK   Shift data clock
  27. ;*************  本地变量声明    **************/
  28. Flag0           DATA    20H
  29. B_1ms           BIT     Flag0.0 ; 1ms标志
  30. LED8            DATA    30H     ; 显示缓冲 30H ~ 37H
  31. display_index   DATA    38H     ; 显示位索引
  32. usrhour         DATA    39H     ;
  33. usrminute       DATA    3AH
  34. usrsecond       DATA    3BH     ;
  35. msecond         DATA    3CH     ; 2 byte
  36. ;*******************************************************************
  37. ;*******************************************************************
  38.         ORG     0000H               ;程序复位入口,编译器自动定义到 0FF0000H 地址
  39.         LJMP    F_Main
  40.         ORG     000BH               ;1  Timer0 interrupt
  41.         LJMP    F_Timer0_Interrupt
  42. ;*******************************************************************
  43. ;*******************************************************************
  44. ;******************** 主程序 **************************/
  45.     ORG     0100H          ;编译器自动定义到 0FF0100H 地址
  46. F_Main:
  47.     MOV     WTST, #00H     ;设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  48.     MOV     CKCON,#00H     ;提高访问XRAM速度
  49.     ORL     P_SW2,#080H    ;使能访问XFR
  50.     MOV     P0M1, #00H     ;设置为准双向口
  51.     MOV     P0M0, #00H
  52.     MOV     P1M1, #00H     ;设置为准双向口
  53.     MOV     P1M0, #00H
  54.     MOV     P2M1, #00H     ;设置为准双向口
  55.     MOV     P2M0, #00H
  56.     MOV     P3M1, #00H     ;设置为准双向口
  57.     MOV     P3M0, #00H
  58.     MOV     P4M1, #00H     ;设置为准双向口
  59.     MOV     P4M0, #00H
  60.     MOV     P5M1, #00H     ;设置为准双向口
  61.     MOV     P5M0, #00H
  62.     MOV     P6M1, #00H     ;设置为准双向口
  63.     MOV     P6M0, #00H
  64.     MOV     P7M1, #00H     ;设置为准双向口
  65.     MOV     P7M0, #00H
  66.     MOV     SP, #STACK_POIRTER
  67.     MOV     PSW, #0
  68.     USING   0       ;选择第0组R0~R7
  69. ;================= 用户初始化程序 ====================================
  70.     MOV     display_index, #0
  71.     MOV     R0, #LED8
  72.     MOV     R2, #8
  73. L_ClearLoop:
  74.     MOV     @R0, #DIS_BLACK     ;上电消隐
  75.     INC     R0
  76.     DJNZ    R2, L_ClearLoop
  77.    
  78.     CLR     TR0
  79.     ORL     AUXR, #(1 SHL 7)    ; Timer0_1T();
  80.     ANL     TMOD, #NOT 04H      ; Timer0_AsTimer();
  81.     ANL     TMOD, #NOT 03H      ; Timer0_16bitAutoReload();
  82.     MOV     TH0, #Timer0_Reload / 256   ;Timer0_Load(Timer0_Reload);
  83.     MOV     TL0, #Timer0_Reload MOD 256
  84.     SETB    ET0         ; Timer0_InterruptEnable();
  85.     SETB    TR0         ; Timer0_Run();
  86.     SETB    EA          ; 打开总中断
  87.    
  88.     MOV     usrhour,   #12 ; 初始化时间值
  89.     MOV     usrminute, #0
  90.     MOV     usrsecond, #0
  91.     LCALL   F_DisplayRTC
  92.    
  93. ;=================== 主循环 ==================================
  94. L_Main_Loop:
  95.     JNB     B_1ms,  L_Main_Loop     ;1ms未到
  96.     CLR     B_1ms
  97.     MOV     WR6, msecond
  98.     INC     WR6, #1         ;msecond + 1
  99.     MOV     msecond, WR6
  100.     CMP     WR6, #1000
  101.     JC      L_Main_Loop     ;if(msecond < 1000), jmp
  102.     MOV     WR6, #0
  103.     MOV     msecond, WR6    ;msecond = 0
  104.     LCALL   F_RTC
  105.     LCALL   F_DisplayRTC
  106.     LJMP    L_Main_Loop
  107. ;========================================================================
  108. ; 函数: F_DisplayRTC
  109. ; 描述: 显示时钟子程序。
  110. ; 参数: none.
  111. ; 返回: none.
  112. ; 版本: VER1.0
  113. ; 日期: 2013-4-1
  114. ; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈
  115. ;========================================================================
  116. F_DisplayRTC:
  117.     PUSH    B       ;B入栈
  118.    
  119.     MOV     A, usrhour
  120.     MOV     B, #10
  121.     DIV     AB
  122.     MOV     LED8, A
  123.     MOV     LED8+1, B
  124.     MOV     LED8+2, #DIS_;
  125.    
  126.     MOV     A, usrminute
  127.     MOV     B, #10
  128.     DIV     AB
  129.     MOV     LED8+3, A;
  130.     MOV     LED8+4, B;
  131.     MOV     LED8+5, #DIS_;
  132.     MOV     A, usrsecond
  133.     MOV     B, #10
  134.     DIV     AB
  135.     MOV     LED8+6, A;
  136.     MOV     LED8+7, B;
  137.    
  138.     POP     B       ;B出栈
  139.     RET
  140. ;========================================================================
  141. ; 函数: F_RTC
  142. ; 描述: RTC演示子程序。
  143. ; 参数: none.
  144. ; 返回: none.
  145. ; 版本: VER1.0
  146. ; 日期: 2013-4-1
  147. ; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈
  148. ;========================================================================
  149. F_RTC:
  150.     INC     usrsecond      ; usrsecond + 1
  151.     MOV     A, usrsecond
  152.     CLR     C
  153.     SUBB    A,#60
  154.     JC      L_QuitRTC   ; usrsecond >= 60?
  155.     MOV     usrsecond, #0;
  156.     INC     usrminute      ; usrminute + 1
  157.     MOV     A, usrminute
  158.     CLR     C
  159.     SUBB    A,#60
  160.     JC      L_QuitRTC   ; usrminute >= 60?
  161.     MOV     usrminute, #0
  162.     INC     usrhour        ; usrhour + 1
  163.     MOV     A, usrhour
  164.     CLR     C
  165.     SUBB    A,#24
  166.     JC      L_QuitRTC   ; usrhour >= 24?
  167.     MOV     usrhour, #0
  168. L_QuitRTC:
  169.     RET
  170. ; *********************** 显示相关程序 ****************************************
  171. T_Display:                      ;标准字库
  172. ;    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  173. DB  03FH,006H,05BH,04FH,066H,06DH,07DH,007H,07FH,06FH,077H,07CH,039H,05EH,079H,071H
  174. ;  black  -    H    J    K    L    N    o    P    U    t    G    Q    r    M    y
  175. DB  000H,040H,076H,01EH,070H,038H,037H,05CH,073H,03EH,078H,03dH,067H,050H,037H,06EH
  176. ;    0.   1.   2.   3.   4.   5.   6.   7.   8.   9.   -1
  177. DB  0BFH,086H,0DBH,0CFH,0E6H,0EDH,0FDH,087H,0FFH,0EFH,046H
  178. T_COM:
  179. DB  001H,002H,004H,008H,010H,020H,040H,080H     ;   位码
  180. ;========================================================================
  181. ; 函数: F_Send_595
  182. ; 描述: 向HC595发送一个字节子程序。
  183. ; 参数: ACC: 要发送的字节数据.
  184. ; 返回: none.
  185. ; 版本: VER1.0
  186. ; 日期: 2024-4-1
  187. ; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈
  188. ;========================================================================
  189. F_Send_595:
  190.     PUSH    02H     ;R2入栈
  191.     MOV     R2, #8
  192. L_Send_595_Loop:
  193.     RLC     A
  194.     MOV     P_HC595_SER,C
  195.     SETB    P_HC595_SRCLK
  196.     CLR     P_HC595_SRCLK
  197.     DJNZ    R2, L_Send_595_Loop
  198.     POP     02H     ;R2出栈
  199.     RET
  200. ;========================================================================
  201. ; 函数: F_DisplayScan
  202. ; 描述: 显示扫描子程序。
  203. ; 参数: none.
  204. ; 返回: none.
  205. ; 版本: VER1.0
  206. ; 日期: 2013-4-1
  207. ; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈
  208. ;========================================================================
  209. F_DisplayScan:
  210.     PUSH    DPH     ;DPH入栈
  211.     PUSH    DPL     ;DPL入栈
  212.     PUSH    00H     ;R0 入栈
  213.    
  214.     MOV     DPTR, #T_Display
  215.     MOV     A, display_index
  216.     ADD     A, #LED8
  217.     MOV     R0, A
  218.     MOV     A, @R0
  219.     MOVC    A, @A+DPTR
  220.     LCALL   F_Send_595      ;输出段码
  221.     MOV     DPTR, #T_COM
  222.     MOV     A, display_index
  223.     MOVC    A, @A+DPTR
  224.     CPL     A
  225.     LCALL   F_Send_595      ;输出位码
  226.    
  227.     SETB    P_HC595_RCLK
  228.     CLR     P_HC595_RCLK    ;   锁存输出数据
  229.     INC     display_index
  230.     MOV     A, display_index
  231.     ANL     A, #0F8H            ; if(display_index >= 8)
  232.     JZ      L_QuitDisplayScan
  233.     MOV     display_index, #0;  ;8位结束回0
  234. L_QuitDisplayScan:
  235.     POP     00H     ;R0 出栈
  236.     POP     DPL     ;DPL出栈
  237.     POP     DPH     ;DPH出栈
  238.     RET
  239. ;*******************************************************************
  240. ;**************** 中断函数 ***************************************************
  241. F_Timer0_Interrupt: ;Timer0 1ms中断函数
  242.     PUSH    PSW     ;PSW入栈
  243.     PUSH    ACC     ;ACC入栈
  244.     LCALL   F_DisplayScan   ; 1ms扫描显示一位
  245.     SETB    B_1ms           ; 1ms标志
  246.     POP     ACC     ;ACC出栈
  247.     POP     PSW     ;PSW出栈
  248.     RETI
  249.    
  250. END
复制代码



03.1-通过IO口控制74HC595驱动8个共阴极数码管.zip

17.09 KB, 下载次数: 1

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-4-21 14:48:33 | 显示全部楼层
通过硬件SPI控制74HC595驱动8个共阴极数码管

截图202504211447473697.jpg
C语言:
  1. /*---------------------------------------------------------------------*/
  2. /* --- Web: www.STCAI.com ---------------------------------------------*/
  3. /*---------------------------------------------------------------------*/
  4. /*************  功能说明    **************
  5. 本例程基于AI8051U为主控芯片的实验箱进行编写测试.
  6. 使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
  7. edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
  8. 用STC的MCU的SPI接口控制74HC595驱动8位数码管。
  9. 显示效果为: 数码时钟.
  10. 使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms.
  11. 下载时, 选择时钟 24MHZ (用户可自行修改频率).
  12. ******************************************/
  13. #include "..\..\comm\AI8051U.h"
  14. #include "stdio.h"
  15. #include "intrins.h"
  16. typedef         unsigned char        u8;
  17. typedef         unsigned int        u16;
  18. typedef         unsigned long        u32;
  19. #define MAIN_Fosc        24000000UL
  20. //==========================================================================
  21. #define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))       //Timer 0 中断频率, 1000次/秒
  22. #define DIS_DOT     0x20
  23. #define DIS_BLACK   0x10
  24. #define DIS_        0x11
  25. /*************  本地常量声明    **************/
  26. u8 code t_display[]={                       //标准字库
  27. //   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  28.     0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
  29. //black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
  30.     0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
  31.     0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
  32. u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
  33. /*************  IO口定义    **************/
  34. sbit P_HC595_SER   = P3^4;   //pin 14    SER     data input
  35. sbit P_HC595_RCLK  = P3^5;   //pin 12    RCLk    store (latch) clock
  36. sbit P_HC595_SRCLK = P3^2;   //pin 11    SRCLK   Shift data clock
  37. /*************  本地变量声明    **************/
  38. u8  LED8[8];        //显示缓冲
  39. u8  display_index;  //显示位索引
  40. bit B_1ms;          //1ms标志
  41. u8  hour,minute,second;
  42. u16 msecond;
  43. /*************  本地函数声明    **************/
  44. void SPI_init(void);
  45. /****************  外部函数声明和外部变量声明 *****************/
  46. /********************** 显示时钟函数 ************************/
  47. void DisplayRTC(void)
  48. {
  49.     if(hour >= 10)  LED8[0] = hour / 10;
  50.     else            LED8[0] = DIS_BLACK;
  51.     LED8[1] = hour % 10;
  52.     LED8[2] = DIS_;
  53.     LED8[3] = minute / 10;
  54.     LED8[4] = minute % 10;
  55.     LED8[5] = DIS_;
  56.     LED8[6] = second / 10;
  57.     LED8[7] = second % 10;
  58. }
  59. /********************** RTC演示函数 ************************/
  60. void RTC(void)
  61. {
  62.     if(++second >= 60)
  63.     {
  64.         second = 0;
  65.         if(++minute >= 60)
  66.         {
  67.             minute = 0;
  68.             if(++hour >= 24)    hour = 0;
  69.         }
  70.     }
  71. }
  72. /******************** 主函数 **************************/
  73. void main(void)
  74. {
  75.     u8  i;
  76.    
  77.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  78.     EAXFR = 1; //扩展寄存器(XFR)访问使能
  79.     CKCON = 0; //提高访问XRAM速度
  80.     P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
  81.     P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
  82.     P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
  83.     P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
  84.     P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
  85.     P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
  86.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
  87.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  88.     SPI_init();
  89.    
  90.     T0x12 = 1;  //Timer0 set as 1T, 16 bits timer auto-reload,
  91.     TH0 = (u8)(Timer0_Reload / 256);
  92.     TL0 = (u8)(Timer0_Reload % 256);
  93.     ET0 = 1;    //Timer0 interrupt enable
  94.     TR0 = 1;    //Tiner0 run
  95.     EA = 1;     //打开总中断
  96.    
  97.     display_index = 0;
  98.     hour   = 11;    //初始化时间值
  99.     minute = 59;
  100.     second = 58;
  101.     RTC();
  102.     DisplayRTC();
  103.    
  104. //  for(i=0; i<8; i++)  LED8[i] = DIS_BLACK;    //上电消隐
  105.     for(i=0; i<8; i++)  LED8[i] = i;    //显示01234567
  106.     while(1)
  107.     {
  108.         if(B_1ms)   //1ms到
  109.         {
  110.             B_1ms = 0;
  111.             if(++msecond >= 1000)   //1秒到
  112.             {
  113. //                P42 = !P42;
  114.                 msecond = 0;
  115.                 RTC();
  116.                 DisplayRTC();
  117.             }
  118.         }
  119.     }
  120. }
  121. /**************** SPI初始化程序 ******************/
  122. void SPI_init(void)
  123. {
  124.     SSIG = 1; //忽略 SS 引脚功能,使用 MSTR 确定器件是主机还是从机
  125.     SPEN = 1; //使能 SPI 功能
  126.     DORD = 0; //先发送/接收数据的高位( MSB)
  127.     MSTR = 1; //设置主机模式
  128.     CPOL = 1; //SCLK 空闲时为高电平,SCLK 的前时钟沿为下降沿,后时钟沿为上升沿
  129.     CPHA = 1; //数据在 SCLK 前时钟沿驱动,后时钟沿采样
  130.     //采用漏极开路+上拉电阻方式驱动,需要调低SPI频率才能正常与Flash通信
  131.     SPCTL = (SPCTL & ~3) | 2;   //SPI 时钟频率选择, 0: 4T, 1: 8T,  2: 16T,  3: 2T
  132.     SPI_S1 = 1;     //00: P1.4 P1.5 P1.6 P1.7, 01: P2.4 P2.5 P2.6 P2.7, 10: P4.0 P4.1 P4.2 P4.3, 11: P3.5 P3.4 P3.3 P3.2
  133.     SPI_S0 = 1;
  134.     HSCLKDIV = 0x01;    //高速时钟1分频,默认2分频
  135.    
  136.     P_HC595_SRCLK = 0;  // set clock to low initial state
  137.     P_HC595_SER = 1;
  138.     SPIF = 1;   //清SPIF标志
  139.     WCOL = 1;   //清WCOL标志
  140. }
  141. /**************** 向HC595发送一个字节函数 ******************/
  142. void Send_595(u8 dat)
  143. {
  144.     P_HC595_RCLK = 0;
  145.     SPDAT = dat;
  146.     while(SPIF == 0) ;
  147.     P_HC595_RCLK = 1;
  148.     SPIF = 1;   //清SPIF标志
  149.     WCOL = 1;   //清WCOL标志
  150. }
  151. /********************** 显示扫描函数 ************************/
  152. void DisplayScan(void)
  153. {
  154.     Send_595(t_display[LED8[display_index]]);   //输出段码
  155.     Send_595(~T_COM[display_index]);            //输出位码
  156.     if(++display_index >= 8)    display_index = 0;  //8位结束回0
  157. }
  158. /********************** Timer0 1ms中断函数 ************************/
  159. void timer0 (void) interrupt 1
  160. {
  161.     DisplayScan();  //1ms扫描显示一位
  162.     B_1ms = 1;      //1ms标志
  163. }
复制代码


汇编:
  1. ;/*---------------------------------------------------------------------*/
  2. ;/* --- Web: www.STCAI.com ---------------------------------------------*/
  3. ;/*---------------------------------------------------------------------*/
  4. ;*************  功能说明    **************
  5. ;本例程基于AI8051U为主控芯片的实验箱进行编写测试。
  6. ;使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
  7. ;data建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
  8. ;用STC的MCU的SPI接口控制74HC595驱动8位数码管。
  9. ;显示效果为: 数码时钟.
  10. ;使用Timer0的16位自动重装来产生1ms节拍,程序运行于这个节拍下, 用户修改MCU主时钟频率时,自动定时于1ms.
  11. ;下载时, 选择时钟 24MHZ (用户可自行修改频率).
  12. ;******************************************/
  13. $include (../../comm/AI8051U.INC)
  14. ;/****************************** 用户定义宏 ***********************************/
  15. Fosc_KHZ    EQU 24000   ;24000KHZ
  16. STACK_POIRTER   EQU     0D0H    ;堆栈开始地址
  17. Timer0_Reload   EQU     (65536 - Fosc_KHZ)  ; Timer 0 中断频率, 1000次/秒
  18. DIS_DOT         EQU     020H
  19. DIS_BLACK       EQU     010H
  20. DIS_            EQU     011H
  21. ;*******************************************************************
  22. ;*******************************************************************
  23. ;*************  IO口定义    **************/
  24. P_HC595_SER     BIT     P3.4  ;   //pin 14    SER     data input
  25. P_HC595_RCLK    BIT     P3.5  ;   //pin 12    RCLk    store (latch) clock
  26. P_HC595_SRCLK   BIT     P3.2  ;   //pin 11    SRCLK   Shift data clock
  27. ;*************  本地变量声明    **************/
  28. Flag0           DATA    20H
  29. B_1ms           BIT     Flag0.0 ; 1ms标志
  30. LED8            DATA    30H     ; 显示缓冲 30H ~ 37H
  31. display_index   DATA    38H     ; 显示位索引
  32. usrhour         DATA    39H     ;
  33. usrminute       DATA    3AH
  34. usrsecond       DATA    3BH     ;
  35. msecond         DATA    3CH     ; 2 byte
  36. ;*******************************************************************
  37. ;*******************************************************************
  38.         ORG     0000H               ;程序复位入口,编译器自动定义到 0FF0000H 地址
  39.         LJMP    F_Main
  40.         ORG     000BH               ;1  Timer0 interrupt
  41.         LJMP    F_Timer0_Interrupt
  42. ;*******************************************************************
  43. ;*******************************************************************
  44. ;******************** 主程序 **************************/
  45.     ORG     0100H          ;编译器自动定义到 0FF0100H 地址
  46. F_Main:
  47.     MOV     WTST, #00H     ;设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  48.     MOV     CKCON,#00H     ;提高访问XRAM速度
  49.     ORL     P_SW2,#080H    ;使能访问XFR
  50.     MOV     P0M1, #00H     ;设置为准双向口
  51.     MOV     P0M0, #00H
  52.     MOV     P1M1, #00H     ;设置为准双向口
  53.     MOV     P1M0, #00H
  54.     MOV     P2M1, #00H     ;设置为准双向口
  55.     MOV     P2M0, #00H
  56.     MOV     P3M1, #00H     ;设置为准双向口
  57.     MOV     P3M0, #00H
  58.     MOV     P4M1, #00H     ;设置为准双向口
  59.     MOV     P4M0, #00H
  60.     MOV     P5M1, #00H     ;设置为准双向口
  61.     MOV     P5M0, #00H
  62.     MOV     P6M1, #00H     ;设置为准双向口
  63.     MOV     P6M0, #00H
  64.     MOV     P7M1, #00H     ;设置为准双向口
  65.     MOV     P7M0, #00H
  66.     MOV     SP, #STACK_POIRTER
  67.     MOV     PSW, #0
  68.     USING   0       ;选择第0组R0~R7
  69. ;================= 用户初始化程序 ====================================
  70.     MOV     display_index, #0
  71.     MOV     R0, #LED8
  72.     MOV     R2, #8
  73. L_ClearLoop:
  74.     MOV     @R0, #DIS_BLACK     ;上电消隐
  75.     INC     R0
  76.     DJNZ    R2, L_ClearLoop
  77.    
  78.     MOV     SPCTL,#0DEH
  79.     ORL     P_SW1, #(3 SHL 2)   ; 0: P1.4 P1.5 P1.6 P1.7, 1: P2.4 P2.5 P2.6 P2.7, 2: P4.0 P4.1 P4.2 P4.3, 3: P3.5 P3.4 P3.3 P3.2
  80.     MOV     SPSTAT,#0C0H        ; Clear SPIF,WCOL
  81.    
  82.     CLR     TR0
  83.     ORL     AUXR, #(1 SHL 7)    ; Timer0_1T();
  84.     ANL     TMOD, #NOT 04H      ; Timer0_AsTimer();
  85.     ANL     TMOD, #NOT 03H      ; Timer0_16bitAutoReload();
  86.     MOV     TH0, #Timer0_Reload / 256   ;Timer0_Load(Timer0_Reload);
  87.     MOV     TL0, #Timer0_Reload MOD 256
  88.     SETB    ET0         ; Timer0_InterruptEnable();
  89.     SETB    TR0         ; Timer0_Run();
  90.     SETB    EA          ; 打开总中断
  91.    
  92.     MOV     usrhour,   #12 ; 初始化时间值
  93.     MOV     usrminute, #0
  94.     MOV     usrsecond, #0
  95.     LCALL   F_DisplayRTC
  96.    
  97. ;=================== 主循环 ==================================
  98. L_Main_Loop:
  99.     JNB     B_1ms,  L_Main_Loop     ;1ms未到
  100.     CLR     B_1ms
  101.     MOV     WR6, msecond
  102.     INC     WR6, #1         ;msecond + 1
  103.     MOV     msecond, WR6
  104.     CMP     WR6, #1000
  105.     JC      L_Main_Loop     ;if(msecond < 1000), jmp
  106.     MOV     WR6, #0
  107.     MOV     msecond, WR6    ;msecond = 0
  108.     LCALL   F_RTC
  109.     LCALL   F_DisplayRTC
  110.     LJMP    L_Main_Loop
  111. ;========================================================================
  112. ; 函数: F_DisplayRTC
  113. ; 描述: 显示时钟子程序。
  114. ; 参数: none.
  115. ; 返回: none.
  116. ; 版本: VER1.0
  117. ; 日期: 2013-4-1
  118. ; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈
  119. ;========================================================================
  120. F_DisplayRTC:
  121.     PUSH    B       ;B入栈
  122.    
  123.     MOV     A, usrhour
  124.     MOV     B, #10
  125.     DIV     AB
  126.     MOV     LED8, A
  127.     MOV     LED8+1, B
  128.     MOV     LED8+2, #DIS_;
  129.    
  130.     MOV     A, usrminute
  131.     MOV     B, #10
  132.     DIV     AB
  133.     MOV     LED8+3, A;
  134.     MOV     LED8+4, B;
  135.     MOV     LED8+5, #DIS_;
  136.     MOV     A, usrsecond
  137.     MOV     B, #10
  138.     DIV     AB
  139.     MOV     LED8+6, A;
  140.     MOV     LED8+7, B;
  141.    
  142.     POP     B       ;B出栈
  143.     RET
  144. ;========================================================================
  145. ; 函数: F_RTC
  146. ; 描述: RTC演示子程序。
  147. ; 参数: none.
  148. ; 返回: none.
  149. ; 版本: VER1.0
  150. ; 日期: 2013-4-1
  151. ; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈
  152. ;========================================================================
  153. F_RTC:
  154.     INC     usrsecond      ; usrsecond + 1
  155.     MOV     A, usrsecond
  156.     CLR     C
  157.     SUBB    A,#60
  158.     JC      L_QuitRTC   ; usrsecond >= 60?
  159.     MOV     usrsecond, #0;
  160.     INC     usrminute      ; usrminute + 1
  161.     MOV     A, usrminute
  162.     CLR     C
  163.     SUBB    A,#60
  164.     JC      L_QuitRTC   ; usrminute >= 60?
  165.     MOV     usrminute, #0
  166.     INC     usrhour        ; usrhour + 1
  167.     MOV     A, usrhour
  168.     CLR     C
  169.     SUBB    A,#24
  170.     JC      L_QuitRTC   ; usrhour >= 24?
  171.     MOV     usrhour, #0
  172. L_QuitRTC:
  173.     RET
  174. ; *********************** 显示相关程序 ****************************************
  175. T_Display:                      ;标准字库
  176. ;    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  177. DB  03FH,006H,05BH,04FH,066H,06DH,07DH,007H,07FH,06FH,077H,07CH,039H,05EH,079H,071H
  178. ;  black  -    H    J    K    L    N    o    P    U    t    G    Q    r    M    y
  179. DB  000H,040H,076H,01EH,070H,038H,037H,05CH,073H,03EH,078H,03dH,067H,050H,037H,06EH
  180. ;    0.   1.   2.   3.   4.   5.   6.   7.   8.   9.   -1
  181. DB  0BFH,086H,0DBH,0CFH,0E6H,0EDH,0FDH,087H,0FFH,0EFH,046H
  182. T_COM:
  183. DB  001H,002H,004H,008H,010H,020H,040H,080H     ;   位码
  184. ;========================================================================
  185. ; 函数: F_Send_595
  186. ; 描述: 向HC595发送一个字节子程序。
  187. ; 参数: ACC: 要发送的字节数据.
  188. ; 返回: none.
  189. ; 版本: VER1.0
  190. ; 日期: 2024-4-1
  191. ; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈
  192. ;========================================================================
  193. F_Send_595:
  194.     CLR     P_HC595_RCLK
  195.     MOV     SPDAT,A
  196. L_Wait:
  197.     JNB     SPIF, L_Wait
  198.     CLR     SPIF
  199.     CLR     WCOL
  200.     SETB    P_HC595_RCLK
  201.     RET
  202. ;========================================================================
  203. ; 函数: F_DisplayScan
  204. ; 描述: 显示扫描子程序。
  205. ; 参数: none.
  206. ; 返回: none.
  207. ; 版本: VER1.0
  208. ; 日期: 2013-4-1
  209. ; 备注: 除了ACCC和PSW外, 所用到的通用寄存器都入栈
  210. ;========================================================================
  211. F_DisplayScan:
  212.     PUSH    DPH     ;DPH入栈
  213.     PUSH    DPL     ;DPL入栈
  214.     PUSH    00H     ;R0 入栈
  215.    
  216.     MOV     DPTR, #T_Display
  217.     MOV     A, display_index
  218.     ADD     A, #LED8
  219.     MOV     R0, A
  220.     MOV     A, @R0
  221.     MOVC    A, @A+DPTR
  222.     LCALL   F_Send_595      ;输出段码
  223.     MOV     DPTR, #T_COM
  224.     MOV     A, display_index
  225.     MOVC    A, @A+DPTR
  226.     CPL     A
  227.     LCALL   F_Send_595      ;输出位码
  228.    
  229.     INC     display_index
  230.     MOV     A, display_index
  231.     ANL     A, #0F8H            ; if(display_index >= 8)
  232.     JZ      L_QuitDisplayScan
  233.     MOV     display_index, #0;  ;8位结束回0
  234. L_QuitDisplayScan:
  235.     POP     00H     ;R0 出栈
  236.     POP     DPL     ;DPL出栈
  237.     POP     DPH     ;DPH出栈
  238.     RET
  239. ;**************** 中断函数 ***************************************************
  240. F_Timer0_Interrupt: ;Timer0 1ms中断函数
  241.     PUSH    PSW     ;PSW入栈
  242.     PUSH    ACC     ;ACC入栈
  243.     LCALL   F_DisplayScan   ; 1ms扫描显示一位
  244.     SETB    B_1ms           ; 1ms标志
  245.     POP     ACC     ;ACC出栈
  246.     POP     PSW     ;PSW出栈
  247.     RETI
  248.    
  249. ;*******************************************************************
  250.     END
复制代码



03.2-通过硬件SPI控制74HC595驱动8个共阴极数码管.zip

17.67 KB, 下载次数: 3

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-30 14:38:57

25

主题

977

回帖

3599

积分

超级版主

积分
3599
发表于 2025-4-23 12:01:41 | 显示全部楼层
深圳大学 Ai8051U《单片机原理及应用》实验课,大型综合实战:
定时器做RTC,按键(去抖,长按,短按),发声
实验目的:
1、本项目主要是帮助同学们熟悉如何管理 多文件项目
2、熟悉矩阵式按键扫描方法,含去抖动短按长按
3、了解使用74HC595控制 LED数码管
4、普通定时器软件模拟RTC,实现RTC的 控制
5、I/O控制无源蜂鸣器发声,
     按键 Key0 ~ Key7 按下时,发出对应的 Do/Re/Mi/Fa/So/La/Si/Do音符
6、扩展部分:如何实现按键

实验现象:
将本项目的HEX文件下载到Ai8051U的实验箱后
1、在LED数码管上面低6位会动态显示当前的RTC时间
2、按下两行4列的8个矩阵按键
   在LED数码管的最高位会显示当前的按键键码,并会发出对应的声音
   同时会根据不同的按键发出不同按键音
   (特别注意:需要将实验箱上“跳线3:蜂鸣器”的跳线连上,蜂鸣器才会发声)
3、矩阵按键中的按键0,是RTC模式设置键
   上电后RTC为正常工作模式,此时数码管动态显示RTC时间
   按一次按键0,RTC会切换为小时设置模式,此时RTC的小时值会0.5秒闪烁一次
   再按一次按键0,RTC会切换为分钟设置模式,此时RTC的分钟值会0.5秒闪烁一次
   再按一次按键0,RTC会切换为秒钟设置模式,此时RTC的秒钟值会0.5秒闪烁一次
   在按一次按键0,恢复为RTC正常工作模式
4、矩阵按键中的按键4按键5分别是上调键下调键
   只有在RTC的时/分/秒设置模式式,上调键和下调键才有效
5、时钟设置模式时,长按按键4和按键5,可实现快速设置功能

截图202504231206438040.jpg

截图202504231207443315.jpg

截图202504231209596819.jpg

截图202504231208509263.jpg


截图202504231319401171.jpg

Project11-实战数码管 矩阵按键扫描.zip

195.27 KB, 下载次数: 41

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2025-4-23 13:22:45 | 显示全部楼层
截图202504231322414536.jpg


截图202504280900253319.jpg

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-04-23 14:03:23

13

主题

27

回帖

452

积分

中级会员

积分
452
发表于 2025-4-23 14:03:23 | 显示全部楼层
深圳大学的单片机水平这么强吗

点评

深圳大学,代表我们深圳的水平,当然可以  详情 回复 发表于 2025-4-23 19:37
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15609
发表于 2025-4-23 19:37:08 | 显示全部楼层
sbk*** 发表于 2025-4-23 14:03
深圳大学的单片机水平这么强吗

深圳大学,代表我们深圳的水平,当然可以
深圳,全球 科技 中心
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 20:17 , Processed in 0.192544 second(s), 112 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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