首页 技术 正文
技术 2022年11月19日
0 收藏 696 点赞 4,750 浏览 4405 个字
/*************************************************************************************************/
//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; //打开总中断
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,999
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,511
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,357
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,140
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848