2019-06-30 16:43:54 yesterdai 阅读数 773
  • 红外遥控其实so easy-第2季第2部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第2个课程,主要讲解如何用单片机进行红外遥控解码。红外遥控是家电产品常用的控制方法,通过本课程学习将对红外遥控发送和接收原理、以及协议、编程等有深刻理解和掌握。

    1919 人正在学习 去看看 朱有鹏

51单片机红外遥控小车

目录

1.红外模块
2.电源模块
3.电动机驱动模块
4.代码
5.总结

1.红外模块
小车采用的红外模块是hx1838模块,采用NEC编码,其时序图如下:时序图
模块时序图
2.电源模块
电源模块采用了两节3.7v的锂电池,由于单片机正常工作的电压在4.5~5.5伏之间,因此采用L7805模块将电压稳定在5伏,给单片机供电。对于四个电动机直接采用7.4伏电压供电。
3.电动机驱动模块
小车的驱动电机采用的是直流电机,根据现有的材料采用的是uln2003模块,使用PWM脉宽调制实现小车的加减速,但无法实现电机的正反转。
4.代码
github
5.总结
这个小车目前功能比较简单,以后会继续改进,emmm,代码也不够完善,要是有朋友能帮我完善就好了,嗯。

2008-09-05 18:39:00 de_12 阅读数 798
  • 红外遥控其实so easy-第2季第2部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第2个课程,主要讲解如何用单片机进行红外遥控解码。红外遥控是家电产品常用的控制方法,通过本课程学习将对红外遥控发送和接收原理、以及协议、编程等有深刻理解和掌握。

    1919 人正在学习 去看看 朱有鹏

    前不久,要用单片机做一个发送红外遥控码的程序,以前只搞硬件,第一次作软件,不知所以然,想到网上参考一下,结果找来找去总是那么一个,还是用汇编写的,看了很久不知讲些什么,只好自己写了。在此给像我一样的新手一个参考,分享一下。

    这个程序主要是用单片机来控制数码相框(或广告机),利用人体红外探头检测是否有人移动,然后根据用记所选择的模式来控制数码相框(或广告机)的工作状态。

    代码如下:

    以下是头文件:

  1. //
  2. //
  3. // this header file is programmed by hdl ,
  4. // maybe there are something that is not correct ,
  5. // please connect me when come accross problem ,
  6. // e_mail:de_12@163.com
  7. //
  8. //
  9. // the following is header file
  10. //
  11. // if you use any other [single chip computer] or [PIC] ,
  12. // please change this header file only , you don not hava to 
  13. // change the [C] file
  14. //
  15. // programmed on 2008 - 08 - 29
  16. //
  17. // single chip computer [holtek ht48f06e] , web site : http://www.holtek.com.tw ; http://www.holtek.com.cn
  18. //
  19. //
  20. #ifndef haodl_h_file                    
  21. #define haodl_h_file                    
  22. #ifndef hdl_inlcude_ht48f06e
  23.     #include "ht48f06e.h"                                           
  24.     #define hdl_inlcude_ht48f06e
  25.     #define single_chip_is_ht48f06e 1
  26.     #define __mod_can_change_by_key__                                   
  27. #endif
  28. #ifdef __mod_can_change_by_key__
  29.     #define keychange 0
  30.     #define plugchange 1
  31. #endif
  32. typedef enum
  33. {
  34.     false,
  35.     true
  36. }
  37. BOOL;
  38. typedef enum
  39. {
  40.     irMute,
  41.     irTurnOffBK,
  42.     irMutePause
  43. }
  44. CONMODE;
  45. typedef unsigned short BYTE;
  46. #define pac _pac
  47. #define pbc _pbc
  48. #define pcc _pcc
  49. #define pa _pa
  50. #define pb _pb
  51. #define pc _pc
  52. #define pa0 _pa0
  53. #define pa1 _pa1
  54. #define pa2 _pa2
  55. #define pa3 _pa3
  56. #define pa4 _pa4
  57. #define pa5 _pa5
  58. #define pa6 _pa6
  59. #define pa7 _pa7
  60. #define pb2 _pb2
  61. #define pb1 _pb1
  62. #define pb0 _pb0
  63. #define tmrc _tmrc
  64. #define intc _intc
  65. #define sysDelay _delay
  66. #define powerOffBk() {pause();/
  67.                         pa1=1;}
  68.                     
  69. #define powerOnBk() {pa1=0;/
  70.                         pause();}
  71.                     
  72. void powerOnIni();
  73. void IR(BYTE);
  74. #define mute() IR(0x04)
  75. #define muteOff mute
  76. #define muteOn mute
  77. #define pause() IR(0x1F)
  78.                         
  79. #define delay(t) {for (a=1;a<=t;a++)/
  80.                     sysDelay(10000);}
  81.                     
  82. #define muteAndPause pause
  83. void delay1s();
  84. #define __hdl main
  85. #endif

       以下是C文件:

  1. #include "hdl_d.h"
  2. /********** function **********
  3. ------- function name : powerOnIni 
  4. ------- function : initiate the status of ht48f06e 
  5. ------- author : hdl 
  6. ------- programmed date : 2008 - 08 - 29 
  7. *******************************/
  8. /*
  9. ********* please modify any variable of this function *********
  10. ********* when you need ***************************************
  11. */
  12. void powerOnIni()
  13. {
  14.     tmrc = 0;
  15.     intc = 0;
  16.     pac = 9;
  17.     pbc = 6;
  18.     pcc = 0;
  19.     pa1 = 0;
  20.     pa2 = 1;
  21. }
  22. /*
  23. // this file is programmed by hdl ,
  24. // please connect me when come accross problem ,
  25. // e_mail:de_12@163.com
  26. */
  27. /***************************** NOTICE : ************************
  28. *********** please change time your ir has to delay ************
  29. ***********   and the ir leader code , custom code  ************
  30. ****************************************************************/
  31. /********** function **********
  32. ------- function name : IR
  33. ------- function : generate ir serial code 
  34. ------- author : hdl 
  35. ------- programmed date : 2008 - 08 - 29 
  36. *******************************/
  37. void IR(BYTE irCode)
  38. {
  39.     BYTE dataCode;
  40.     BYTE i;
  41.     
  42.     if (irCode == 0)
  43.         return;     
  44.     
  45.     /***** this variable is not required ****/
  46.     dataCode = irCode;
  47.     
  48.     /**** the start of leader code ****/
  49.     
  50.     pa2 = 0;
  51.     sysDelay(9000);
  52.     pa2 = 1;
  53.     sysDelay(4500);
  54.     
  55.     /**** the end of leader code ****/
  56.     
  57.     /**** start of custom code ****/
  58.     
  59.     for (i=0;i<8;i++)
  60.     {
  61.         pa2 = 1;
  62.         sysDelay(560);
  63.         pa2 = 0;
  64.         sysDelay(565);      
  65.     }
  66.     
  67.     for (i=0;i<8;i++)
  68.     {
  69.         pa2 = 1;
  70.         sysDelay(560);
  71.         pa2 = 0;
  72.         sysDelay(1690);     
  73.     }
  74.     
  75.     /**** end of custom code ****/
  76.     
  77.     /**** start of data code ****/
  78.     
  79.     for (i=0;i<8;i++)
  80.     {
  81.         if ((dataCode>>i)&0x01) 
  82.         {
  83.             pa2 = 1;
  84.             sysDelay(560);  
  85.             pa2 = 0;
  86.             sysDelay(1690);
  87.         }           
  88.         else
  89.         {
  90.             pa2 = 1;
  91.             sysDelay(560);
  92.             pa2 = 0;
  93.             sysDelay(565);
  94.         }           
  95.     }
  96.     
  97.     for (i=0;i<8;i++)
  98.     {
  99.         if ((dataCode>>i)&0x01)
  100.         {
  101.             pa2 = 1;
  102.             sysDelay(560);
  103.             pa2 = 0;
  104.             sysDelay(565);
  105.         }   
  106.         else
  107.         {
  108.             pa2 = 1;
  109.             sysDelay(560);
  110.             pa2 = 0;
  111.             sysDelay(1690);
  112.         }           
  113.     }
  114.     
  115.     /**** end of data code ****/
  116.     
  117.     /**** other code starts ****/
  118.     /**** different ir may have different code ****/
  119.     /**** this code is not required ****/
  120.     
  121.     pa2 = 1;
  122.     
  123.     for (i=0;i<2;i++)
  124.         sysDelay(30000);
  125.     sysDelay(7500);
  126.     
  127.     pa2 = 0;
  128.     sysDelay(9000);
  129.     pa2 = 1;
  130.     sysDelay(2250);
  131.     pa2 = 0;
  132.     sysDelay(560);
  133.     pa2 = 1;
  134.     
  135.     /**** other code ends ****/
  136.     
  137.     irCode = 0;
  138. }
  139. /********** function **********
  140. ------- function name : delay1s
  141. ------- function : delay one minute
  142. ------- author : hdl 
  143. ------- programmed date : 2008 - 08 - 29 
  144. *******************************/
  145. void delay1s()
  146. {
  147.     BYTE a;
  148.     delay(100);
  149. }

    程序注释应是很清楚了,从中可以看到IR码的发送函数IR(BYTE);正是通过此函数发送的IR码。主函数是用来切换工作模式的,您可以试着编写一下,这里不再给出了。

    如果有什么问题,与我联系。

    E-mail : de_12@163.com。

2019-06-15 10:36:14 weixin_38679924 阅读数 598
  • 红外遥控其实so easy-第2季第2部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第2个课程,主要讲解如何用单片机进行红外遥控解码。红外遥控是家电产品常用的控制方法,通过本课程学习将对红外遥控发送和接收原理、以及协议、编程等有深刻理解和掌握。

    1919 人正在学习 去看看 朱有鹏

项目简介:
(TC9012)红外遥控器发送红外信号, 红外接收模块接收到信号后,通过外部中断0传送给(51)单片机; 单片机对接收到的每帧数据解码后将相应的按键值显示在LCD1602上; 并实现对相应外设的控制:0-开buzzer, 1-关buzzer; 2-开LED, 3-关LED。
TC9012遥控器相关参数如下:
1.发送的每帧数据格式如下:
在这里插入图片描述
每帧数据共33bit(1bit引导码 + 32bit数据),发送时低位在前,高位在后;
2.引导码波形格式如下:
在这里插入图片描述
3.逻辑0波形格式如下:
在这里插入图片描述
4.逻辑1波形格式如下:
在这里插入图片描述
C语言代码如下:

/*---------------------------
FileName: InfraredControl2.h
Funtion: 头文件
Author: Zhang Kaizhou
Date: 2019-6-14 19:09:23
---------------------------*/
#include <reg52.h>
#include <string.h>
#include <stdio.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define DATALEN 33 // 数据帧长度(1bit引导码 + 32bit数据)
	
/*红外接收模块端口定义*/
sbit infraredReceiver = P3^2;

/*LCD1602显示模块端口定义*/
sbit lcdrs = P1^0;
sbit lcdrw = P1^1;
sbit lcden = P2^5;

/*LED灯端口定义*/
sbit led = P1^7;

/*蜂鸣器端口定义*/
sbit buzzer = P2^3;

/*主模块函数声明*/
void timerInit();
void ecternINT0Init();
void dataProcess();
void keyValueProcess();

/*LCD1602显示模块函数声明*/
void delay(uint xms);
void writeCommand(uchar command);
void writeDataLCD(uchar dat);
void LCDInit();
void display(uchar dat);
/*---------------------------------------------------------------------
FileName: main.c
Function: (TC9012)红外遥控器发送红外信号, 红外接收模块接收到信号后,
通过外部中断0传送给(51)单片机; 单片机对接收到的每帧数据解码后将相应的
按键值显示在LCD1602上; 并实现对相应外设的控制:0-开buzzer, 1-关buzzer;
2-开LED, 3-关LED。
Author: Zhang Kaizhou
Date: 2019-6-14 19:08:23
----------------------------------------------------------------------*/
#include "InfraredControl2.h"

/*定义全局变量*/
uchar time = 0; // 用于记录接收的数据中两个下降沿之间的时间差
uchar disValue = 0; // 用于存放要显示数据
uchar dat[DATALEN] = 0; // 用于存放接收到的数据
uchar finalData[4] = 0; // 用于存放最终译码后的键值
bit receiveFlag = 0; // 接收结束标志位
bit processFlag = 0; // 一帧数据处理完成标志位
bit keyFlag = 0; // 键值处理完成标志位

/*主函数*/
void main(){
	LCDInit();
	ecternINT0Init();
	timerInit();
	while(1){
		if(receiveFlag){
			receiveFlag = 0;
			dataProcess();
		}
		if(processFlag){
			processFlag = 0;
			keyValueProcess();
		}
		if(keyFlag){
			keyFlag = 0;
			display(disValue);
		}
	}
}

/*定时器初始化函数*/
void timerInit(){
	TMOD = 0x02; // timer0 定时模式 工作方式2(自动重装初值的8位定时器)
	TH0 = 0x00; // 置初值
	TL0 = 0x00;
	ET0 = 1; // 开timer0溢出中断
	TR0 = 1; // 启动timer0
}

/*timer0中断服务程序*/
void timer0Service() interrupt 1{
	time++;
}

/*外部中断0(INT0)初始化*/
void ecternINT0Init(){
	IT0 = 1; //外部中断0为跳变沿触发
	EX0 = 1; // 允许外部中断0
	EA = 1; // 开全局中断
}

/*外部中断0(INT0)中断服务程序*/
void externINT0Service() interrupt 0{
	static uchar i; // 定义静态局部变量i, 每次调用函数时保存上次的变量值
	static bit startFlag;
	if(startFlag){ // 判定是否已启动红外通信
		if(time >= 30 && time < 50){ // 检测到引导码(4.5 + 4.5 = 9ms), 9 / 0.278 = 32; 检测冗余时间范围[30, 50]
			i = 0; // 引导码保存在数组的第0位
		}
		dat[i++] = time; // 存储每个数据位持续的时间用于后续0 1的判定
		time = 0;
		if(i == 33){ // 一帧数据(1bit引导码 + 32bit数据)接收结束
			receiveFlag = 1;
			i = 0;
		}
	}else{ // 启动红外通信
		time = 0;
		startFlag = 1;
	}
}

/*数据处理函数*/
void dataProcess(){
	uchar i, j, k = 1; // k标记当前处理的数据位(跳过第0位引导码)
	uchar value; // 存放处理后的键值
	for(i = 0; i < 4; i++){ // 一帧数据(4个字节)
		value = 0;
		for(j = 0; j < 8; j++){ // 每个字节8位
			if(dat[k++] > 7){ // 当前数据为1
				/*TC9012遥控器定义'0'的两个下降沿时间间隔为1.125ms; '1'的两个下降沿时间间隔为2.25ms;
					所以接收端检测到的时间间隔[time * T(系统)]的平均值 = (1.125 + 2.25) / 2 = 1.6875ms;
					假定系统晶振为11.0592MHz, 则T(系统) = 1.0850694us; 8位定时器每次定时长度 = 256 * T(系统) = 0.277ms;
					1.6875 / 0.277 = 6.0921(次); 所以, 若定时次数大于7次,即平均时间间隔大于1.6875ms, 可判定该数据为1;
					否则为0。
				*/
				value |= 0x80; // 最高位置1
			}
			if(j < 7){
				value >>= 1; // 因为TC9012遥控器发送的数据低位在前,高位在后,故需做右移位处理
			}
		}
		finalData[i] = value;
	}
	processFlag = 1; // 一帧数据处理完
}

/*键值处理函数*/
void keyValueProcess(){
	switch(finalData[2]){
		/*特殊功能键(11个)*/
		case 0x45: break;
		case 0x46: break;
		case 0x47: break;
		case 0x44: break;
		case 0x40: break;
		case 0x43: break;
		case 0x07: break;
		case 0x15: break;
		case 0x09: break;
		case 0x19: break;
		case 0x0d: break;
		
		/*数字键(0~9共10个)*/
		case 0x16: disValue = 0; buzzer = 0; break; // 显示按键值0, 开蜂鸣器
		case 0x0c: disValue = 1; buzzer = 1; break; // 显示按键值1, 关蜂鸣器
		case 0x18: disValue = 2; led = 0; break; // 显示按键值2, 开LED
		case 0x5e: disValue = 3; led = 1; break; // 显示按键值3, 关LED
		case 0x08: disValue = 4; break;
		case 0x1c: disValue = 5; break;
		case 0x5a: disValue = 6; break;
		case 0x42: disValue = 7; break;
		case 0x52: disValue = 8; break;
		case 0x4a: disValue = 9; break; // 9
		default: break;
	}
	keyFlag = 1;
}
/*-----------------------------
FileName:display.c
Function: LCD1602显示函数
Author: Zhang Kaizhou
Date: 2019-6-14 19:10:49
------------------------------*/
#include "InfraredControl2.h"

uchar code table0[] = {"Infrared value"};
uchar code table1[] = {"Received:"};
uchar code table2[] = {"0123456789"};
uchar num = 0;

/*初始化LCD1602的设置*/
void LCDInit(){
	uchar i;
	lcden = 0; // 拉低使能端,准备产生使能高脉冲信号
	writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口)
	writeCommand(0x0c); // 开显示,不显示光标
	writeCommand(0x06); // 写一个字符后地址指针自动加1
	writeCommand(0x01); // 显示清零,数据指针清零
	
	/*LCD上电界面*/
	writeCommand(0x80); // 将数据指针定位到第一行首
	for(i = 0; i < strlen(table0); i++){
		writeDataLCD(table0[i]);
		delay(5);
	}
	
	writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首
	for(i = 0; i < strlen(table1); i++){
		writeDataLCD(table1[i]);
		delay(5);
	}
}

/*LCD显示函数*/
void display(uchar dat){
	writeCommand(0x80 + 0x40 + strlen(table1));
	writeDataLCD(table2[dat]);
	delay(5);
}

/*写指令函数*/
void writeCommand(uchar command){
	lcdrs = 0; // 命令选择
	lcdrw = 0;
	P0 = command;
	delay(5);
	
	lcden = 1; // 产生一个正脉冲使能信号
	delay(5);
	lcden = 0;
}

/*写数据函数*/
void writeDataLCD(uchar dat){
	lcdrs = 1; // 数据选择
	lcdrw = 0;
	P0 = dat;
	delay(5);
	
	lcden = 1;
	delay(5);
	lcden = 0;
}

/*延时xms函数*/
void delay(uint xms){
	uint i, j;
	for(i = xms; i > 0; i--)
		for(j = 110; j > 0; j--);
}
2015-03-22 21:24:17 wendenggo 阅读数 927
  • 红外遥控其实so easy-第2季第2部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第2个课程,主要讲解如何用单片机进行红外遥控解码。红外遥控是家电产品常用的控制方法,通过本课程学习将对红外遥控发送和接收原理、以及协议、编程等有深刻理解和掌握。

    1919 人正在学习 去看看 朱有鹏
51单片机红外遥控基于nec协议,数据分为六位。第三位为辨别码。在例程中添加接口在如图位置
2019-11-11 22:42:00 nknkkn 阅读数 24
  • 红外遥控其实so easy-第2季第2部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第2个课程,主要讲解如何用单片机进行红外遥控解码。红外遥控是家电产品常用的控制方法,通过本课程学习将对红外遥控发送和接收原理、以及协议、编程等有深刻理解和掌握。

    1919 人正在学习 去看看 朱有鹏

基于单片机的红外通信
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以下是一个红外遥控小车的程序

#include <reg52.h>
#define uchar unsigned char
#define uint  unsigned int
sbit P10=P1^0;
sbit P11=P1^1;
sbit IN1 = P1^2;
sbit IN2 = P1^3;
sbit IN3 = P1^6;
sbit IN4 = P1^7;
sbit EN1 = P1^4;
sbit EN2 = P1^5;
uchar IRtime,t;    //储存检测红外高低电平持续时间
uchar IRcord[4]; //储存解码后的4个字节数据
uchar IRdata[33];//包含起始码在内的33位数据
bit IRpro_ok;    //解码后4个字节数据接收完成标志位
bit IRok;        //33位数据接收完成标志位
uchar zz=0,yz=0;
void delay(uint z)
{
 uint i,j;
 for(i=z;i>0;i--)
 for(j=114;j>0;j--);
}
void init()
{
    TMOD|=0x02;//设置定时器0工作模式2,8位自动重装
    TL0=TH0=0;//初始化定时器0寄存器,定时器0溢出一次时间为256个机器周期
    EA=1;
    ET0=1;
    TR0=1;
    
    IT0=1;//设置外部中断0跳边沿触发方式
    EX0=1;
    }
```c
void time0() interrupt 1
{
    IRtime++;//277.76us
 t++;
  if(t==200)
  t=EN1=EN2=0;
     if(zz==t)
  EN1 = 1;
  if(yz==t)
  EN2 = 1;
}
//外部中断0存入33次脉宽
void int0() interrupt 0
{
    static uchar i;//静态变量用于存入33次数据计数
    static bit startflag;//开始储存脉宽标志位
    if(startflag)//标志被置1则开始存储33次脉冲宽度,一位一位存
    {
        if((IRtime<53)&&(IRtime>=32))i=0;//判断引导码,如果是引导码则从起始码开始存
        IRdata[i]=IRtime;//以T0溢出的次数来计算脉宽把这个时间存放在数组
        IRtime=0;//计数清零
        i++;//计数脉宽存入次数自加
        if(i==33)//i=33就表示已经存入了33次脉宽
        {
            IRok=1;//脉宽检查完成
            i=0;//把脉宽计数清零准备下次存入
        }
    }
    else
    {
        IRtime=0;//定时器0计数清零,因为初始化时就启动了,即使没有收到红外数据也再加
        startflag=1;//开始处理标志位置1
    }
}
//把提取的33次脉宽解码 NEC协议
void IRcordpro()
{
    uchar i;//计数处理4个字节
    uchar j;//用于处理1个字节的8位数据
    uchar k;//用于计数处理33次脉宽
    k=1;//从第一位脉宽开始处理,丢掉起始码
    for(i=0;i<4;i++)
    {
        for(j=0;j<8;j++)
        {
            if(IRdata[k]>5)    IRcord[i]|=0x80;//如果脉宽大于数据0标准的1125us那么就判断为数据1
            
            if(j<7)    IRcord[i]>>=1;//只能移动7次,防止最后一位移出
            k++;//处理下一次脉宽
        }
    }
    IRpro_ok=1;//解码完成
}
void run()
{
   if(IRcord[2]==0x1c)
   {
    IN1 = 0;
    IN2 = 1;
    IN3 = 1;
    IN4 = 0;
    delay(100);
       IN1 = 0;
          IN2 = 0;
           IN3 = 0;
            IN4 = 0;
            }
            if(IRcord[2]==0x08)
   {
    P11=0;
    IN1 = 0;
    IN2 = 0;
    IN3 = 1;
    IN4 = 0;
    delay(100);
    delay(100);
    P11=1;
    IN1 = 0;
      IN2 = 0;
    IN3 = 0;
    IN4 = 0;
   }
   if(IRcord[2]==0x5a)
   {
       P10=0;
    IN1 = 0;
    IN2 = 1;
    IN3 = 0;
    IN4 = 0;
    delay(100);
     P10=1;
    IN1 = 0;
    IN2 = 0;
    IN3 = 0;
    IN4 = 0;
   }
    if(IRcord[2]==0x52)
   {
       P10=0;
    IN1 = 1;
    IN2 = 0;
    IN3 = 0;
    IN4 = 1;
    delay(200);
     P10=1;
    IN1 = 0;
    IN2 = 0;
    IN3 = 0;
    IN4 = 0;
   }
}
void main()
{
    init();
    while(1)
    {
        if(IRok)//判断33次脉宽是否提取完成
        {
            IRcordpro();//根据脉宽解码出4个字节数据
            IRok=0;//清零脉宽检查完成标志位等待下一次脉宽检查
            if(IRpro_ok)//判断是否解码完成
            {
       run();
                IRpro_ok=0;//清零解码完成标志位
            }
        }
    }   
}

51单片机红外通讯

阅读数 249

红外遥控器库文件

博文 来自: qq_34629988
没有更多推荐了,返回首页