38KHz,NEC红外模拟发送和接收程序
/*************************************************************************************************/
//38k NEC 编码接收和模拟发射
//完整的信号构成:引导码+8位的客户码+8位客户码的补码+8位的按键值+8位按键值的补码+结束码
//接收使用外部中断0,发射管低电平触发
//STC15F104W@24MHz
//
//为了尽可能的简化代码量,没有引入按键,程序运行起来为每250ms一个周期,每250ms通过红外发射管发射一次数据,同
//时若检测到接收管接收到了完整的数据则把这个数据通过串口发出
//
//由于发送和接收数据肯定无法同时在一片单片机上完成,所以若需测试代码的完整功能应准备两个单片机或者其他设备。
//
//网上能找到的模拟红外发射的代码多为通过定时器实现,本代码则统统使用软件延时实现。一来使用定时器太浪费资源,二
//来对于1T单片机来说,用软件延时马马虎虎输出38K的波形还是挺简单的(这都0202年了,估计以后很难由机会再用到12T
//的51单片机了吧)
/*************************************************************************************************/ #include "config.h"
#include "delay.h"
#include "suart.h" sbit IRIN =P3^2; //红外接收端口
sbit IROUT=P3^3; //红外发射端口
unsigned char IrValue[4]; //红外键值.四个数据分别为用户码、用户补码、键值、键值补码
bit flag_Ir; //红外接收完成标志位
void Ir_Init(void); //红外初始化(外部中断0和发送接收端口初始化)
void Ir_Out(unsigned char u, unsigned char x); //发送数据,两个参数分别为用户码和键值
void Ir_Out_Frame(unsigned char y); //发送一帧数据,由 Ir_Out() 函数调用
void Delay7us(); //7us延时 @24.000MHz_STC-Y5
void Delay19us(); //19us延时@24.000MHz_STC-Y5
void Delay100us(); //100us延时@24.000MHz_STC-Y5 /**************************************************************************************************
* 主函数
*/
void main(void)
{
Ir_Init(); //红外初始化
SUART_INIT(); //串口初始化
TxString("38KHz NEC 红外接收测试程序\r\n");
while (1)
{
delay_ms(250); //每250ms通过红外发送一个数据
Ir_Out(0x42,0x5A); //参数为用户码、键值 if(flag_Ir) //如果接收到完整数据,则把数据通过串口打印出来
{
flag_Ir=0; //必须清空接收完成标志
TxByte(IrValue[0]);
TxByte(IrValue[1]);
TxByte(IrValue[2]);
TxByte(IrValue[3]);
}
}
} /**************************************************************************************************
* 红外接收初始化
*/
void Ir_Init(void)
{
IT0 = 1; //下降沿触发
EX0 = 1; //打开中断0允许
EA = 1; //打开总中断
IRIN = 1; //初始化端口
IROUT = 1;
flag_Ir = 0; //初始化接收完成标志位
} /**************************************************************************************************
* 延时7us @ 24MHz STC-Y5
* 生成38k波使用,占空比在1/3时效果最好。i的取值供参考,使用时视波形表现调整。
*/
void Delay7us() //@24.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 38;
while (--i);
}
/**************************************************************************************************
* 延时19us @ 24MHz STC-Y5
* 生成38k波使用,占空比在1/3时效果最好。i的取值供参考,使用时视波形表现调整。
*/
void Delay19us() //@24.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 105;
while (--i);
}
/**************************************************************************************************
* 延时100us @ 24MHz STC-Y5
*/
void Delay100us() //@24.000MHz
{
unsigned char i, j;
i = 3;
j = 82;
do
{
while (--j);
} while (--i);
} /**************************************************************************************************
* 红外发射程序
*/
void Ir_Out(unsigned char u, unsigned char x)
{
int tt;
EA=0; //关闭所有中断 /*发送引导码*/
tt=350; //输出9ms 1(有38k信号输出表示 1. 38k每个周期约26us,9ms大概tt个周期,视实际情况调整)
do {IROUT=0; Delay19us(); IROUT=1; Delay7us();} while(--tt);
tt=45; //输出4.5ms 0 (无38k信号输出表示 0. 同样,tt的取值看实际情况调整)
do {IROUT=1; Delay100us();} while(--tt); /*发送用户码和用户补码*/
Ir_Out_Frame(u);
Ir_Out_Frame(~u); /*发送键值和键值补码*/
Ir_Out_Frame(x);
Ir_Out_Frame(~x); /*发送结束码*/
tt=25; //输出0.65ms 1
do {IROUT=0; Delay19us(); IROUT=1; Delay7us();} while(--tt);
tt=5; //输出40ms 0
do {IROUT=1; Delay100us();} while(--tt); /*重复码*/
//9ms 1
//2.25ms 0
//0.56ms 1
//40ms 0
//56ms 0 EA=1; // 打开中断
}
/**************************************************************************************************
* 红外单帧发射程序
*/
void Ir_Out_Frame(unsigned char y)
{
char num;
int tt;
for (num=0; num<8; num++) //循环8次移位
{
tt=25; //输出0.65ms 1
do {IROUT=0; Delay19us(); IROUT=1; Delay7us();} while(--tt);
if(y&0x01) //if为1
{
tt=16; //输出1.65ms 0
do {IROUT=1; Delay100us();} while(--tt);
}
else //否则
{
tt=5; //输出0.56ms 0
do {IROUT=1; Delay100us();} while(--tt);
}
y >>= 1; //右移一位
}
} /**************************************************************************************************
* 读取红发外值
* 外部中断的服务程序
*/
void ReadIr() interrupt 0
{
unsigned int err;
unsigned int tt;
unsigned char Time;
unsigned char j, k;
EA=0; //关闭总中断
Time=0;
tt=80; //延时8ms去干扰,引导码为9ms的低电平和4.5ms的高电平
do { Delay100us(); } while(--tt);
if(IRIN==0) //确认是否真的接收到正确的信号
{
err=500; //超时判断
while((IRIN==0)&&(err>0)) //等待高电平,最多等待50ms
{
Delay100us();
err--;
}
if(IRIN==1) //收到高电平
{
err=500; //超市判断
while((IRIN==1)&&(err>0)) //等待4.5ms的高电平过去
{
Delay100us();
err--;
}
for(k=0; k<4; k++) //开始接收数据,共有4个数据
{
for(j=0; j<8; j++) //每个8位
{
err=60;
while((IRIN==0)&&(err>0)) //等待信号前面的560us低电平过去
{
Delay100us();
err--;
}
err=500;
while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
{
Delay100us();
Time++;
err--;
if(Time>50) //超过5ms说明接收到重复码。重复码:9ms高电平+2.25ms低电平+560us高电平
{
EA=1; //打开总中断
return; //退出函数
}
}
IrValue[k]>>=1; //k表示第几组数据
if(Time>=8) //若高电平出现大于0.8ms,为1(1.65ms为1,0.56ms为0,这里取中间值)
IrValue[k]|=0x80;
Time=0; //用完时间要重新赋值
}
}
}
if(IrValue[2]=~IrValue[3]) //这里一般只判断键值而不判断用户码,因为对于一些用户码是0的遥控无论怎样都是0
{
flag_Ir = 1; //如果按键值与按键值的补码的取反相同,则接收完成标志置位
}
}
EA=1; //打开总中断
}
38KHz,NEC红外模拟发送和接收程序的更多相关文章
- 使用httperrequest,模拟发送及接收Json请求
使用httpreques\Json-Handle\tcpdump\wireshark工具进行,抓取手机访问网络的包,分析request及response请求,通过httprequester来实现模拟发 ...
- 使用firefox插件httperrequest,模拟发送及接收Json请求 【转】
转自[http://blog.csdn.net/feixue1232/article/details/8535212] 目标:使用httpreques\Json-Handle\tcpdump\wire ...
- 使用HttpRequester模拟发送及接收Json请求
1.开发人员在火狐浏览器里经常使用的工具有Firebug,httprequester,restclient......火狐浏览器有一些强大的插件供开发人员使用!需要的可以在附加组件中扩展. 2.htt ...
- C# Socket模拟发送接收
Socket简介 通过TCP/IP与仪器或设备通讯,在C#语言中,我们通常采用Socket.本项目是一个简单的Socket建立服务监听与Socket作为客户端请求的一个示例. 项目结构 客户端项目 S ...
- 在C#程序中模拟发送键盘按键消息
using System.Runtime.InteropServices; 引入键盘事件函数 [DllImport("user32.dll")]public static exte ...
- nodejs 数据库操作,消息的发送和接收,模拟同步
var deasync = require('deasync'); //导入模板 var mysql=require('mysql'); var Stomp = require('stompjs'); ...
- udp网络程序-发送、接收数据
1. udp网络程序-发送数据 创建一个基于udp的网络程序流程很简单,具体步骤如下: 创建客户端套接字 发送/接收数据 关闭套接字 代码如下: #coding=utf-8from socket im ...
- 管道通信实例(A程序作为服务器,不断从B程序接收数据,并发送到C程序中)
A程序作为服务器,不断从B程序接收数据,并发送到C程序中:#include <stdio.h>#include <conio.h> #include <tchar.h&g ...
- DICOM医学图像处理:DIMSE消息发送与接收“大同小异”之DCMTK fo-dicom mDCM
背景: 从DICOM网络传输一文开始,相继介绍了C-ECHO.C-FIND.C-STORE.C-MOVE等DIMSE-C服务的简单实现,博文中的代码给出的实例都是基于fo-dicom库来实现的,原因只 ...
随机推荐
- Spring学习03(Bean的自动装配)
6.Bean的自动装配 6.1 自动装配说明 自动装配是使用spring满足bean依赖的一种方法 spring会在应用上下文中为某个bean寻找其依赖的bean. Spring中bean的三种装配机 ...
- Git-05-文件删除与恢复
删除文件 1 添加一个文件test.txt文件用于测试 2 删除文件,这样删除,工作区和版本库一致 也可以直接rm 然后在 git rm,git commit 这样也能保证工作区和版本库一致 恢复误删 ...
- HTTP头参数详解及其中的危险
一.重要的头参数 user_agent 发出请求的用户信息 X-Forwarded-For 表示 HTTP 请求端真实 IP(格式:X-Forwarded-For: client, proxy1, p ...
- SpringMVC/boot-CSRF安全方案
1. CSRF原理与防御方案概述 一. 原理 增删改的接口参数值都有规律可循,可以被人恶意构造增删改接口 将恶意构造的增删改接口发给对应特定用户,让特定用户点击 特定用户使用自己的认证信息对该接口发起 ...
- 能说会道爱办公——“别人家的”Chrome插件到底怎么做
根据相关数据显示,谷歌的Chrome浏览器目前已达近七成的市场占有率,成为浏览器的"霸主".大家选择Chrome,除了是因为性能的优越以及强大的兼容性之外,Chrome充足的扩展插 ...
- NOIP 模拟 $21\; \rm Game$
题解 考试的时候遇到了这个题,没多想,直接打了优先队列,但没想到分差竟然不是绝对值,自闭了. 正解: 值域很小,所以我们开个桶,维护当前最大值. 如果新加入的值大于最大值,那么它肯定直接被下一个人选走 ...
- JS获取对象在内存中计算后的样式
通过obj.style的方式只能取得"内联style"的值,对于<style></style>中的css属性值,则无能为力 . 我们可以用obj.curre ...
- 你真的了解JS里的"new"吗?
我们常常喜欢用new关键字去创建一些对象如new Vue(),但是这个关键字的背后究竟做了什么其实没太多人去关注. 想象我们是苹果公司,要生产30部iPod,规定: 每台iPod都会有自己的ID 每台 ...
- C++ 矩形交集和并集的面积-离散化
//离散化,x,y坐标分别按从小到大排序 //离散化 //1.首先分离出所有的横坐标和纵坐标分别按升序存入数组X[ ]和Y[ ]中. //2. 设数组XY[ ][ ].对于每个矩形(x1,y1)(x2 ...
- Java String.split()的特殊用法
1 //用多种字符分隔字符串 2 public class Main { 3 /* 4 * "(1,2),(2,4),(3,6),(4,7)"按[(),]分隔 5 * 空白(1,2 ...