当前位置: 首页 > wzjs >正文

荔湾做网站武汉搜索引擎营销

荔湾做网站,武汉搜索引擎营销,聚牛网站建设公司,一家专做中式设计的网站写在前言 此为博主自学江科大51单片机(B站)的笔记,方便后续重温知识 在后面的章节中,为了防止篇幅过长和易于查找,我把一个小节分成两部分来发,上章节主要是关于本节课的硬件介绍、电路图、原理图等理论知识…

写在前言


  此为博主自学江科大51单片机(B站)的笔记,方便后续重温知识

  在后面的章节中,为了防止篇幅过长和易于查找,我把一个小节分成两部分来发,上章节主要是关于本节课的硬件介绍、电路图、原理图等理论知识,主要是为下章节的代码部分打基础。

  我的单片机是24年12月在tb普中买的,型号是STC89C52,在原视频中引脚或接口不对应的我都会改正,保证在我的机子上能运行才发上来的,还有一些文字部分是我的理解,并非照搬,所以可能有理解不到位的现象。

  如有误或交流,敬请指点提问

红外遥控有一个小拨片把电池隔开,用的时候要拿出来

课程目标:

1.LCD显示遥控的地址码,遥控码和+-控制自定义数字

2.红外遥控电机调速

一、红外遥控

新建工程,导入Dealy和LCD模块

1.外部中断

测试一下Web外部中断和下降沿能不能触发

下降沿触发IT0给1,IEO不用管给0,EX0使能中断和EA总中断给1,高优先级精度高防止打断PX0给1

再给一个中断函数,接着在这个函数里对Num++,然后把这个Num显示出来

#include <REGX52.H>
#include " Delay.h"
#include " LCD1602.h"unsigned char Num;void main()
{LCD_Init();LCD_ShowString(1,1,"A");IT0=1;IE0=0;EX0=1;EA=1;PX0=1;while(1){LCD_ShowNum(2,1,Num,3);}}void Int0_Routine(void)  interrupt 0
{Num++;
}

烧录后我们会在LCD上看到000,然后我们怎么触发外部中断呢,要给一个下降沿,怎么给呢,可以看到P32这个引脚接到K3独立按键上,所以按下K3就可以触发外部中断,而且下降沿只触发一次(在这里因为没交消抖,如果按住晃两下还会+多次1)

接下来我们试一下低电平触发,把IT0置0,再运行后发现只要一直按着K3,数字就会一直跳动,直到松手,这是因为低电平触发在低电平时间会一直触发,这就是两种触发方式的区别

在这里我们要用到下降沿触发,接下来把这个中断函数封装一下,因为中断函数一般是放在要用的地方,所以在这里作为一个模版放在这里注释掉

//Int0.c#include <REGX52.H>void Int0_Init(void)
{IT0=1;IE0=0;EX0=1;EA=1;PX0=1;}/*
void Int0_Routine(void)  interrupt 0
{Num++;
}
*/
//Int0.h#ifndef __INT0_H__
#define __INT0_H__void Int0_Init(void);#endif

这样就把外部中断函数封装起来了,要用直接调用就可以了

2.红外解码

思路:IR.c继承Int0和定时器T0(只用来计时),然后main里调用IR.c

定义一个变量表示当前状态,0代表空闲,1代表寻找开始或重复的头部信号,2代表开始解码数据;

当0收到下降沿,把0置1,打开计数器,读取定时器的值,判断中间的时间,

如果是重发信号,就给一个重发标志位置1重发回去;如果是起始信号,就把1置2

然后2状态会连续进行32次,每进行一次2状态,就计算0和1的时间,然后存到变量缓存区,在里面再定义一个变量记录进行了多少次2状态,如果存完32次就认为数据已经收到

然后对数据进行论证,然后再置一个收到数据的标志位,然后把状态切回0

首先来改造定时器0,让他可以计时

第一个函数是初始化,第二个是设置计时值,第三个是得到计时值

第四个是控制启动和停止

//Timer0.c#include <REGX52.H>void Timer0_Init(void)		//1毫秒@12.000MHz
{TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0;		//设置定时初值TH0 = 0;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 0;		//定时器0不计时
}void Timer0_SetCounter(unsigned int Value)
{TH0=Value/256;TL0=Value%256;}unsigned int Timer0_GetCounter(void)
{return (TH0<<8)|TL0;
}void Timer0_Run(unsigned char Flag)
{TR0=Flag;
}

然后我们来验证一下

//main#include <REGX52.H>
#include " Delay.h"
#include " LCD1602.h"
#include " Int0.h"
#include " Timer0.h"unsigned char Num;
unsigned int Time;void main()
{LCD_Init();LCD_ShowString(1,1,"A");Timer0_Init();Timer0_SetCounter(0);Timer0_Run(1);Delay(10);Time=Timer0_GetCounter();LCD_ShowNum(2,1,Time,5);while(1){}
}

可以看到成功计算了,这里显示的是10000us,也就是10ms,只有一点误差很正常

接下来正式开始写红外编码的函数

前面说过了这个函数继承Timer0和Int0,所以导入进来

先把底层给初始化,就是把Timer0和Int0给初始化

void IR_Init(void)
{Timer0_Init();Int0_Init();
}

再定义一些变量,计时,状态,数据区,指向当前存到第几位,数据收到位,重发标志位,IR的地址用于存储数据,一个IR的命令码

左右移有距离限制,最高只有16位有效,所以数据区(32位)不能用long型,只能定义char型,分成4个字节

unsigned int IR_Time;
unsigned char IR_State;unsigned char IR_Data[4];
unsigned char IR_pData;unsigne char IR_DataFlag;
unsigne char IR_RepeatFlag;
unsigne char IR_Address;
unsigne char IR_Command;

然后把Int0的中断函数复制过来,在里面进行编码

用if判断,if IR状态默认是0,当信号来下降沿后,把计时值清零,计时器开始,状态置为1;else if 状态是1,读取计时值,然后再把计时值清零,

然后对计时值进行判断,嵌套if,if 这个时间在13500正负500范围内,就是start信号(下红图),此时把状态置2;else if 这个时间在11250正负500范围,就是重发信号(下绿图),此时把重复标识位置1,然后把计时器停止,把状态置0;再次else,如果出现两个范围都不是,即解码错误等情况,状态继续置1

以上就是状态1的功能

上面的数值是12mhz的,但我们的开发板是11.0592mhz所以开始值是12442,重复值是10368

 到这里可以去验证一下,记得在.h文件声明初始化函数,然后在main文件导入,在主函数里写初始化

然后在代码中有三个地方有P2=0;即让LED全亮,逐次测试每个地方,如果按下遥控器任一个键,LED就会全亮,这样就是成功了

#include <REGX52.H>
#include " Int0.h"
#include " Timer0.h"unsigned int IR_Time;
unsigned char IR_State;unsigned char IR_Data[4];
unsigned char IR_pData;unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;void IR_Init(void)
{Timer0_Init();Int0_Init();
}void Int0_Routine(void) interrupt 0
{if(IR_State==0){P2=0;Timer0_SetCounter(0);Timer0_Run(1);IR_State=1;}else if(IR_State==1){P2=0;IR_Time=Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time>12442-500 && IR_Time<12442+500){P2=0;IR_State=2;}else if(IR_Time>10368-500 && IR_Time<10368+500){IR_RepeatFlag=1;Timer0_Run(0);IR_State=0;}else{IR_State=1;}}}

接下来写关于状态2的功能

先把时间拿出来,然后清零,

紧接着判断时间是否在0的范围里,即if 收到0,就把data的对应位清零(利用“&=~”),把0x01左移pdata位,但是pdata范围是0-31,所以要拆分成4个部分

IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8))

这里巧妙的只用一句代码就把pdata拆分成4个部分,还把每一组的每一位都对应上,思路非常牛

假设pData是10,对第十位取零,也就是第[1]个数组的第2位取零,对应10/8=1和10%8=2

然后把IR_pData++,当下一位来存到下一位

接下来判断时间是否在1的范围里,即else if 收到1,就把data的对应位置1(|=),照样要IR_pData++;

接着要else 特殊情况,把R_pData清零,这一次的数据就作废了,把状态置1

接下来再对IR_pData进行判断,如果大于等于32就是收数据收完了,就清零,然后对数据进行验证,如果第一位等于第二位,第二位也等于第三位,就代表验证通过,成功收到一个数据,然后把DataFlag置1,把数据转移到地址码和命令码上

收到数据后把定时器停止,再把状态置0

void Int0_Routine(void) interrupt 0
{if(IR_State==0){Timer0_SetCounter(0);Timer0_Run(1);IR_State=1;}else if(IR_State==1){IR_Time=Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time>12442-500 && IR_Time<12442+500){IR_State=2;}else if(IR_Time>10368-500 && IR_Time<10368+500){IR_RepeatFlag=1;Timer0_Run(0);IR_State=0;}else{IR_State=1;}}else if(IR_State==2){IR_Time=Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time>1120-500 && IR_Time<1120+500){IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8))IR_pData++;}else if(IR_Time>2250-500 && IR_Time<2250+500){IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8))IR_pData++;}else{IR_pData=0;IR_State=1;}if(IR_pData>=32){IR_pData=0;if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3])){IR_Address=IR_Data[0];IR_Command=IR_Data[2];IR_DataFlag=1;	}Timer0_Run(0);IR_State=0;}}
}

接下来再写一个获取数据标志位的函数

if DataFlag为1,就清零然后返回代表收到,否则就直接返回0

还有获取重复标志位的函数,思路一样的

if RepeatFlag为1,就清零然后返回代表收到,否则就直接返回0

再写两个获取地址和命令的函数

直接返回地址,命令;相当于封装起来

接着把这些函数都放.h文件里声明

unsigned char IR_GetDataFlag(void)
{if(IR_DataFlag){IR_DataFlag=0;return 1;}return 0;
}unsigned char IR_GetRepeatFlag(void)
{if(IR_RepeatFlag){IR_RepeatFlag=0;return 1;}return 0;
}
unsigned char IR_GetAddress(void)
{return IR_Address;
}unsigned char IR_GetCommand(void)
{return IR_Command;
}

然后去主函数里验证一下

定义两个变量地址和命令

接下来的代码放到while里,如果收到数据标识位,把地址和命令拿出来,用LCD显示,因为地址和命令都是十六进制,所以要显示HEX

#include " Delay.h"
#include " LCD1602.h"
#include " Int0.h"
#include " Timer0.h"
#include " IR.h"unsigned char Num;
unsigned char Address;
unsigned char Command;void main()
{LCD_Init();LCD_ShowString(1,1,"A");IR_Init();while(1){if(IR_GetDataFlag()){Address=IR_GetAddress();Command=IR_GetCommand();LCD_ShowHexNum(2,1,Address,2);LCD_ShowHexNum(2,5,Command,2);}}
}

此时就可以在LCD上显示遥控按下的键码值

接下来再写连发功能

一旦收到重发标志位,重发之前肯定收到了一个数据,这个数据已经放在地址里,此时这个标志位已经置1

        if(IR_GetDataFlag() || IR_GetRepeatFlag())

这样就可以实现按下遥控上的VOL-和VOL+就可以在LCD上显示加减并且可以连发

#include <REGX52.H>
#include " Delay.h"
#include " LCD1602.h"
#include " Int0.h"
#include " Timer0.h"
#include " IR.h"unsigned char Num;
unsigned char Address;
unsigned char Command;void main()
{LCD_Init();LCD_ShowString(1,1,"A");IR_Init();while(1){if(IR_GetDataFlag() || IR_GetRepeatFlag()){Address=IR_GetAddress();Command=IR_GetCommand();LCD_ShowHexNum(2,1,Address,2);LCD_ShowHexNum(2,5,Command,2);if(Command==0x15){Num--;}if(Command==0x09){Num++;}LCD_ShowNum(2,10,Num,3);			}}
}

接下来我们把引脚宏定义,方便调用,因为要外部调用,所以写在IR.h里

#define IR_POWER		0x45
#define IR_MODE			0x46
#define IR_MUTE			0x47
#define IR_START_STOP	0x44
#define IR_PREVIOUS		0x40
#define IR_NEXT			0x43
#define IR_EQ			0x07
#define IR_VOL_MINUS	0x15
#define IR_VOL_ADD		0x09
#define IR_0			0x16
#define IR_RPT			0x19
#define IR_USD			0x0D
#define IR_1			0x0C
#define IR_2			0x18
#define IR_3			0x5E
#define IR_4			0x08
#define IR_5			0x1C
#define IR_6			0x5A
#define IR_7			0x42
#define IR_8			0x52
#define IR_9			0x4A

下面再完善一下整个代码

显示更完善的信息,并且让他在不按下时会显示000,再微调一下坐标值

#include <REGX52.H>
#include " Delay.h"
#include " LCD1602.h"
#include " Int0.h"
#include " Timer0.h"
#include " IR.h"unsigned char Num;
unsigned char Address;
unsigned char Command;void main()
{LCD_Init();LCD_ShowString(1,1,"ADDR CMD NUm");LCD_ShowString(2,1,"00    00   000");IR_Init();while(1){if(IR_GetDataFlag() || IR_GetRepeatFlag()){Address=IR_GetAddress();Command=IR_GetCommand();LCD_ShowHexNum(2,1,Address,2);LCD_ShowHexNum(2,7,Command,2);if(Command==IR_VOL_MINUS){Num--;}if(Command==IR_VOL_ADD){Num++;}LCD_ShowNum(2,12,Num,3);			}}
}

二、红外遥控电机调速

下面的代码是在直流电机调速的基础上进行的

下面把PWM模块化,把定时0改成定时1,因为遥控用了定时1

因为高四位是定时1,低四位是定时0,所以只需换一下

然后把其他关于定时0的部分都换成定时1

然后把电机模块化

首先是初始化,然后是设置速度,再把定时1拿过来

#include <REGX52.H>
#include "Timer1.h"//引脚定义
sbit Motor=P1^0;unsigned char Counter,Compare;/*** @brief  电机初始化* @param  无* @retval 无*/
void Motor_Init(void)
{Timer1_Init();
}/*** @brief  电机设置速度* @param  Speed 要设置的速度,范围0~100* @retval 无*/
void Motor_SetSpeed(unsigned char Speed)
{Compare=Speed;
}//定时器1中断函数
void Timer1_Routine() interrupt 3
{TL1 = 0x9C;		//设置定时初值TH1 = 0xFF;		//设置定时初值Counter++;Counter%=100;	//计数值变化范围限制在0~99if(Counter<Compare)	//计数值小于比较值{Motor=1;		//输出1}else				//计数值大于比较值{Motor=0;		//输出0}
}
#ifndef __MOTOR_H__
#define __MOTOR_H__void Motor_Init(void);
void Motor_SetSpeed(unsigned char Speed);#endif
#include <REGX52.H>
#include " Delay.h"
#include " Key.h"
#include " Nixie.h"
#include " Motor.h"unsigned char KeyNum,Speed;void main()
{Motor_Init();while(1){KeyNum=Key();if(KeyNum==1){Speed++;Speed%=4;if(Speed==0){Motor_SetSpeed(0);}if(Speed==1){Motor_SetSpeed(50);}if(Speed==2){Motor_SetSpeed(75);}if(Speed==3){Motor_SetSpeed(100);}}Nixie(1,Speed);}}

这样就实现了封装,并且功能跟之前一样,更加简洁

最后再改改主函数 

导入IR头文件,然后把IR初始化

把按键部分删掉,我们这里也不需要连发功能

如果收到数据,就把命令取出来,嵌套if,如果命令等于IR0,速度=0,然后依次延伸,后面的速度也不变

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Motor.h"
#include "IR.h"unsigned char Command,Speed;void main()
{Motor_Init();IR_Init();while(1){if(IR_GetDataFlag())	//如果收到数据帧{Command=IR_GetCommand();		//获取遥控器命令码if(Command==IR_0){Speed=0;}		//根据遥控器命令码设置速度if(Command==IR_1){Speed=1;}if(Command==IR_2){Speed=2;}if(Command==IR_3){Speed=3;}if(Speed==0){Motor_SetSpeed(0);}	//速度输出if(Speed==1){Motor_SetSpeed(50);}if(Speed==2){Motor_SetSpeed(75);}if(Speed==3){Motor_SetSpeed(100);}}Nixie(1,Speed);						//数码管显示速度}
}

 到这里也就实现了用遥控器的0和123控制直流电机的暂停和123档位

http://www.dtcms.com/wzjs/3678.html

相关文章:

  • 湖州网站建设企业新东方在线教育平台官网
  • 怎么用本机ip做网站网站快速排名推荐
  • 打码挂机网站建设百度做广告多少钱
  • 网站备案要关闭吗网站的推广方案的内容有哪些
  • 淮安神舟建设招标网站2021最近比较火的营销事件
  • 网站建立百度信任新乡百度网站优化排名
  • 做设计在哪个网站找图片关键词优化seo外包
  • 高职两学一做专题网站地推任务网
  • 网站的建设流程具体有哪些百度招聘2022年最新招聘
  • 高明网站设计案例2022最近热点事件及评述
  • 有专门做网站的公司谷歌seo外包
  • 免费推广seo重庆seo公司排名
  • 单位做好职工养老保险中断补缴的新闻网络优化工具app手机版
  • 网站快速过备案百度关键词相关性优化软件
  • 网站开发 保密期限ios微信上的pdf乱码
  • 网站301重定向怎么做广告牌
  • 如何做不同域名跳转同一个网站搜索引擎有哪些好用
  • 东莞网站建设乐云seo在线制作培训机构优化
  • 中山做百度网站的公司名称软件培训机构
  • 一个域名做多个网站他达拉非片和伟哥区别
  • 制作企业网站多少钱优化设计三年级上册答案语文
  • 免费网络电话软件哪个好用百度小程序关键词优化
  • 普通电脑怎么做网站服务器吗痘痘怎么去除有效果
  • 做店标 做店招的网站关键词挖掘站长
  • 网站开发程序员岗位职责网站友链交换平台
  • 建设银行开户行查询网站数字营销软件
  • 查询网站备案时间成人职业技能培训班
  • 怎样建设个人游戏网站青岛网站建设制作推广
  • 网页布局及版面设计淘宝关键词排名优化技巧
  • 网站开发预算成本价营销模式有哪些 新型