孤殇兮 2023-03-24 13:21 采纳率: 93.3%
浏览 183
已结题

51单片机外部中断控制数码管

1.实验任务
编写控制程序,要求:
(1)两个按键L/R,分别连接外部中断0和外部中断1;
(2)数码管初始显示:01234567;
(3)当用户按下L按键时,数码管显示的数据向左移动;
(4)当用户按下R按键时,数码管显示的数据向右移动。
注意事项:按键不松开数据不更新,仍然显示原数据。
2.实验原理
2.1硬件原理与连线图
1.外部中断与独立按键连线图,如图1所示。

图1 独立按键电路原理图
2.数码管连线图,如图2所示。

图2 数码管动态显示电路原理图
【注意】一定要按本图所示的连线编写控制程序。

img

  • 写回答

5条回答 默认 最新

  • OKX安生 2023-03-24 17:38
    关注
    该回答引用于gpt与OKX安生共同编写:
    
    • 该回答引用于gpt与OKX安生共同编写:

    好的,以下是8051单片机控制7段数码管外部中断的具体步骤:

    1.定义和初始化变量
    首先需要定义和初始化一些变量来存储当前显示的值以及左右移位的状态。还需要定义一个查找表来将数字映射到其对应的段模式。

    2.配置外部中断引脚和使能中断
    将L和R按键连接到外部中断0和外部中断1引脚,然后使用P3寄存器将这些引脚配置为输入。设置IE寄存器的相应位以启用中断。

    3.初始化7段数码管
    将每个段的引脚连接到单片机的IO口,并将这些IO口配置为输出。然后可以通过设置每个IO口的状态来显示初始值“01234567”。

    4.实现中断服务程序
    当外部中断触发时,执行中断服务程序。在中断服务程序中,需要首先检测哪个按键被按下。如果是左键,则将当前显示的值向左移动一个数字,并更新显示。如果是右键,则将当前显示的值向右移动一个数字,并更新显示。需要注意去抖动逻辑,避免单次按键触发多次中断。

    5.主程序
    在主程序中,需要无限循环等待中断的发生。同时,在中断服务程序中更新了显示后,需要将更新后的值存储到缓冲区中,以便下一次更新时使用。

    希望这些步骤能够帮助您实现在8051单片机上使用外部中断控制7段数码管的功能。

    • 以下是一个示例代码,可以实现在8051单片机上使用外部中断控制7段数码管左右移位的功能:

    您可以参考一下:

    #include <reg52.h>
    
    #define uchar unsigned char
    #define uint unsigned int
    
    // 数字到段模式的查找表
    uchar code segTable[] = {
        0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
        0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
    };
    
    // 存储当前显示的值、缓冲区和左右移位状态的变量
    uchar curValue = 0, buffer[8] = {0}, leftShift = 0, rightShift = 0;
    
    // 初始化IO口和中断
    void init() {
        P3 = 0xFF; // 将P3设为输入
        IE = 0x85; // 启用INT0和INT1中断
        IT0 = 1; // 设定INT0中断触发方式为下降沿
        IT1 = 1; // 设定INT1中断触发方式为下降沿
    }
    
    // 显示数字
    void display(uchar digit) {
        P1 = segTable[digit]; // 设置IO口状态
        delay(); // 延时一段时间,以便眼睛观察到数码管的变化
    }
    
    // 更新并显示数码管
    void updateDisplay() {
        // 将当前值存储到缓冲区中
        buffer[curValue] = curValue;
        // 如果需要左移,则将缓冲区向左移动一位
        if (leftShift) {
            for (uint i = 1; i < 8; i++) {
                buffer[i - 1] = buffer[i];
            }
            leftShift = 0; // 清除左移标志位
        }
        // 如果需要右移,则将缓冲区向右移动一位
        if (rightShift) {
            for (uint i = 7; i > 0; i--) {
                buffer[i] = buffer[i - 1];
            }
            rightShift = 0; // 清除右移标志位
        }
        // 显示缓冲区中的值
        for (uint i = 0; i < 8; i++) {
            display(buffer[i]);
        }
    }
    
    // 左移函数
    void leftShiftHandler() interrupt 0 {
        leftShift = 1;
    }
    
    // 右移函数
    void rightShiftHandler() interrupt 2 {
        rightShift = 1;
    }
    
    // 延时函数
    void delay() {
        uchar i, j;
        for (i = 255; i > 0; i--)
            for (j = 110; j > 0; j--);
    }
    
    // 主函数
    void main() {
        init(); // 初始化
        while (1) { // 无限循环
            updateDisplay(); // 更新并显示数码管
        }
    }
    

    需要根据您的实际硬件配置和需求进行调整和修改。希望能对您有所帮助!

    展开全部

    评论 编辑记录
  • 极客智能体-在线 2023-03-25 11:09
    关注

    以下答案由GPT-3.5大模型与博主波罗歌共同编写:

    1. 控制程序实现

    这个任务可以使用中断来实现:当L按键按下时触发外部中断0,R按键按下时触发外部中断1。代码中可以使用滚动变量,表示当前数码管显示的数据是哪一位开始的。当触发外部中断0时,滚动变量加1,当触发外部中断1时,滚动变量减1,然后更新数码管的显示。

    下面是这个任务的控制程序代码,通过 Keil C 编写。需要头文件 stm8s.h 和 stm8s_gpio.h,另外还需要初始化 GPIO 和外部中断:

    #include "stm8s.h"已黑化的小白 #include "stm8s_gpio.h"已黑化的小白 
    // 定义数码管的引脚
    #define SEG_A GPIO_PIN_1
    #define SEG_B GPIO_PIN_2
    #define SEG_C GPIO_PIN_3
    #define SEG_D GPIO_PIN_4
    #define SEG_E GPIO_PIN_5
    #define SEG_F GPIO_PIN_6
    #define SEG_G GPIO_PIN_7
    #define SEG_DP GPIO_PIN_0
    
    // 定义数码管的数字数据
    const uint8_t digit[] = {
        SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,         // 0
        SEG_B | SEG_C,                                       // 1
        SEG_A | SEG_B | SEG_G | SEG_E | SEG_D,               // 2
        SEG_A | SEG_B | SEG_C | SEG_D | SEG_G,               // 3
        SEG_B | SEG_C | SEG_F | SEG_G,                       // 4
        SEG_A | SEG_F | SEG_G | SEG_C | SEG_D,               // 5
        SEG_A | SEG_F | SEG_G | SEG_C | SEG_D | SEG_E,       // 6
        SEG_A | SEG_B | SEG_C,                               // 7
        SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // 8
        SEG_A | SEG_B | SEG_C | SEG_F | SEG_G                // 9
    };
    
    // 定义数码管的状态
    uint8_t display[8] = { 2, 1, 0, 3, 4, 5, 6, 7 };
    uint8_t display_pos = 0;
    
    // 外部中断0中断服务程序
    INTERRUPT_HANDLER(EXTI_PORTA_IRQHandler, 2) {
        if (GPIO_ReadInputData(GPIOA) & GPIO_PIN_3) { // 检查按键是否按下
            display_pos++; // 滚动变量加1
            display_pos %= 8;
        }
        // 清除中断标记
        EXTI_ClearITPendingBit(EXTI_IT_Pin3);
    }
    
    // 外部中断1中断服务程序
    INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4) {
        if (GPIO_ReadInputData(GPIOB) & GPIO_PIN_4) { // 检查按键是否按下
            display_pos--; // 滚动变量减1
            display_pos &= 0x7;
        }
        // 清除中断标记
        EXTI_ClearITPendingBit(EXTI_IT_Pin4);
    }
    
    // 数码管显示函数
    void display_digit(uint8_t pos) {
        // 设置数码管的引脚状态
        GPIO_WriteLow(GPIOD, DIGIT_1 | DIGIT_2 | DIGIT_3 | DIGIT_4);
        GPIO_WriteHigh(GPIOD, (1 << pos));
    
        uint8_t value = display[pos];
    
        GPIO_WriteLow(GPIOC, SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP);
        GPIO_WriteHigh(GPIOC, digit[value]);
    }
    
    int main(void) {
        // 初始化GPIO
        GPIO_Init(GPIOD, (DIGIT_1 | DIGIT_2 | DIGIT_3 | DIGIT_4), GPIO_MODE_OUT_PP_LOW_FAST);
        GPIO_Init(GPIOC, (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP), GPIO_MODE_OUT_PP_LOW_FAST);
        GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_FL_IT); // 外部中断0连接PA3
        GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_IN_FL_IT); // 外部中断1连接PB4
        EXTI_SetPinSensitivity(EXTI_PIN_3, EXTI_SENSITIVITY_FALL_ONLY);
        EXTI_SetPinSensitivity(EXTI_PIN_4, EXTI_SENSITIVITY_FALL_ONLY);
    
        enableInterrupts(); // 开启全局中断
    
        while (1) {
            // 数码管显示
            for (uint8_t i = 0; i < 8; i++) {
                display_digit(i);
                for (uint16_t j = 0; j < 1000; j++);
            }
        }
    }
    
    1. 实验原理

    这个任务实现的核心是利用了单片机的外部中断和数码管动态显示原理。

    外部中断可以响应外部信号的变化,并且可以立即将处理器转移到中断服务程序中执行。在这个任务中,外部中断0和中断1的触发信号来自两个按键,分别连接到了单片机的PA3和PB4引脚。当按键按下时,相应的引脚被拉低,触发中断;当按键松开时,相应的引脚被拉高,中断被取消。

    数码管动态显示原理采用了扫描显示技术。一个数码管显示器通常由多个发光二极管(LED)和一个集合极(共阴极或共阳极)组成。在多个数码管显示器中,要显示的那个数码管会通过集合极被选中,其他的数码管会被关闭。每个数码管需要一个数字信号来指示在当前显示框中显示哪个数字。在一次扫描过程中,所有的数码管都被轮流选中,并且它们里面的数字信号相继变化,以便将正确的数字显示到正确的位置。

    在本实验中,使用了一个常见的数码管动态显示方案,它使用了四个共阴极数码管,每个数码管连接了一个GPIO口。在程序中,表示数码管当前显示哪个位置的变量 display_pos 会随着用户按键的操作而改变,最终数码管会显示相应的更新后的数字。
    如果我的回答解决了您的问题,请采纳!

    展开全部

    评论
  • JoseKe 2023-03-26 12:35
    关注
    本实验要求使用51单片机控制外部中断来控制数码管的显示,具体要求如下:
    1. 两个按键L/R,分别连接外部中断0和外部中断1。
    2. 数码管初始显示:01234567。
    3. 当用户按下L按键时,数码管显示的数据向左移动。
    4. 当用户按下R按键时,数码管显示的数据向右移动。
    注意事项:按键不松开数据不更新,仍然显示原数据。
    实验原理:
    1. 硬件原理与连线图
    本实验需要使用外部中断和数码管动态显示电路,具体连线如下:
    (1)外部中断与独立按键连线图,如图1所示。
    (2)数码管连线图,如图2所示。
    注意:一定要按照图中所示的连线编写控制程序。
    2. 软件原理
    本实验需要编写控制程序,实现按键控制数码管的显示。具体步骤如下:
    (1)初始化程序,包括数码管的引脚设置和外部中断的设置。
    (2)设置数码管的初始显示值为01234567。
    (3)编写外部中断0和外部中断1的中断服务程序,分别实现向左移动和向右移动数码管的显示。
    (4)在主程序中循环检测按键状态,如果按键被按下,则触发相应的中断服务程序,更新数码管的显示。
    (5)在程序结束时,关闭外部中断和数码管的引脚。
    总结:
    本实验通过使用51单片机的外部中断和数码管动态显示电路,实现了按键控制数码管的显示。通过编写控制程序,可以实现向左移动和向右移动数码管的显示,具有一定的实用价值。
    评论
  • m0_66713710 2023-03-27 09:25
    关注

    简要回答 提前将数组写好 中断配置好 再中断程序中加个判断判断按键是否松开松开后进入for循环对数组进行移位 输出即可

    评论
  • CSDN-Ada助手 CSDN-AI 官方账号 2023-03-28 07:43
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:

    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论
编辑
预览

报告相同问题?

问题事件

  • 系统已结题 3月31日
  • 创建了问题 3月24日
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部