基于单片机的遥控器设计

news2024/11/16 14:21:19

一、项目介绍

随着科技的不断发展,红外遥控器已经成为我们日常生活中普遍使用的一种电子设备。它能够给我们带来便捷和舒适,减少人工操作的繁琐性。然而,在实际应用中,有时候我们可能需要制作一个自己的红外遥控器,以便于更好地满足个性化需求。这样的需求可能来自于家庭影音设备的控制、智能家居系统的控制,或者其他自动化控制方案等。

本项目的目标是设计一个简单且易于实现的单片机红外遥控器,使用户能够自己定制并控制各种电子设备。通过使用键盘矩阵和红外发射二极管,用户只需按下相应的按键即可发送红外信号,从而实现对电子设备的控制。此外,为了方便用户知道当前按下的键值,我们还添加了数码管显示的功能,使用户可以直观地看到自己所按下按键的值。

通过这个项目,可以学习到单片机的基本原理和应用、键盘矩阵和红外遥控的工作原理、数码管的驱动方式等知识。并且,还可以根据自己的需求进行各种扩展和改进,如增加更多按键、添加更多的电子设备控制功能等。

image-20230707174010048

二、系统设计

2.1 硬件设计

【1】主控芯片

选择STC89C52作为主控芯片,该芯片具有强大的功能和广泛的应用,可以满足本设计的需求。

【2】键盘设计

采用4x4矩阵键盘作为输入设备,通过行列扫描的方式读取用户按键情况。每个键对应一个唯一的键值,模拟电视机遥控板的键值。

【3】红外线发送设计

使用红外线发射二极管,根据NEC协议发送控制码。NEC协议是一种常用的红外遥控协议,它定义了红外信号的帧结构和通信规则。

【4】数码管显示设计

使用4位数码管进行键值数值的显示。将键值转换为对应的数码管段码,通过依次设置4位数码管的段选信号和位选信号,显示对应的键值数值。

2.2 软件设计

【1】 键盘扫描与键值获取

通过设置行和列的IO口状态,循环扫描键盘,当有键被按下时,获取对应的键值。

【2】红外控制码发送

根据NEC协议的要求,生成控制码的高低电平序列,并通过红外发射二极管发送出去。

三、源代码

#include <reg51.h>

// 定义键盘矩阵的行和列
sbit ROW1 = P0^0;
sbit ROW2 = P0^1;
sbit ROW3 = P0^2;
sbit ROW4 = P0^3;
sbit COL1 = P0^4;
sbit COL2 = P0^5;
sbit COL3 = P0^6;
sbit COL4 = P0^7;

// 定义红外发射二极管的IO口
sbit IR_LED = P2^0;

// 定义数码管的IO口
sbit DIGIT1 = P1^0;
sbit DIGIT2 = P1^1;
sbit DIGIT3 = P1^2;
sbit DIGIT4 = P1^3;
sbit SEG_A = P1^4;   // 数码管段A
sbit SEG_B = P1^5;   // 数码管段B
sbit SEG_C = P1^6;   // 数码管段C
sbit SEG_D = P1^7;   // 数码管段D

// 定义按键值对应的控制码
unsigned char keyTable[4][4] = {
    {'1', '2', '3', 'A'},
    {'4', '5', '6', 'B'},
    {'7', '8', '9', 'C'},
    {'*', '0', '#', 'D'}
};

// 函数声明
void delay(unsigned int time);
unsigned char scanKeyboard(void);
void sendIRCode(unsigned char code);
void displayValueOn7Segment(unsigned char value);

void main()
{
    unsigned char keyValue;
    
    while (1)
    {
        // 扫描键盘,获取键值
        keyValue = scanKeyboard();
        
        if (keyValue != '\0')  // 按键按下
        {
            // 发送红外控制码
            sendIRCode(keyValue);
            
            // 数码管显示键值
            displayValueOn7Segment(keyValue);
        }
    }
}

// 延时函数
void delay(unsigned int time)
{
    unsigned int i, j;
    for (i = 0; i < time; i++)
    {
        for (j = 0; j < 1000; j++);
    }
}

// 扫描键盘并获取键值
unsigned char scanKeyboard(void)
{
    unsigned char row, col;
    
    ROW1 = 0; ROW2 = 1; ROW3 = 1; ROW4 = 1;   // 第1行置低,其余行置高
    if (COL1 == 0) { delay(10); while (COL1 == 0); return keyTable[0][0]; }
    if (COL2 == 0) { delay(10); while (COL2 == 0); return keyTable[0][1]; }
    if (COL3 == 0) { delay(10); while (COL3 == 0); return keyTable[0][2]; }
    if (COL4 == 0) { delay(10); while (COL4 == 0); return keyTable[0][3]; }
    
    ROW1 = 1; ROW2 = 0; ROW3 = 1; ROW4 = 1;   // 第2行置低,其余行置高
    if (COL1 == 0) { delay(10); while (COL1 == 0); return keyTable[1][0]; }
    if (COL2 == 0) { delay(10); while (COL2 == 0); return keyTable[1][1]; }
    if (COL3 == 0) { delay(10); while (COL3 == 0); return keyTable[1][2]; }
    if (COL4 == 0) { delay(10); while (COL4 == 0); return keyTable[1][3]; }
    
    ROW1 = 1; ROW2 = 1; ROW3 = 0; ROW4 = 1;   // 第3行置低,其余行置高
    if (COL1 == 0) { delay(10); while (COL1 == 0); return keyTable[2][0]; }
    if (COL2 == 0) { delay(10); while (COL2 == 0); return keyTable[2][1]; }
    if (COL3 == 0) { delay(10); while (COL3 == 0); return keyTable[2][2]; }
    if (COL4 == 0) { delay(10); while (COL4 == 0); return keyTable[2][3]; }
    
    ROW1 = 1; ROW2 = 1; ROW3 = 1; ROW4 = 0;   // 第4行置低,其余行置高
    if (COL1 == 0) { delay(10); while (COL1 == 0); return keyTable[3][0]; }
    if (COL2 == 0) { delay(10); while (COL2 == 0); return keyTable[3][1]; }
    if (COL3 == 0) { delay(10); while (COL3 == 0); return keyTable[3][2]; }
    if (COL4 == 0) { delay(10); while (COL4 == 0); return keyTable[3][3]; }
    
    return '\0';   // 未按键返回空字符
}


// 发送红外控制码
void sendIRCode(unsigned char code)
{
    // 根据NEC协议生成红外控制码的高低电平序列
    // 将红外控制码通过红外发射二极管发送出去

    unsigned int i;
    unsigned int startHighTime = 9000;   // 红外协议起始高电平时间(μs)
    unsigned int startLowTime = 4500;    // 红外协议起始低电平时间(μs)
    unsigned int bitHighTime = 560;      // 红外协议数据位高电平时间(μs)
    unsigned int bit0LowTime = 560;      // 红外协议数据位0低电平时间(μs)
    unsigned int bit1LowTime = 1690;     // 红外协议数据位1低电平时间(μs)

    // 发送起始高电平
    IR_LED = 1;
    delayMicroseconds(startHighTime);

    // 发送起始低电平
    IR_LED = 0;
    delayMicroseconds(startLowTime);

    // 逐位发送数据位
    for (i = 0; i < 8; i++)
    {
        if (code & 0x01)  // 当前位为1
        {
            IR_LED = 1;
            delayMicroseconds(bitHighTime);

            IR_LED = 0;
            delayMicroseconds(bit1LowTime);
        }
        else  // 当前位为0
        {
            IR_LED = 1;
            delayMicroseconds(bitHighTime);

            IR_LED = 0;
            delayMicroseconds(bit0LowTime);
        }

        code >>= 1;  // 移位获取下一位
    }
}

// 数码管显示键值
void displayValueOn7Segment(unsigned char value)
{
    unsigned char digitCode[10] =
    {
        0x3F,   // 显示数字0
        0x06,   // 显示数字1
        0x5B,   // 显示数字2
        0x4F,   // 显示数字3
        0x66,   // 显示数字4
        0x6D,   // 显示数字5
        0x7D,   // 显示数字6
        0x07,   // 显示数字7
        0x7F,   // 显示数字8
        0x6F    // 显示数字9
    };

    unsigned char digit1, digit2, digit3, digit4;

    digit1 = digitCode[value / 1000];
    digit2 = (digitCode[value / 100]) & 0x7F; // 去掉小数点
    digit3 = (digitCode[value / 10]) & 0x7F;  // 去掉小数点
    digit4 = (digitCode[value % 10]);

    // 设置位选并显示数码管的段码
    DIGIT1 = 0; DIGIT2 = 1; DIGIT3 = 1; DIGIT4 = 1;
    P1 = digit1;

    delay(5);  // 延时一段时间,使数码管显示较稳定

    DIGIT1 = 1; DIGIT2 = 0; DIGIT3 = 1; DIGIT4 = 1;
    P1 = digit2;

    delay(5);

    DIGIT1 = 1; DIGIT2 = 1; DIGIT3 = 0; DIGIT4 = 1;
    P1 = digit3;

    delay(5);

    DIGIT1 = 1; DIGIT2 = 1; DIGIT3 = 1; DIGIT4 = 0;
    P1 = digit4;

    delay(5);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/957165.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云原生进阶之PaaS中间件】第一章Redis-2.4缓存更新机制

1 缓存和数据库的数据一致性分析 1.1 Redis 中如何保证缓存和数据库双写时的数据一致性&#xff1f; 无论先操作db还是cache&#xff0c;都会有各自的问题&#xff0c;根本原因是cache和db的更新不是一个原子操作&#xff0c;因此总会有不一致的问题。想要彻底解决这种问题必须…

目标检测YOLO算法,先从yolov1开始

学习资源 有一套配套的学习资料&#xff0c;才能让我们的学习事半功倍。 yolov1论文原址&#xff1a;You Only Look Once: Unified, Real-Time Object Detection 代码地址&#xff1a;darknet: Convolutional Neural Networks (github.com) 深度学习经典检测方法 one-stag…

React 18 对 state 进行保留和重置

参考文章 对 state 进行保留和重置 各个组件的 state 是各自独立的。根据组件在 UI 树中的位置&#xff0c;React 可以跟踪哪些 state 属于哪个组件。可以控制在重新渲染过程中何时对 state 进行保留和重置。 UI 树 浏览器使用许多树形结构来为 UI 建立模型。DOM 用于表示 …

3DCAT携手华为,打造XR虚拟仿真实训实时云渲染解决方案

2023年5月8日-9日&#xff0c;以 因聚而生 众志有为 为主题的 华为中国合作伙伴大会2023 在深圳国际会展中心隆重举行。本次大会汇聚了ICT产业界的广大新老伙伴朋友&#xff0c;共同探讨数字化转型的新机遇&#xff0c;共享数字化未来的新成果。 华为中国合作伙伴大会2023现场&…

Python小知识 - 使用Python进行数据分析

使用Python进行数据分析 数据分析简介 数据分析&#xff0c;又称为信息分析&#xff0c;是指对数据进行综合处理、归纳提炼、概括总结的过程&#xff0c;是数据处理的第一步。 数据分析的目的是了解数据的内在规律&#xff0c;为数据挖掘&#xff0c;并应用于商业决策、科学研究…

04ShardingSphere-JDBC垂直分片

1、准备服务器 比如商城项目中&#xff0c;有用户、订单等系统&#xff0c;数据库在设计时用户信息与订单信息在同一表中。这里创建用户服务、订单服务实现数据库的用户信息和订单信息垂直分片 服务器规划&#xff1a;使用docker方式创建如下容器 服务器&#xff1a;容器名se…

P13 VUE 二级menu实现

主要修改以下几个点&#xff1a; CommonAside.vue中 外层便利有孩子节点&#xff0c;关键词key是对应的标签&#xff0c;class动态图表渲染 内层遍历不能再用item&#xff0c;用subitem&#xff0c;遍历该item.childeren&#xff0c;关键词是path&#xff0c; <templat…

java 批量下载将多个文件(minio中存储)压缩成一个zip包

我的需求是将minio中存储的文件按照查询条件查询出来统一压成一个zip包然后下载下来。 思路&#xff1a;针对这个需求&#xff0c;其实可以有多个思路&#xff0c;不过也大同小异&#xff0c;一般都是后端返回流文件前端再处理下载&#xff0c;也有少数是压缩成zip包之后直接给…

【C++设计模式】详解装饰模式

2023年8月31日&#xff0c;周四上午 这是我目前碰到的最难的设计模式..... 非常难以理解而且比较灵活多半&#xff0c;学得贼难受&#xff0c;写得贼费劲..... 2023年8月31日&#xff0c;周四晚上19:48 终于写完了&#xff0c;花了一天的时间来学习装饰模式和写这篇博客。 …

《Kubernetes部署篇:Ubuntu20.04基于二进制安装安装kubeadm、kubelet和kubectl》

一、背景 由于客户网络处于专网环境下&#xff0c; 使用kubeadm工具安装K8S集群&#xff0c;由于无法连通互联网&#xff0c;所有无法使用apt工具安装kubeadm、kubelet、kubectl&#xff0c;当然你也可以使用apt-get工具在一台能够连通互联网环境的服务器上下载kubeadm、kubele…

说说Kappa架构

分析&回答 对于实时数仓而言&#xff0c;Lmabda架构有很明显的不足&#xff0c;首先同时维护两套系统&#xff0c;资源占用率高&#xff0c;其次这两套系统的数据处理逻辑相同&#xff0c;代码重复开发。 能否有一种架构&#xff0c;只需要维护一套系统&#xff0c;就可以…

【核磁共振成像】相位差重建

目录 一、相位差map重建一般步骤和反正切函数主值范围二、反正切运算三、可预期相位误差和伴随场的校正四、图形变形校正 一、相位差map重建一般步骤和反正切函数主值范围 MRI是一个相敏成像模态&#xff0c;MR原始数据傅里叶变换后的复数图像中每个像素值有模和相位。标准模重…

HTML5

写在前面 一、开个头 安装vscode 1.1 什么是网页 网站是指因特网上根据一定的规则&#xff0c;使用HTML等制作的用于展示特定内容相关的网页集合。 网页是网站中的一“页”&#xff0c;通常是HTML格式的文件&#xff0c;它要通过浏览器来阅读。 网页是构成网站的基本元素…

uniapp 微信小程序 锚点跳转

uniapp文档 以下是我遇到的业务场景&#xff0c;是点击商品分类的某一类 然后页面滚动至目标分类&#xff0c; 首先第一步是设置锚点跳转的目的地&#xff0c;在目标的dom上面添加id属性 然后给每个分类每一项添加点击事件&#xff0c;分类这里的item数据里面有一字段是和上…

OpenCV(三):Mat类数据的读取

目录 1.Mat类矩阵的常用属性 2.Mat元素的读取 1.at方法读取Mat矩阵元素 at (int row,int col) 2.矩阵元素地址定位方式访问元素 3.Android jni demo 1.Mat类矩阵的常用属性 下面是一些Mat类的常用属性&#xff1a; rows: 返回Mat对象的行数。 cols: 返回Mat对象的列数。 …

SpringMVC概述与简单使用

1.SpringMVC简介 SpringMVC也叫做Spring web mvc,是 Spring 框架的一部分&#xff0c;是在 Spring3.0 后发布的。 2.SpringMVC优点 1.基于 MVC 架构 基于 MVC 架构&#xff0c;功能分工明确。解耦合&#xff0c; 2.容易理解&#xff0c;上手快&#xff1b;使用简单。 就可以…

AttributeError: ‘ConfigDict‘ object has no attribute ‘log_level‘

运行 python tools/train.py configs/pspnet/pspnet_r50-d8_512x512_80k_ade20k.py 时出现 问题 Traceback (most recent call last):File "tools/train.py", line 242, in <module>main()File "tools/train.py", line 167, in mainlogger get_ro…

0基础学习VR全景平台篇 第94篇:智慧景区浏览界面介绍

一、景区详细信息介绍 点击左上角的图标就可以看到景区详细信息例如景区简介&#xff0c;地址&#xff0c;开放信息&#xff0c;联系电话等 二、问题反馈中心 点击左下角的【问题反馈】按钮向作者进行问题反馈 三、开场地图 1、直接点击开场地图页面上的图标浏览该场景 2、通…

Java流数据

流数据 可以从不同的角度对流进行分类&#xff1a; 处理的数据单位不同&#xff0c;可分为&#xff1a;字符流&#xff0c;字节流 2.数据流方向不同&#xff0c;可分为&#xff1a;输入流&#xff0c;输出流 3.功能不同&#xff0c;可分为&#xff1a;节点流&#xff0c;处理…

【golang】简单介绍下goroutine

前面的两篇&#xff0c;从相对比较简单的锁的内容入手(也是干货满满)&#xff0c;开始了go的系列。这篇开始&#xff0c;进入更核心的内容。我们知道&#xff0c;go应该是第一门在语言层面支持协程的编程语言(可能是我孤陋寡闻)&#xff0c;goroutine也完全算的上是go的门面。g…