打印
[范例教程]

单片机红外通信

[复制链接]
2778|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
eefas|  楼主 | 2023-7-14 12:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
关于红外通信,网上有很多关于解码的单片机代码和视频,发射编码部分并不好找。写发射部分代码花费了不少时间,拿出来与大家分享一下。下面是我在网上找到的资料:

一、NEC 协议特征:
1.  8 位地址和 8 位命令长度
2. 每次传输两遍地址(用户码)和命令(按键值)
3. 通过脉冲串之间的时间间隔来实现信号的调制(PPM
4.  38Khz 载波
5. 每位的周期为 1.12ms(低电平)或者 2.25ms(高电平)



二、NEC  协议的典型脉冲链:

用户码和数据码中的‘0’‘1’是利用脉冲的时间间隔来区分,这种编码方式称为脉冲 位置调制方式(PPM)。
其中位 0 首先为 0.56ms 的高电平,然后是 0.565ms 的低电平;位 1 首先是 0.56ms的高电平,然后是 1.69ms 的低电平。


五、编程注意事项
1.红外接收头引脚信号是相反的电平 以上电平是从发射头角度来看,红外接收头引脚输出的是相反的电平。 如图,即没有数据传输时,P3.2 引脚保持为高电平,当接收到数据时,首先是引导 码,9ms 的低电平和 4.5ms 的高电平,然后是 32 位数据和 1 位停止位。一般来说, P3.2     与单片机的某中断引脚相连,当接收数据时,低电平会触发中断。

2.数据从 LSB(低位)开始发送,所以选择右移方式接收数据。 四个字节的数据都是先发送 D0,最后发送 D7。所以接收到 1 位数据后,给变量的 最高位赋值,右移。或者先右移,再给变量的最高位赋值。

3.可以用一个数组保存 32 个数据的持续时间,用于后面判断高低电平。 用定时器对两个数据(中断)之间的时间计时,并保存这个持续时间用于以后判断 是位 1 还是位 0

4.可以用 2 字节,4 字节变量存储 32 个数据,以节省代码空间

可以用两个 16 位的 int 型变量存储数据,第一个 int 变量存储用户码,第二个存储数 据码和数据反码。也可以用一个 32 long 型的变量存储所有数据。

5.判断停止位 接收到停止位后可以屏蔽红外引脚的中断,防止后面数据的干扰,解码成功后在开 启中断。
typedef unsigned char uchar;
typedef unsigned int  uint;
sbit irsend = P7^5;              // 红外发送
sbit K = P0^7;                   // 按键总开关
sbit key1 = P0^0;                // 按键1
sbit key2 = P0^1;                // 按键2
uint hwcount, count;             // 要进中断的总次数、用于记录进入中断次数
uchar irsys[2]= {0x00,0xff};     // 16位用户码
bit hsflag = 0;                  // 发送38KHz载波标志位
uchar ircode;                          // 发送的红外数据

void Timer1Init(void)                     // 13微秒@12.000MHz
{
        AUXR &= 0xBF;                         // 定时器时钟12T模式
        TMOD &= 0x0F;                         // 设置定时器模式
        TMOD |= 0x20;                         // 设置定时器模式
        TL1 = 0xF3;                             // 设置定时初值
        TH1 = 0xF3;                             // 设置定时重载值
        TF1 = 0;                             // 清除TF1标志
        TR1 = 0;                             // 定时器1关闭计时
        ET1 = 1;                     // 开定时器1中断
        EA  = 1;                     // 开总中断
}

void Timer1_isr() interrupt 3
{
        count++;
        if(hsflag)                   // 有发射标志,则发射38khz
        {
                irsend = ~irsend;
        }
        else                         // 否则不发射,即相当于发射编码中的低电平
                irsend = 1;
               
}

void ir_SendByte()               // 红外发送一字节数据
{
        uchar i;
        for(i=0;i<8;i++)             // 一字节八位,循环八次
        {
                hwcount = 43;            // 0.56ms高电平,需要进43次定时器1中断(560/13=43)
                hsflag = 1;              // 发射38KHz载波标志
                count = 0;               // count置0,从这时起记录进入定时器1中断的次数
                TR1 = 1;                 // 定时器1开启计时
                while(count < hwcount);  // 在此等待,直到进入中断次数达到43次
                TR1 = 0;                 // 定时器1关闭计时
                if(ircode&0x01)          // 数据是从最低位开始发送的,最低位是1则要进130次中断
                {
                        hwcount = 130;       // 1.69ms低电平,进中断总次数130(1690/13=130)
                }
                else                     // 最低位是0,则要进43次定时器1中断
                {
                        hwcount = 43;        // 0.565ms低电平,进中断总次数43(565/13=43)
                }
                hsflag = 0;              // 低电平,不需要38kHz载波
                count = 0;
                TR1 = 1;
                while(count < hwcount);
                TR1 = 0;
                ircode = ircode >> 1;    // 将数据右移一位,即从低位到高位发送
        }
}
void ir_Send(uchar date)
{
        hwcount = 692;               // (引导码中的)9ms高电平,9000/13=692
        hsflag = 1;                  // 高电平需要38kHz载波
        count = 0;               
        TR1 = 1;
        while(count < hwcount);
        TR1 = 0;
        hwcount = 346;               // (引导码中)4.5ms低电平,4500/13=346
        hsflag = 0;                  // 低电平不需要38kHz载波
        count = 0;
        TR1 = 1;
        while(count < hwcount);
        TR1 = 0;
        ircode = irsys[0];           // 发送用户码的前8位
        ir_SendByte();
        ircode = irsys[1];           // 发送用户码的后8位
        ir_SendByte();
        ircode = date;               // 发送键值
        ir_SendByte();
        ircode = ~date;              // 发送键值反码
        ir_SendByte();
        hwcount = 43;                // 0.56ms高电平,560/13=43
        hsflag = 1;                  // 高电平需要38kHz载波
        count = 0;
        TR1 = 1;                     // 定时器1开启计时
        while(count < hwcount);
        TR1 = 0;                     // 定时器1关闭计时
        hwcount = 43;                // (NEC协议中的停止码)0.56ms低电平
        hsflag = 0;
        count = 0;
        TR1 = 1;
        while(count < hwcount);
        TR1 = 0;
        irsend = 1;                  // 关闭红外发射
}
void main()
{
        K = 0;                       // 按键总开关拉低
        Timer1Init();                // 定时器1初始化
        while(1)
        {
                if(key1 == 0)            // 按键1         
                {               
                        ir_Send(0x8a);       // 发送键值8aH
                }
                if(key2 == 0)            // 按键2
                {
                        ir_Send(0xa6);       // 发送键值a6H
                }
        }
}


使用特权

评论回复
沙发
Pretext| | 2023-7-21 11:33 | 只看该作者
红外通信的原理一直没搞明白。

使用特权

评论回复
板凳
V853| | 2023-7-21 11:33 | 只看该作者
记得好像要用中断才能处理红外数据。

使用特权

评论回复
地板
软核硬核| | 2023-7-21 11:34 | 只看该作者
这个不错,可以发射的话,就可以控制其他空调了。

使用特权

评论回复
5
OKAKAKO| | 2023-7-21 17:38 | 只看该作者
楼主红外线其实是不是就是通过收发器进行光波的接收与发送,实现高低电平的转换的吧

使用特权

评论回复
6
中国龙芯CDX| | 2023-7-24 13:13 | 只看该作者
发射编码部分其实就是定义相关数据与IO口对应即可,一般都有固定的规范

使用特权

评论回复
7
小小蚂蚁举千斤| | 2023-7-25 09:48 | 只看该作者
NEC  协议的规范确实是目前红外的主流

使用特权

评论回复
8
小夏天的大西瓜| | 2023-7-25 10:14 | 只看该作者
红外通信的原理是利用发射器将电信号转换成红外光信号,然后通过空气传输到接收器,再将红外光信号转换成电信号

使用特权

评论回复
9
szt1993| | 2023-7-25 10:58 | 只看该作者
编程时一定要注意:红外接收头引脚信号是相反的电平

使用特权

评论回复
10
OKAKAKO| | 2023-7-25 12:47 | 只看该作者
一般红外设备就是用中断进行区分从而达到更高优先级触发

使用特权

评论回复
11
jf101| | 2023-7-25 13:29 | 只看该作者
红外通信的原理是不是就是依靠光线的闪烁进行的吧

使用特权

评论回复
12
星辰大海不退缩| | 2023-7-25 14:42 | 只看该作者
红外接收器为提高灵敏度,输入高电平输出相反

使用特权

评论回复
13
AdaMaYun| | 2023-7-26 11:34 | 只看该作者
红外是利用脉冲的时间间隔来区分,这种编码方式称为脉冲 位置调制方式(PPM)

使用特权

评论回复
14
LOVEEVER| | 2023-7-26 17:39 | 只看该作者
38Khz 载波其实速率还是挺快的

使用特权

评论回复
15
langgq| | 2023-8-31 19:46 | 只看该作者
好像要用中断才能处理红外数据

使用特权

评论回复
16
pixhw| | 2023-9-12 16:08 | 只看该作者
单片机红外通信是一种常见的通信方式,通常用于红外遥控器、红外传感器等应用。

使用特权

评论回复
17
ulystronglll| | 2023-9-12 17:51 | 只看该作者
红外通信的传输距离相对较短,一般不超过10米

使用特权

评论回复
18
mikewalpole| | 2023-9-12 22:57 | 只看该作者

能耗优化:在移动设备或电池供电的应用中,要优化红外通信的功耗,以延长电池寿命。可以

使用特权

评论回复
19
vivilyly| | 2023-9-13 09:14 | 只看该作者
考虑数据的安全性               

使用特权

评论回复
20
pmp| | 2023-9-13 09:54 | 只看该作者
注意信号的传输路径和接收灵敏度等因素。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

76

主题

2793

帖子

2

粉丝