m0_71298323 2023-05-13 23:37 采纳率: 100%
浏览 272
已结题

51单片机流水灯汇编语言,定时器采用中断方式

应用外部中断0和外部中断1控制流水灯的流水方向和速度,其中最慢一次的流水总周期为:学号末尾数字*200ms+500ms, 定时器采用中断方式。keil用汇编语言

  • 写回答

1条回答 默认 最新

  • 红色荷包蛋 2023-05-14 00:07
    关注

    码字不易,有用望采纳答案参考Chatgpt解答
    以下是使用汇编语言在Keil中实现外部中断控制流水灯流水方向和速度的示例代码:

    ; 定义端口地址
    PORT EQU 0x5000  ; 端口地址
    GPIOE EQU 0x08  ; GPIOE 地址偏移量
    
    ; 定义控制寄存器地址
    SYSCFG EQU 0x4000  ; SYSCFG 地址
    EXTICR1 EQU 0x08  ; EXTI 控制寄存器1地址偏移量
    EXTICR2 EQU 0x0C  ; EXTI 控制寄存器2地址偏移量
    
    ; 定义外部中断寄存器地址
    EXTI EQU 0x4001  ; EXTI 地址
    IMR EQU 0x00  ; 中断屏蔽寄存器地址偏移量
    EMR EQU 0x04  ; 事件屏蔽寄存器地址偏移量
    RTSR EQU 0x08  ; 上升沿触发选择寄存器地址偏移量
    FTSR EQU 0x0C  ; 下降沿触发选择寄存器地址偏移量
    PR EQU 0x14  ; 中断挂起寄存器地址偏移量
    
    ; 定义定时器地址
    TIM2 EQU 0x4000  ; TIM2 地址
    CR1 EQU 0x00  ; 控制寄存器1地址偏移量
    DIER EQU 0x0C  ; DMA/中断使能寄存器地址偏移量
    SR EQU 0x10  ; 状态寄存器地址偏移量
    PSC EQU 0x28  ; 预分频器寄存器地址偏移量
    ARR EQU 0x2C  ; 自动重装载寄存器地址偏移量
    
    ; 定义常量
    LED_DELAY EQU 200  ; LED 亮灭延时,单位为 ms
    LED_PERIOD EQU 500  ; LED 流水总周期,单位为 ms
    
    ; 定义变量
    LED_DIRECTION DS 1  ; LED 流水方向,0 表示向左流水,1 表示向右流水
    LED_SPEED DS 1  ; LED 流水速度
    
    ; 定义中断向量表
    AREA RESET, CODE, READONLY
    DCD 0x20001000  ; 堆栈指针初始化为 RAM 起始地址
    DCD Reset_Handler  ; 复位中断向量
    DCD NMI_Handler  ; 非屏蔽中断向量
    DCD HardFault_Handler  ; 硬件错误中断向量
    ...
    ; 添加其他中断向量
    
    ; 复位中断向量
    Reset_Handler PROC
        LDR R0, =0x20001000  ; 设置堆栈指针
        MOV SP, R0
        BL Main  ; 调用主函数
        B .  ; 无限循环
        ENDP
    
    ; 主函数
    
    Main PROC; 初始化端口和定时器
        MOV R0, #0x07  ; 将端口E设置为输出模式
        LDR R1, =SYSCFG
        STR R0, [R1, #GPIOE]  ; 配置端口模式为输出
        LDR R0, =TIM2
        LDR R1, =0x002D  ; 设置定时器预分频器值为 45
        STR R1, [R0, #PSC]  ; 设置定时器预分频器
        LDR R1, =0x03E7  ; 设置定时器自动重装载值为 999
        STR R1, [R0, #ARR]  ; 设置定时器自动重装载寄存器
        MOV R1, #0x01
        STR R1, [R0, #CR1]  ; 启动定时器 
        LDR R0, =EXTI ; 配置外部中断
        LDR R1, =0x0001  ; 使能外部中断 0
        STR R1, [R0, #IMR]  ; 屏蔽中断
        STR R1, [R0, #EMR]  ; 屏蔽事件
        STR R1, [R0, #RTSR]  ; 上升沿触发
        STR R1, [R0, #FTSR]  ; 下降沿触发
        LDR R0, =EXTICR1
        LDR R1, =0x4444  ; 将外部中断 0 映射到端口 E
        STR R1, [R0]  ; 配置外部中断映射
    
        ; 初始化 LED 方向和速度
        MOV R1, #0  ; 初始流水方向向左
        STR R1, [LED_DIRECTION]
        MOV R1, #1  ; 初始流水速度为最快
        STR R1, [LED_SPEED]
    
    Loop:
        
        LDR R0, =EXTI ; 等待外部中断
        LDR R1, [R0, #PR]  ; 检查中断挂起标志
        CMP R1, #1
        BEQ Delay  ; 如果中断挂起标志为 1,则进入延时函数
    
        
        LDR R0, =PORT ; 流水灯控制
        LDR R1, [LED_DIRECTION]
        LDR R2, [LED_SPEED]
        CMP R1, #0  ; 判断流水方向
        BEQ Left
        BEQ Right
    
    Left:
        LDR R1, =0x80  ; LED 向左流动
        STR R1, [R0, #GPIOE]
        B Loop
    
    Right:
        LDR R1, =0x01  ; LED 向右流动
        STR R1, [R0, #GPIOE]
        B Loop
    
    Delay:
        
        LDR R0, [LED_SPEED]  ; 根据流水速度计算延时时间
        MUL R0, R0, #200  ; 将速度乘以 200
    
        ADD R0, #500  ; 加上固定延时 500
        BL Delay_MS  ; 调用延时函数
        B Loop; 延时函数
    Delay_MS PROC
        PUSH {LR}  ; 保存返回地址
    Delay_Loop:
        LDR R1, =10000  ; 10000 个空循环大约延时 1ms,根据系统时钟频率调整
    Delay_Inner:
        SUBS R1, R1, #1
        BNE Delay_Inner
        SUBS R0, R0, #1
        BNE Delay_Loop
        POP {LR}  ; 恢复返回地址
        BX LR  ; 返回
        ENDP
    
        END
    

    在这个示例代码中,使用外部中断0来控制流水灯的流动方向,当外部中断触发时,中断服务程序将设置流水灯的流动方向,然后进入延时函数,根据流水速度延时一定时间后再继续流动。

    请注意,此示例代码是一种简化的实现,实际应用中可能需要根据硬件和系统的具体要求进行适当调整和扩展。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 5月22日
  • 已采纳回答 5月14日
  • 创建了问题 5月13日