100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > STC学习:红外通信1(收发单个字节)

STC学习:红外通信1(收发单个字节)

时间:2019-10-24 20:23:47

相关推荐

STC学习:红外通信1(收发单个字节)

程序运行效果说明

测试方法说明:需要两个电路板,一个用于发送,另一个用于接收。按键KEY1发送数据,按键KEY2让数据值加1,按键KEY3设置电路板是发送或接收,灯亮情况反映当前电路板的收发设置:L0号灯亮说明该电路板为发送方,不亮则为接收方。发送方发送后,发送方数码管的数字显示在接收方数码管上。

程序相关电路及工作原理说明

红外发送接收功能主要依靠2个部分来实现,一是红外收发电路,二是串行接口。红外收发电路用于数据的传输,相当于一座通信的桥梁;串行接口建立在这座桥梁的两端,能把我们需要传输的数据通过红外收发电路这座桥梁进行收发。

1.红外发送接收电路工作原理

红外线接收头可将收到的38kHz的脉冲转换成低电平,使P3.6的输入为0;接收头没收到脉冲则持续输出高电平,使P3.6输入为1。因此,连接在P3.5的红外发光二极管发出38kHz脉冲代表发送0,否则代表发送1。

2.串口1工作原理

串口:串口是串行接口的简称,可以将数据在引脚上一位一位地进行发送和接收。因为串口的数据发送和接收都需要有一个同步的速度,否则就无法正常传输,所以我们在使用串口时需要确定发送和接收的频率,而这个频率我们称为波特率。收发双方设定好了相同的波特率才能正常通信。本例用的是串口1,使用定时器T1作为波特率发生器,发送和接收引脚分配在P3.7和P3.6。

串口1有两个缓冲器的,名称都是SBUF,用于收发数据。

(1)发送信号:(给发送缓冲寄存器SBUF赋值后)数据从P3.7输出(例如:SBUF = data,则开始发送data的内容)。当数据发送完, TI(发送中断请求标志位)自动置1,引起中断;

(2)接收信号:当数据接收完毕后, RI(接收中断请求标志位)自动置1,引起中断,此时可以从接收缓冲寄存器SBUF中读出数据(例如:data=SBUF)。

注: TI和RI需要软件清零。发送和接收中断会转跳到同一个中断处理函数。

对于串口发送数据的规则,我们可以参照下面的时序图:

那么,我们如何将串行接口的数据装载到红外收发这座通信桥梁上呢?

为了使红外发送电路知道在什么时候发送什么样的数据,我们只需要查看串行接口P3.7上发送的数据是什么,让红外发光二极管按照P3.7发送的数据做出相应的发光行为,接收一方便能从连接在P3.6引脚上的红外接收头接收到数据,然后对数据进行解调,从而达到了通信的目的。

代码如下:

#include<STC15F2K60S2.H>#define uint unsigned int#define uchar unsigned char#define cstKeyCheckTime 75//按键消抖的周期#define cstKeyMinTime 50 //按键识别被为按下时需检测到的最少次数sbit sbtSel0=P2^0;//位选信号sbit sbtSel1=P2^1;//位选信号sbit sbtSel2=P2^2;//位选信号sbit sbtLedSel=P2^3; //数码管和LED的选择信号sbit sbtPutIr=P3^5; //红外线发送引脚sbit sbtGetIr=P3^7; //串口1发送引脚sbit sbtKey1=P3^2;//按键1 发送信号sbit sbtKey2=P3^3;//按键2 数据加1sbit sbtKey3=P1^7;//按键3 收发模式开关/*---------变量定义---------*/int time=cstKeyCheckTime; //按键消抖周计数(一个周期检测cstKeyCheckTime次)int intKey1Cnt=0;//周期中检测到sbtKey1=0的次数int intKey2Cnt=0;//周期中检测到sbtKey2=0的次数int intKey3Cnt=0;//周期中检测到sbtKey3=0的次数int intKey1State=1; //sbtKey1状态:设置为0代表已按下,1代表未按下int intKey2State=1; //sbtKey2状态:设置为0代表已按下,1代表未按下int intKey3State=1; //sbtKey3状态:设置维0代表已按下,1代表未按下uint uiSeg7Num=0; //数码管显示的数字uchar ucPutIrFlagN=1; //状态标记:0代表可发送,1和2代表不可发送int intMyBuf=11; //接收缓冲,用于收发标志0xca的判断uchar arrSegSelect[]= //段选,显示0-f{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};/*---------函数声明---------*///中断函数除外void TimerInit();//定时器设置void Uart1Init();//串口1设置void Init();//初始化,推挽,设置中断开关void DigSelct(int); //设置数码管位选void CheckKey();//消抖检测以及按键操作(定时器0中断中调用)/*---------主函数---------*/void main(){TimerInit(); //设置定时器Uart1Init(); //设置串口1Init(); //初始化while( 1 );}/*---------初始化函数---------*///设置推挽,中断开关设置void Init(){P0M1=0x00;P0M0=0xff;P2M1=0x00;P2M0=0x08;//中断开关设置,详见数据手册P458ET1=0; //禁止T1中断ET0=1; //打开定时器T0中断ES=1; //打开串口1中断IE2=0X04; //打开定时器2中断EA=1; //打开总中断}/*---------串口1初始化函数---------*/void Uart1Init() //设置方法见数据手册P621(串口1设置)和P498(定时器T1设置){PCON&=0x7F; //波特率不倍速,SMOD=0SCON=0x50; //串口1使用工作方式1,REN=1(允许串行接收)AUXR&=0xFE; //串口1选择定时器T1作为波特率发生器,S1ST2=0AUXR1=0x40; //串口1在P3.6接收,在P3.7发送PS=1; //设置串口中断为最高优先级}/*---------定时器初始化函数---------*/void TimerInit() //设置方法见数据手册P498{AUXR|=0x40; //定时器T1为1T模式,速度是传统8051的12倍,不分频。TMOD&=0x0F;//清除T1模式位TMOD|=0x20;//设置T1模式位,使用8位自动重装模式TL1=0x70; //设置初值TH1=0x70; //设置T1重装值TR1=1; //T1运行控制位置1,允许T1计数AUXR|=0x80; //定时器T0为1T模式,的速度是传统8051的12倍,不分频。TMOD&=0xF0; //清除T0模式位TMOD|=0x02; //设置T0模式位,使用8位自动重装模式TL0=0x70;//设置初值TH0=0x70; //设T0重装值TF0=0; //T0溢出标志位清零TR0=1; //T0运行控制位置1,允许T0计数//定时器T2用于显示和按键消抖,500us定时16位自动重装AUXR|=0x04; //定时器T2为1T模式T2L=0x66; //低位重装值T2H=0xEA; //高位重装值AUXR|= 0x10; //定时器2开始计时}/*---------数码管显示位的选择函数---------*/void DigSelct(int x){sbtSel0=x%2;sbtSel1=x%4/2;sbtSel2=x/4;}/*---------按键检测函数---------*///消抖周期中一次按键的检测,以及检测cstKeyCheckTime次后的操作(需要多次重复调用)void CheckKey(){time--;if(sbtKey1==0)intKey1Cnt++;if(sbtKey2==0)intKey2Cnt++;if(sbtKey3==0)intKey3Cnt++;if(time<=0) //一个周期结束{if(intKey1Cnt>=cstKeyMinTime) //判断sbtKey1被检测为按下的次数是否大于按键识别被为按下需检测到的最少次数{if(intKey1State==1) //判断是否已经被按下{if(ucPutIrFlagN==0) //判断是否可以发送{ucPutIrFlagN=1; //第一次先发送一个标志 PS:如果不增加这个标志,在日光灯下来回遮挡接收头可能会接收到干扰信号SBUF=0xca; //标志为0xca,发送完后在串口中断中再发送数据}intKey1State=0;//状态改变为已经被按下}}elseintKey1State=1; //状态改变为未被按下if(intKey2Cnt>=cstKeyMinTime){if(intKey2State==1){uiSeg7Num++; //数据加1uiSeg7Num%=10;intKey2State=0;}}elseintKey2State=1;if(intKey3Cnt>=cstKeyMinTime){if(intKey3State==1){ucPutIrFlagN=!ucPutIrFlagN; //能否发送的切换REN=~REN;//接收允许标志位,1代表可接收,0代表不可接收intKey3State=0;}}elseintKey3State=1;time=cstKeyCheckTime;intKey1Cnt=0;intKey2Cnt=0;intKey3Cnt=0;}}/*---------定时器0中断服务函数---------*/void T0_Process()interrupt 1{if(sbtGetIr==0)//sbtPutIr根据sbtGetIr的信号产生脉冲sbtPutIr=~sbtPutIr;else //如果P3.7=1则P3.5输出0sbtPutIr=0;}/*---------串口1中断服务函数---------*///发送完毕TI自动置1,产生中断; 接收完毕RI值1,产生中断void Uart1_Process()interrupt 4{if(TI) //判断是否发送中断{TI=0; //发送中断请求标志位清0if(ucPutIrFlagN==1) //判断是否第一次发送{ucPutIrFlagN=2; //第二次发送数据SBUF=uiSeg7Num; //发送uiSeg7Num}if(ucPutIrFlagN==2) //判断是否第二次发送完毕ucPutIrFlagN=0; //发送完ucPutIrFlagN清零}if(RI)//判断是否接收中断{RI=0; //接收中断请求标志位清0if(intMyBuf==0xca)//判断上一次是否收到0xca标志uiSeg7Num=SBUF; //正式接收数据intMyBuf=SBUF; //把这次接收到的数据存入自定义的缓存中,等待下一次的比较}}/*---------定时器2中断服务函数---------*/void T2_Process()interrupt 12{P0=0;//P0清零sbtLedSel=~sbtLedSel; //切换显示if(sbtLedSel==0){DigSelct(7); //选择数码管的第七位P0=arrSegSelect[uiSeg7Num]; //设置数码管显示内容}elseP0=!ucPutIrFlagN;//设置发光的LED灯CheckKey();//按键消抖检测}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。