• 如果发现薅来的封装是错误的,请不要怪羊


    如果发现薅来的封装是错误的,请不要怪羊

    板子上用了一个薅来的红外发射管的封装, 用程序调试时, 发现已经发了红外码, 但是收不到.
    例程是开发板上的现成代码, 工程没问题. 那就是硬件有问题了. 开始查.

    最后发现是当时从元件销售商下载的原始封装就错了, 这事弄的. 不过下载封装时, 人家有免责声明的. 即使没有免责声明, 咱是薅羊毛的, 哪能怪🐏呢? 只能怪自己不仔细.

    所以不管是啥板子, 没有调试通的时候, 不要冲动去做批量. 头一版的板子, 总能找出错误的.
    很羡慕有的大神可以一版通过.

    笔记

    排查过程

    这板子是个开发板, 原理图都是抄的, 除非自己抄错了(前面调试中, 已经发现自己抄错一个地方了, 非常鄙视自己).
    从原理图开始看和红外发射相关的地方.
    在这里插入图片描述
    看到LED1的1脚为正, 2脚为负接地.
    是不是自己将红外发射管焊接反了呢? 去看看PCB.
    在这里插入图片描述
    看到这, 有点怪, 看到+端接的是GND.
    我焊接时, 是看了红外发射管的datasheet后, 将正极焊接到了丝印的+端.
    应该不是焊接反了
    我用的红外发射管型号 : IR204C-A-L M档
    在这里插入图片描述
    我是将红外发射管的长腿接到了丝印的+端.
    那就是封装错了.

    去元件销售商去看封装
    在这里插入图片描述
    从预览看, 人家给的封装是对的.在线用立创EDA分别看了原理图和PCB, 和预览一样, 正确的.
    口说无凭啊, 我怎么会薅来封装后, 改人家原版的丝印呢? 这不科学啊.
    我有个好习惯, 原始文档都要归档的, 不怕哪个环节出问题.
    薅来封装后, 已经归档了. 去看原始归档文件.
    在这里插入图片描述
    原始的存档都在, 就是当时下载了封装后, 先做了归档, 再转格式.
    看看原始档.
    在这里插入图片描述
    可以看到, 红外发射管的原理图是对的, 1是A, 2是C
    去看PCB
    在这里插入图片描述
    可以看到原始档的PCB的丝印是错的.
    这就知道原因了: 因为薅来的原始封装就是错的.
    估计是有用户上报了bug, 元件销售商悄咪咪的更新了. 但是我这有原始文档记录啊:) 可以看出大厂的工作成果也有瑕疵, 其实这也是正常的. 大厂人手足, 更新的勤快啊.

    咱这人手不足, 看归档记录, 这都过去快半年了, 才开始调试板子. 感慨啊, 日月如梭.

    重新验证

    知道问题后, 怕出其他幺蛾子, 将红外发射管拆下来后, 焊接了圆孔插座, 将红外发射管插入插座, 烧程序测试, 好使了.
    在这里插入图片描述

    官方程序的小改进

    我实验的这个工程, 有按键发送红外码和接收红外码的功能.
    原始接收的红外码有显示, 发送的红外码没有显示.
    看到数码管上正好空了2个字符, 将按键发送的键值显示出来.
    在这里插入图片描述
    可以看出红外接收管的指向性不强, 板子自己发送后, 接收管那么偏, 居然自己也收到了.
    用手指捂住红外接收管, 也能收到红外码, 说明人肉是挡不住红外光的.

    修改后的工程实现

    
    /*---------------------------------------------------------------------*/
    /* --- STC MCU International Limited ----------------------------------*/
    /* --- STC 1T Series MCU Demo Programme -------------------------------*/
    /* --- Mobile: (86)13922805190 ----------------------------------------*/
    /* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
    /* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
    /* --- Web: www.GXWMCU.com --------------------------------------------*/
    /* --- QQ:  800003751 -------------------------------------------------*/
    /* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
    /*---------------------------------------------------------------------*/
    
    
    
    /*************	本程序功能说明	**************
    
    红外接收程序。适用于市场上用量最大的NEC编码。
    
    应用层查询 B_IR_Press标志为,则已接收到一个键码放在IR_code中, 处理完键码后, 用户程序清除B_IR_Press标志.
    
    数码管左起4位显示用户码, 最右边两位显示数据, 均为十六进制.
    
    用户可以在宏定义中指定用户码.
    
    用户底层程序按固定的时间间隔(60~125us)调用 "IR_RX_NEC()"函数.
    
    
    按下IO行列键(不支持ADC键盘),显示发送、接收到的键值。
    
    ******************************************/
    
    #define MAIN_Fosc		22118400L	//定义主时钟
    
    #include	"STC15Fxxxx.H"
    
    sbit	P_IR_TX   = P3^7;	//定义红外发送脚
    
    /****************************** 用户定义宏 ***********************************/
    
    #define	SysTick 14225	// 次/秒, 系统滴答频率, 在4000~16000之间
    
    /***********************************************************/
    
    #define DIS_DOT		0x20
    #define DIS_BLACK	0x10
    #define DIS_		0x11
    
    
    
    /****************************** 自动定义宏 ***********************************/
    
    #define	Timer0_Reload	(65536UL - ((MAIN_Fosc + SysTick/2) / SysTick))		//Timer 0 中断频率, 在config.h中指定系统滴答频率, 例程为14225.
    
    /*****************************************************************************/
    
    
    
    
    
    /*************	本地常量声明	**************/
    /*************	本地常量声明	**************/
    // 官方原版demo, 给的共阴极数码管值是对的
    // 我板子HC595连接数码管的A,B脚错了
    // 将正确的注释掉, 再按错误的连接, 重新给数码管赋值
    //u8 code t_display[]={						//标准字库
    	 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    //	0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
    black	 -     H    J	 K	  L	   N	o   P	 U     t    G    Q    r   M    y
    //	0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    //	0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};	//0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
    
    /*
    // 数码管的管脚排列
      A
    F   B
      B
    E   C
      D   DP
    */
    	u8 code t_display[] = 
    	{ // 标准字库           
    		//                    P G F E D C B A    数码管引脚在数据字节中的位置       
    		0x3F /*0*/, // 0x3f = 0 0 1 1,1 1 1 1 => AB互换 => 0 0 1 1,1 1 1 1 = 0x3f
    		0x05 /*1*/, // 0x06 = 0 0 0 0,0 1 1 0 => AB互换 => 0 0 0 0,0 1 0 1 = 0x05
    		0x5B /*2*/, // 0x5B = 0 1 0 1,1 0 1 1 => AB互换 => 0 1 0 1,1 0 1 1 = 0x5B
    		0x4F /*3*/, // 0x4F = 0 1 0 0,1 1 1 1 => AB互换 => 0 1 0 0,1 1 1 1 = 0x4F
    		0x65 /*4*/, // 0x66 = 0 1 1 0,0 1 1 0 => AB互换 => 0 1 1 0,0 1 0 1 = 0x65
    		0x6E /*5*/, // 0x6D = 0 1 1 0,1 1 0 1 => AB互换 => 0 1 1 0,1 1 1 0 = 0x6E
    		0x7E /*6*/, // 0x7D = 0 1 1 1,1 1 0 1 => AB互换 => 0 1 1 1,1 1 1 0 = 0x7E
    		0x07 /*7*/, // 0x07 = 0 0 0 0,0 1 1 1 => AB互换 => 0 0 0 0,0 1 1 1 = 0x07
    		0x7F /*8*/, // 0x7F = 0 1 1 1,1 1 1 1 => AB互换 => 0 1 1 1,1 1 1 1 = 0x7F
    		0x6F /*9*/, // 0x6F = 0 1 1 0,1 1 1 1 => AB互换 => 0 1 1 0,1 1 1 1 = 0x6F
    		0x77 /*A*/, // 0x77 = 0 1 1 1,1 1 1 1 => AB互换 => 0 1 1 1,1 1 1 1 = 0x77
    		0x7C /*b*/, // 0x7C = 0 1 1 1,1 1 0 0 => AB互换 => 0 1 1 1,1 1 0 0 = 0x7C
    		0x3A /*C*/, // 0x39 = 0 0 1 1,1 0 0 1 => AB互换 => 0 0 1 1,1 0 1 0 = 0x3A
    		0x5D /*d*/, // 0x5E = 0 1 0 1,1 1 1 0 => AB互换 => 0 1 0 1,1 1 0 1 = 0x5D
    		0x7A /*E*/, // 0x79 = 0 1 1 1,1 0 0 1 => AB互换 => 0 1 1 1,1 0 1 0 = 0x7A
    		0x72 /*F*/, // 0x71 = 0 1 1 1,0 0 0 1 => AB互换 => 0 1 1 1,0 0 1 0 = 0x72
            	 	  	   	   	                         
    		0x00 /* */, // 0x00 = 0 0 0 0,0 0 0 0 => AB互换 => 0 0 0 0,0 0 0 0 = 0x00
    		0x40 /*-*/, // 0x40 = 0 1 0 0,0 0 0 0 => AB互换 => 0 1 0 0,0 0 0 0 = 0x40
    		0x58 /*c*/, // 0x58 = 0 1 0 1,1 0 0 0 => AB互换 => 0 1 0 1,1 0 0 0 = 0x7A
    		0x7B /*e*/, // 0x7B = 0 1 1 1,1 0 1 1 => AB互换 => 0 1 1 1,1 0 1 1 = 0x7B
    		// 表示不了'G'
    		0x75 /*H*/, // 0x76 = 0 1 1 1,0 1 1 0 => AB互换 => 0 1 1 1,0 1 0 1 = 0x75
    		0x74 /*h*/, // 0x74 = 0 1 1 1,0 1 0 0 => AB互换 => 0 1 1 1,0 1 0 0 = 0x74
    		0x1D /*J*/, // 0x1E = 0 0 0 1,1 1 1 0 => AB互换 => 0 0 0 1,1 1 0 1 = 0x1D
    		0x70 /*k*/, // 0x70 = 0 1 1 1,0 0 0 0 => AB互换 => 0 1 1 1,0 0 0 0 = 0x70
    		0x38 /*L*/, // 0x38 = 0 0 1 1,1 0 0 0 => AB互换 => 0 0 1 1,1 0 0 0 = 0x38
    		// 表示不了 'M' or 'm'
    		0x37 /*N*/, // 0x37 = 0 0 1 1,0 1 1 1 => AB互换 => 0 0 1 1,0 1 1 1 = 0x37
    		0x54 /*n*/, // 0x54 = 0 1 0 1,0 1 0 0 => AB互换 => 0 1 0 1,0 1 0 0 = 0x54
    		0x5C /*o*/, // 0x5C = 0 1 0 1,1 1 0 0 => AB互换 => 0 1 0 1,1 1 0 0 = 0x5C
    		0x73 /*P*/, // 0x73 = 0 1 1 1,0 0 1 1 => AB互换 => 0 1 1 1,0 0 1 1 = 0x73
    		0x67 /*q*/, // 0x67 = 0 1 1 0,0 1 1 1 => AB互换 => 0 1 1 0,0 1 1 1 = 0x67
    		0x50 /*r*/, // 0x50 = 0 1 0 1,0 0 0 0 => AB互换 => 0 1 0 1,0 0 0 0 = 0x50
    		// 表示不了 'S' or 's'
    		0x78 /*t*/, // 0x78 = 0 1 1 1,1 0 0 0 => AB互换 => 0 1 1 1,1 0 0 0 = 0x78
    		0x3D /*U*/, // 0x3E = 0 0 1 1,1 1 1 0 => AB互换 => 0 0 1 1,1 1 0 1 = 0x3D
    		0x6D /*y*/, // 0x6e = 0 1 1 0,1 1 1 0 => AB互换 => 0 1 1 0,1 1 0 1 = 0x6D
    		
    		0xBF /*0.*/, // 0xBF = 1 0 1 1,1 1 1 1 => AB互换 => 1 0 1 1,1 1 1 1 = 0xBF
    		0x85 /*1.*/, // 0x86 = 1 0 0 0,0 1 1 0 => AB互换 => 1 0 0 0,0 1 0 1 = 0x85
    		0xDB /*2.*/, // 0xDB = 1 1 0 1,1 0 1 1 => AB互换 => 1 1 0 1,1 0 1 1 = 0xDB
    		0xCF /*3.*/, // 0xCF = 1 1 0 0,1 1 1 1 => AB互换 => 1 1 0 0,1 1 1 1 = 0xCF
    		0xE5 /*4.*/, // 0xE6 = 1 1 1 0,0 1 1 0 => AB互换 => 1 1 1 0,0 1 0 1 = 0xE5
    		0xEE /*5.*/, // 0xED = 1 1 1 0,1 1 0 1 => AB互换 => 1 1 1 0,1 1 1 0 = 0xEE
    		0xFE /*6.*/, // 0xFD = 1 1 1 1,1 1 0 1 => AB互换 => 1 1 1 1,1 1 1 0 = 0xFE
    		0x87 /*7.*/, // 0x87 = 1 0 0 0,0 1 1 1 => AB互换 => 1 0 0 0,0 1 1 1 = 0x87
    		0xFF /*8.*/, // 0xFF = 1 1 1 1,1 1 1 1 => AB互换 => 1 1 1 1,1 1 1 1 = 0xFF
    		0xEF /*9.*/, // 0xEF = 1 1 1 0,1 1 1 1 => AB互换 => 1 1 1 0,1 1 1 1 = 0xEF
    		0x45 /*-1*/  // 0x46 = 0 1 0 0,0 1 1 0 => AB互换 => 0 1 0 0,0 1 0 1 = 0x45
    	};
    
    u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};		//位码
    
    
    /*************	IO口定义	**************/
    sbit	P_HC595_SER   = P4^0;	//pin 14	SER		data input
    sbit	P_HC595_RCLK  = P5^4;	//pin 12	RCLk	store (latch) clock
    sbit	P_HC595_SRCLK = P4^3;	//pin 11	SRCLK	Shift data clock
    
    /*************	本地变量声明	**************/
    
    u8 	LED8[8];		//显示缓冲
    u8	display_index;	//显示位索引
    bit	B_1ms;			//1ms标志
    
    u8	cnt_1ms;		//1ms基本计时
    
    
    u8	IO_KeyState, IO_KeyState1, IO_KeyHoldCnt;	//行列键盘变量
    u8	KeyHoldCnt;	//键按下计时
    u8	KeyCode;	//给用户使用的键码, 1~16有效
    u8	cnt_27ms;
    
    u16		PCA_Timer2;
    
    
    
    /*************	红外发送程序变量声明	**************/
    u8	IR_TxIndex;			//发送步骤索引, 用户把数据准备好, 用 IR_TxIndex = 1; 来启动,之后程序自动发送完成
    u8	IR_TxData[5];		//发送数据, IR_TxData[0] -- 用户码低字节, IR_TxData[1] -- 用户码高字节, 
    						//			IR_TxData[2] -- 用户数据字节, IR_TxData[3] -- 数据字节反码,  IR_TxData[4]留空.
    
    u8	IR_Tx_Tick;			//(系统使用,用户不可操作) 发送时隙, 做0.5625ms延时计数
    u8	IR_TxPulseTime;		//(系统使用,用户不可操作) 发送38KHZ时间
    u8	IR_TxSpaceTime;		//(系统使用,用户不可操作) 发送空格时间
    u8	IR_TxTmp;			//(系统使用,用户不可操作) 发送缓冲
    u8	IR_TxBitCnt;		//(系统使用,用户不可操作) 发送bit计数
    u8	IR_TxFrameTime;		//(系统使用,用户不可操作) 帧时间, 108ms
    bit	B_StopCR;			//(系统使用,用户不可操作) 停止PCA
    bit	B_Space;			//发送空闲(延时)标志
    u16	tx_cnt;				//发送或空闲的脉冲计数(等于38KHZ的脉冲数,对应时间), 红外频率为38KHZ, 周期26.3us
    
    /*************	红外接收程序变量声明	**************/
    sbit	P_IR_RX	= P3^6;			//定义红外接收输入IO口
    
    u8	IR_SampleCnt;		//采样计数
    u8	IR_BitCnt;			//编码位数
    u8	IR_UserH;			//用户码(地址)高字节
    u8	IR_UserL;			//用户码(地址)低字节
    u8	IR_data;			//数据原码
    u8	IR_DataShit;		//数据移位
    
    bit	P_IR_RX_temp;		//Last sample
    bit	B_IR_Sync;			//已收到同步标志
    bit	B_IR_Press;			//安键动作发生
    u8	IR_code;			//红外键码
    u16	UserCode;			//用户码
    
    /*********************************/
    
    /*************	本地函数声明	**************/
    void	IO_KeyScan(void);
    void	PCA_config(void);
    
    
    
    /********************** 主函数 ************************/
    void main(void)
    {
    	u8	i;
    	
    	P0M1 = 0;	P0M0 = 0;	//设置为准双向口
    	P1M1 = 0;	P1M0 = 0;	//设置为准双向口
    	P2M1 = 0;	P2M0 = 0;	//设置为准双向口
    	P3M1 = 0;	P3M0 = 0;	//设置为准双向口
    	P4M1 = 0;	P4M0 = 0;	//设置为准双向口
    	P5M1 = 0;	P5M0 = 0;	//设置为准双向口
    	P6M1 = 0;	P6M0 = 0;	//设置为准双向口
    	P7M1 = 0;	P7M0 = 0;	//设置为准双向口
    
    	display_index = 0;
    
    	AUXR = 0x80;	//Timer0 set as 1T, 16 bits timer auto-reload, 
    	TH0 = (u8)(Timer0_Reload / 256);
    	TL0 = (u8)(Timer0_Reload % 256);
    	ET0 = 1;	//Timer0 interrupt enable
    	TR0 = 1;	//Tiner0 run
    	EA = 1;		//打开总中断
    	
    	B_StopCR = 0;
    	PCA_config();
    	
    	
    	for(i=0; i<8; i++)	LED8[i] = DIS_;	//上电显示-
    	LED8[4] = DIS_BLACK;
    	LED8[5] = DIS_BLACK;
    
    	while(1)
    	{
    		if(B_1ms)	//1ms到
    		{
    			B_1ms = 0;
    			
    			if(++cnt_27ms >= 27)
    			{
    				cnt_27ms = 0;
    				IO_KeyScan();
    
    				if(KeyCode > 0)		//检测到收到红外键码
    				{
    					IR_TxData[0] = 0x00;		//IR_TxData[0] -- 用户码低字节
    					IR_TxData[1] = 0xFF;		//IR_TxData[1] -- 用户码高字节
    					IR_TxData[2] = KeyCode;		//IR_TxData[2] -- 用户数据字节
    					IR_TxData[3] = ~KeyCode;	//IR_TxData[3] -- 数据字节反码
    					IR_TxIndex = 1;				//启动,之后程序自动发送完成
    					
    					// 就加下面2句, 将按键发送的红外键值显示到第5个,第6个数码管上
    					LED8[4] = KeyCode >> 4;
    					LED8[5] = KeyCode & 0x0f;
    					
    					KeyCode = 0;
    				}
    			}
    
    			if(B_IR_Press)		//检测到收到红外键码
    			{
    				B_IR_Press = 0;
    				
    				LED8[0] = (u8)((UserCode >> 12) & 0x0f);	//用户码高字节的高半字节
    				LED8[1] = (u8)((UserCode >> 8)  & 0x0f);	//用户码高字节的低半字节
    				LED8[2] = (u8)((UserCode >> 4)  & 0x0f);	//用户码低字节的高半字节
    				LED8[3] = (u8)(UserCode & 0x0f);			//用户码低字节的低半字节
    				LED8[6] = IR_code >> 4;
    				LED8[7] = IR_code & 0x0f;
    			}
    		}
    	}
    } 
    /**********************************************/
    
    /*****************************************************
    	行列键扫描程序
    	使用XY查找4x4键的方法,只能单键,速度快
    
       Y     P04      P05      P06      P07
              |        |        |        |
    X         |        |        |        |
    P00 ---- K00 ---- K01 ---- K02 ---- K03 ----
              |        |        |        |
    P01 ---- K04 ---- K05 ---- K06 ---- K07 ----
              |        |        |        |
    P02 ---- K08 ---- K09 ---- K10 ---- K11 ----
              |        |        |        |
    P03 ---- K12 ---- K13 ---- K14 ---- K15 ----
              |        |        |        |
    ******************************************************/
    
    
    u8 code T_KeyTable[16] = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};
    
    void IO_KeyDelay(void)
    {
    	u8 i;
    	i = 60;
    	while(--i)	;
    }
    
    void	IO_KeyScan(void)	//50ms call
    {
    	u8	j;
    
    	j = IO_KeyState1;	//保存上一次状态
    
    	P0 = 0xf0;	//X低,读Y
    	IO_KeyDelay();
    	IO_KeyState1 = P0 & 0xf0;
    
    	P0 = 0x0f;	//Y低,读X
    	IO_KeyDelay();
    	IO_KeyState1 |= (P0 & 0x0f);
    	IO_KeyState1 ^= 0xff;	//取反
    	
    	if(j == IO_KeyState1)	//连续两次读相等
    	{
    		j = IO_KeyState;
    		IO_KeyState = IO_KeyState1;
    		if(IO_KeyState != 0)	//有键按下
    		{
    			F0 = 0;
    			if(j == 0)	F0 = 1;	//第一次按下
    			else if(j == IO_KeyState)
    			{
    				if(++IO_KeyHoldCnt >= 37)	//1秒后重键
    				{
    					IO_KeyHoldCnt = 33;		//108ms repeat
    					F0 = 1;
    				}
    			}
    			if(F0)
    			{
    				j = T_KeyTable[IO_KeyState >> 4];
    				if((j != 0) && (T_KeyTable[IO_KeyState& 0x0f] != 0)) 
    					KeyCode = (j - 1) * 4 + T_KeyTable[IO_KeyState & 0x0f] + 16;	//计算键码,17~32
    			}
    		}
    		else	IO_KeyHoldCnt = 0;
    	}
    	P0 = 0xff;
    }
    
    
    
    
    
    /**************** 向HC595发送一个字节函数 ******************/
    void Send_595(u8 dat)
    {		
    	u8	i;
    	for(i=0; i<8; i++)
    	{
    		dat <<= 1;
    		P_HC595_SER   = CY;
    		P_HC595_SRCLK = 1;
    		P_HC595_SRCLK = 0;
    	}
    }
    
    /********************** 显示扫描函数 ************************/
    void DisplayScan(void)
    {	
    	Send_595(~T_COM[display_index]);				//输出位码
    	Send_595(t_display[LED8[display_index]]);	//输出段码
    
    	P_HC595_RCLK = 1;
    	P_HC595_RCLK = 0;							//锁存输出数据
    	if(++display_index >= 8)	display_index = 0;	//8位结束回0
    }
    
    
    //*******************************************************************
    //*********************** IR Remote Module **************************
    //*********************** By 梁深 (Coody) 2002-8-24 *****************
    //*********************** IR Remote Module **************************
    //this programme is used for Receive IR Remote (NEC Code).
    
    //data format: Synchro, AddressH, AddressL, data, /data, (total 32 bit).
    
    //send a frame(85ms), pause 23ms, send synchro of continue frame, pause 94ms
    
    //data rate: 108ms/Frame
    
    
    //Synchro: low=9ms, high=4.5 / 2.25ms, low=0.5626ms
    //Bit0: high=0.5626ms, low=0.5626ms
    //Bit1: high=1.6879ms, low=0.5626ms
    //frame rate = 108ms ( pause 23 ms or 96 ms)
    
    /******************** 红外采样时间宏定义, 用户不要随意修改	*******************/
    
    #define IR_SAMPLE_TIME		(1000000UL/SysTick)			//查询时间间隔, us, 红外接收要求在60us~250us之间
    #if ((IR_SAMPLE_TIME <= 250) && (IR_SAMPLE_TIME >= 60))
    	#define	D_IR_sample			IR_SAMPLE_TIME		//定义采样时间,在60us~250us之间
    #endif
    
    #define D_IR_SYNC_MAX		(15000/D_IR_sample)	//SYNC max time
    #define D_IR_SYNC_MIN		(9700 /D_IR_sample)	//SYNC min time
    #define D_IR_SYNC_DIVIDE	(12375/D_IR_sample)	//decide data 0 or 1
    #define D_IR_DATA_MAX		(3000 /D_IR_sample)	//data max time
    #define D_IR_DATA_MIN		(600  /D_IR_sample)	//data min time
    #define D_IR_DATA_DIVIDE	(1687 /D_IR_sample)	//decide data 0 or 1
    #define D_IR_BIT_NUMBER		32					//bit number
    
    //*******************************************************************************************
    //**************************** IR RECEIVE MODULE ********************************************
    
    void IR_RX_NEC(void)
    {
    	u8	SampleTime;
    
    	IR_SampleCnt++;							//Sample + 1
    
    	F0 = P_IR_RX_temp;						//Save Last sample status
    	P_IR_RX_temp = P_IR_RX;					//Read current status
    	if(F0 && !P_IR_RX_temp)					//Pre-sample is high,and current sample is low, so is fall edge
    	{
    		SampleTime = IR_SampleCnt;			//get the sample time
    		IR_SampleCnt = 0;					//Clear the sample counter
    
    			 if(SampleTime > D_IR_SYNC_MAX)		B_IR_Sync = 0;	//large the Maxim SYNC time, then error
    		else if(SampleTime >= D_IR_SYNC_MIN)					//SYNC
    		{
    			if(SampleTime >= D_IR_SYNC_DIVIDE)
    			{
    				B_IR_Sync = 1;					//has received SYNC
    				IR_BitCnt = D_IR_BIT_NUMBER;	//Load bit number
    			}
    		}
    		else if(B_IR_Sync)						//has received SYNC
    		{
    			if(SampleTime > D_IR_DATA_MAX)		B_IR_Sync=0;	//data samlpe time too large
    			else
    			{
    				IR_DataShit >>= 1;					//data shift right 1 bit
    				if(SampleTime >= D_IR_DATA_DIVIDE)	IR_DataShit |= 0x80;	//devide data 0 or 1
    				if(--IR_BitCnt == 0)				//bit number is over?
    				{
    					B_IR_Sync = 0;					//Clear SYNC
    					if(~IR_DataShit == IR_data)		//判断数据正反码
    					{
    						UserCode = ((u16)IR_UserH << 8) + IR_UserL;
    						IR_code      = IR_data;
    						B_IR_Press   = 1;			//数据有效
    					}
    				}
    				else if((IR_BitCnt & 7)== 0)		//one byte receive
    				{
    					IR_UserL = IR_UserH;			//Save the User code high byte
    					IR_UserH = IR_data;				//Save the User code low byte
    					IR_data  = IR_DataShit;			//Save the IR data byte
    				}
    			}
    		}
    	}
    }
    
    
    /********************** Timer0 1ms中断函数 ************************/
    void timer0 (void) interrupt TIMER0_VECTOR
    {
    	IR_RX_NEC();
    
    	if(IR_TxIndex > 0)	//有发送任务, 用户把数据准备好, 用 IR_TxIndex = 1; 来启动,之后程序自动发送完成
    	{
    		if(++IR_Tx_Tick >= 8)	//8*70.3=562.4us, 接近标准的 256 / 0.455 = 562.6us, 一般遥控器使用455K晶体(0.455MHZ)
    		{
    			IR_Tx_Tick = 0;
    			if(IR_TxPulseTime > 0)	//发送时间未完
    			{
    				if(--IR_TxPulseTime == 0)
    				{
    					B_StopCR = 1;
    				}
    			}
    			else if(IR_TxSpaceTime > 0)	IR_TxSpaceTime--;	//空格时间未完
    		
    			if((IR_TxPulseTime | IR_TxSpaceTime) == 0)		//一个脉冲发完了
    			{
    				if(IR_TxIndex == 1)		//刚开始, 发送数据同步头, IR_TxPulseTime = 9ms, IR_TxSpaceTime = 4.5ms
    				{
    					CL = 0;
    					CH = 0;
    					PCA_Timer2 = 10;
    					CCAP2L = 10;			//将影射寄存器写入捕获寄存器,先写CCAP0L
    					CCAP2H = 0;	//后写CCAP0H
    					CR = 1;
    
    					IR_TxPulseTime = 16;	//16*0.5625 = 9ms
    					IR_TxSpaceTime = 8;		// 8*0.5625 = 4.5ms
    					IR_TxIndex = 2;
    					IR_TxTmp = IR_TxData[0];	//取第一个数据
    					IR_TxBitCnt = 0;
    				}
    				else if(IR_TxIndex == 2)	//发送数据, 0为IR_TxPulseTime = 0.5625ms, IR_TxSpaceTime = 0.5625ms
    				{							//发送数据, 1为IR_TxPulseTime = 0.5625ms, IR_TxSpaceTime = 1.6875ms
    					CL = 0;
    					CH = 0;
    					PCA_Timer2 = 10;
    					CCAP2L = 10;			//将影射寄存器写入捕获寄存器,先写CCAP0L
    					CCAP2H = 0;	//后写CCAP0H
    					CR = 1;
    					
    					IR_TxPulseTime = 1;
    					if(IR_TxTmp & 1)	IR_TxSpaceTime = 3;	//数据1对应 1.6875 + 0.5625 ms 
    					else				IR_TxSpaceTime = 1;	//数据0对应 0.5625 + 0.5625 ms
    					IR_TxTmp >>= 1;
    					if(++IR_TxBitCnt >= 33)		//4个字节发送完成
    					{
    						IR_TxIndex = 3;			//下一步就结束了
    					}
    					else if((IR_TxBitCnt & 7) == 0)	IR_TxTmp = IR_TxData[IR_TxBitCnt >> 3];	//发完一个字节, 取一个数
    				}
    				else if(IR_TxIndex == 3)	IR_TxIndex = 0;	//发送完成了
    			}
    		}
    	}
    	
    	if(--cnt_1ms == 0)
    	{
    		cnt_1ms = SysTick / 1000;
    		B_1ms = 1;		//1ms标志
    		DisplayScan();	//1ms扫描显示一位
    	}
    }
    
    
    //========================================================================
    // 函数: void	PCA_config(void)
    // 描述: PCA配置函数.
    // 参数: None
    // 返回: none.
    // 版本: V1.0, 2012-11-22
    //========================================================================
    void	PCA_config(void)
    {
    	//  PCA0初始化
    	AUXR1   = (AUXR1 & ~0x30) | 0x10;	//切换IO口, 0x00: P1.2 P1.1 P1.0 P3.7,  0x10: P3.4 P3.5 P3.6 P3.7, 0x20: P2.4 P2.5 P2.6 P2.7
    
    	CCAPM2  = 0x48;	//工作模式 0x00: PCA_Mode_Capture,  0x42: PCA_Mode_PWM,  0x48: PCA_Mode_SoftTimer
    	CCAPM2 |= 0x04;	//允许高速取反输出, 一般用在16位软件定时器
    	CCAPM2 |= 0x01;	//允许中断
    //	PCA_PWM2  = (PCA_PWM2 & ~0xc0) | 0x00;	//PWM宽度, 0x00: 8bit, 0x40: 7bit,  0x80: 6bit
    	PCA_Timer2 = 100;	//随便给一个小的初值
    	CCAP2L = (u8)PCA_Timer2;			//将影射寄存器写入捕获寄存器,先写CCAP0L
    	CCAP2H = (u8)(PCA_Timer2 >> 8);	//后写CCAP0H
    
    	PPCA = 1;	//高优先级中断
    	CMOD  = (CMOD  & ~0xe0) | 0x08;	//选择时钟源, 0x00: 12T, 0x02: 2T, 0x04: Timer0溢出, 0x06: ECI, 0x08: 1T, 0x0A: 4T, 0x0C: 6T, 0x0E: 8T
    	CH = 0;
    	CL = 0;
    	CR = 0;
    	P37 = 1;	//停止发射
    }
    
    //========================================================================
    // 函数: void	PCA_Handler (void) interrupt PCA_VECTOR
    // 描述: PCA中断处理程序.
    // 参数: None
    // 返回: none.
    // 版本: V1.0, 2012-11-22
    //========================================================================
    
    #define	D_38K_DUTY	((MAIN_Fosc * 26) / 1000000UL + MAIN_Fosc / 3000000UL)	/* 	38KHZ周期时间	26.3us */
    #define	D_38K_OFF	((MAIN_Fosc * 17) / 1000000UL + MAIN_Fosc / 3000000UL)	/* 发射管关闭时间	17.3us */
    #define	D_38K_ON	((MAIN_Fosc * 9) / 1000000UL)							/* 发射管导通时间	9us */
    
    void	PCA_Handler (void) interrupt PCA_VECTOR
    {
    	CCON = 0x40;	//清除所有中断标志,但不关CR
    	if(P_IR_TX)		PCA_Timer2 += D_38K_OFF;	//装载高电平时间	17.3us
    	else			PCA_Timer2 += D_38K_ON;	//装载低电平时间	9us
    	CCAP2L = (u8)PCA_Timer2;			//将影射寄存器写入捕获寄存器,先写CCAP0L
    	CCAP2H = (u8)(PCA_Timer2 >> 8);	//后写CCAP0H
    	if(B_StopCR)
    	{
    		CR = 0;
    		B_StopCR = 0;
    		P_IR_TX = 1;
    	}
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584

    END

  • 相关阅读:
    Java程序员学习资料分享,等你来收藏!
    腾讯云部署K8s集群
    瀑布流布局
    63基于matlab的生物地理的优化器(BBO)被用作多层感知器(MLP)的训练器。
    Leadshop开源商城小程序源码 – 支持公众号H5
    使用ION-SFU和媒体设备在Golang中构建一个WebRTC视频和音频广播器
    Git01下载安装+与SVN的区别+实操
    基于复旦微的FMQL45T900全国产化ARM核心模块(100%国产化)
    调试器通用波形显示工具
    校验 GPT-4 真实性的三个经典问题:快速区分 GPT-3.5 与 GPT-4,并提供免费测试网站
  • 原文地址:https://blog.csdn.net/LostSpeed/article/details/127453412