开篇先说一句废话····
本旺名字叫萨摩耶,,Please 叫我旺财,,,哈哈,招财进宝嘛!
开篇
从学完帮网友写完《倒计时数字钟–矩阵按键可调》然后在CSDN上总结完之后,学习了剩下的模块,由于难度的提升和学期进入复习阶段,导致很长一段时间都“放弃”了单片机,今天突然想着继续总结一下之前学习的红外通信,特有此篇。
红外通信张什么样
直接上图
接收装置
发送装置
红外通信概念
红外遥控是利用波长0.76~1.5um之间的红外信号来传递信号
一个红外线系统一个有两个部分构成
- 红外发射–> 键盘,红外编码,电源,红外发射
- 红外接收–>红外接收,红外编码,电源,应用电路
常用PWM(利用脉冲宽度)和PPM(脉冲串之间时间间隔)两种方式来实现信号调剂,而我们采用的就是PPM(脉时)。
在发射端要对晶振进行整数分频, 分频系数一般取 12。
通常的红外遥控器是将遥控信号(二进制脉冲码) 调制在 38KHz 的载波上。普中科技单片机红外遥控采用NEC协议。
特点:
- 8位地址和8位指令长度
- 地址和命令传输两次(确保可靠性)
- 载波频率为38KHz
- 位时间为1.125ms或2.25ms
NEC协议下位定义的时序图如下:
数据格式:
编程的时候就是利用数据格式和时序图。一定要注意的是因为红外通信的三端,VCC,GND,VDD。也就是单线通信,和Ds18b20一样一定要注意通信时间的控制。
用数码管显示红外编码
其实我觉得红外通信和矩阵按键的用法差不多,都是先知道每个按键的值(红外通信中红外发射装置的每个按键的红外编码),使用多分支判断使用。所以我们首先要完成就是采集每个按键的红外编码,而今天的项目就是用数码显示每个按键的红外编码,为以后的使用做铺垫。
先看红外通信的原理图。
发现,红外接收模块的数据口接在P3^ 2上,而 P3 ^2也是外部中断0的引发管脚,所以红外通信使用外部中断来接受信号。
主函数步骤:
1.初始化(初始化外部中断0和初始化数据传输口P3^2)
2.循环采集数据,并且转换为数码管段选
3.数码管显示
void IrInit(){
IT0=1;
EX0=1;
EA=1;
INIR=1;
}
//数码管显示函数
void Showsmg(){
u8 i;
for(i=0;i<3;i++){
switch(i){
case 2: LSA=1;LSB=0;LSC=1;break;
case 1: LSA=0;LSB=1;LSC=1;break;
case 0: LSA=1;LSB=1;LSC=1;break;
}
P0=Display[i];
Delay(100);
P0=0x00;
}
}
void main(){
IrInit();
while(1){
Display[0]=smgduan[IrData[2]/16];
Display[1]=smgduan[IrData[2]%16];
Display[2]=smgduan[16];
Showsmg();
}
}
外部中断步骤:(数据格式图)
1.声明一变量来存放高电平时间
2.如果P3^2口为低电平,超时判断(等待前9ms过去)
如果传输正确(为高电平)接着运行,否则9ms后结束
3.如果P3^2口为高电平,超时判断(等待4.5ms过去)
开始接受数据(4组8位数据)
4.采用for循环嵌套(大循环4次,小循环8次)循环内:
- 等待前面560us低电平
- 计算高电平时间(区分位0和位1)判断如果时间超过3ms退出(位1的总时间为2.25ms)
- 对高电平时间判断分辨出位0或者位1,存放在数组中
- 时间变量清零
5.判断数据码和数据反码(取反后)如果相等则退出中断
void ReadIr() interrupt 0{
u8 i,j;
u16 err;
time=0;
Delay(700);
if(INIR==0){
err=1000;
while((INIR==0)&&(err>0)){
Delay(1);
err--;
}
if(INIR==1){
err=500;
while((INIR==1)&&(err>0)){
Delay(1);
err--;
}
for(i=0;i<4;i++){
for(j=0;j<8;j++){
err=60;
while((INIR==0)&&(err>0)){
Delay(1);
err--;
}
err=500;
while((INIR==1)&&(err>0)){
Delay(10);
time++;
err--;
if(time>30){
return;
}
}
IrData[i]>>=1;
if(time>=8){
IrData[i]|=0x80;
}
time=0;
}
}
}
if(IrData[2]!=~IrData[3]){
return;
}
}
}
附上完整代码:
#include "reg52.h"
#include "intrins.h"
typedef unsigned int u16;
typedef unsigned char u8;
u8 IrData[6];
u8 Display[8];
u8 time;
u8 smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x76};
//38译码器
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit INIR=P3^2;
void Delay(u16 i) //11.0592MHz 10us
{
while(i--);
}
void IrInit(){
IT0=1;
EX0=1;
EA=1;
INIR=1;
}
//数码管显示函数
void Showsmg(){
u8 i;
for(i=0;i<3;i++){
switch(i){
case 2: LSA=1;LSB=0;LSC=1;break;
case 1: LSA=0;LSB=1;LSC=1;break;
case 0: LSA=1;LSB=1;LSC=1;break;
}
P0=Display[i];
Delay(100);
P0=0x00;
}
}
void main(){
IrInit();
while(1){
Display[0]=smgduan[IrData[2]/16];
Display[1]=smgduan[IrData[2]%16];
Display[2]=smgduan[16];
Showsmg();
}
}
void ReadIr() interrupt 0{
u8 i,j;
u16 err;
time=0;
Delay(700);
if(INIR==0){
err=1000;
while((INIR==0)&&(err>0)){
Delay(1);
err--;
}
if(INIR==1){
err=500;
while((INIR==1)&&(err>0)){
Delay(1);
err--;
}
for(i=0;i<4;i++){
for(j=0;j<8;j++){
err=60;
while((INIR==0)&&(err>0)){
Delay(1);
err--;
}
err=500;
while((INIR==1)&&(err>0)){
Delay(10);
time++;
err--;
if(time>30){
return;
}
}
IrData[i]>>=1;
if(time>=8){
IrData[i]|=0x80;
}
time=0;
}
}
}
if(IrData[2]!=~IrData[3]){
return;
}
}
}
总结
项目完成后可以记录每个按键对应的数据码存放到专门的数组中,为之后的红外通信的使用做准备。