研究学习
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
代码是用的VS Code编辑器
单片机源程序如下:
- //elecfun 2018-04-01 01:22:17
- #include <STC12C2052AD.h>
- #include <intrins.h>
- #include "IRNEC.h"
- unsigned char IR_KEY[6][3] = {0xFF};
- sbit KEY_SET = P3^7;
- #define _DEBUG
- #ifdef _DEBUG
- unsigned char code ITC[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- //12mhz 4800bps
- void UART_init(void)
- {
- PCON |= 0x80; //波特率不倍速
- SCON = 0x50; //8位数据,可变波特率
- TMOD &= 0x0F;
- TMOD |= 0x20;
- TL1 = TH1 = 0xF3;
- ET1 = 0;
- TR1 = 1;
- }
- void SendChar(unsigned char dat)
- {
- SBUF = dat;
- while (!TI);
- TI = 0;
- }
- void SendString(unsigned char *s)
- {
- while (*s) //Check the end of the string
- {
- SendChar(*s++); //Send current char and increment string ptr
- }
- }
- #endif
- /********************读字节函数*********************/
- unsigned char Byte_Read(unsigned int add)
- {
- ISP_DATA = 0x00;//清空数据
- ISP_CONTR = 0x83;//打开ISP,设置操作等待时间 12MHz以下0x83 30MHz以下0x80 6MHz以下0x84
- ISP_CMD = 0x01;//字节读命令
- ISP_ADDRH = add>>8;//设置高8位地址
- ISP_ADDRL = add&0x00ff;//设置低8位地址
- ISP_TRIG = 0x46;//发送46h到触发寄存器
- ISP_TRIG = 0xb9;//发送b9h到触发寄存器
- _nop_();//延时
- ISP_CONTR = 0;//关闭IAP 功能
- ISP_CMD = 0;//清空命令寄存器
- ISP_TRIG = 0;//清空命令触发寄存器
- ISP_ADDRH = 0;//清空地址高位
- ISP_ADDRL = 0;//清空地址低位
- return (ISP_DATA);//返回读到的数据
- }
- /*******************字节编程函数********************/
- void Byte_Program(unsigned int add, unsigned char dat)
- {
- ISP_CONTR = 0x83;//打开ISP,设置操作等待时间
- ISP_CMD = 0x02;//字节编程命令
- ISP_ADDRH = add>>8;//设置高8位地址
- ISP_ADDRL = add&0x00ff;//设置低8位地址
- ISP_DATA = dat;//要编程的数据先送进ISP_DATA 寄存器
- ISP_TRIG = 0x46;//发送46h到触发寄存器
- ISP_TRIG = 0xb9;//发送b9h到触发寄存器
- _nop_();//延时
- ISP_CONTR = 0;//关闭IAP 功能
- ISP_CMD = 0;//清空命令寄存器
- ISP_TRIG = 0;//清空命令触发寄存器
- ISP_ADDRH = 0;//清空地址高位
- ISP_ADDRL = 0;//清空地址低位
- }
- /********************扇区擦除函数**********************/
- void Sector_Erase(unsigned int add)
- {
- ISP_CONTR = 0x83;//打开ISP,设置操作等待时间
- ISP_CMD = 0x03;//扇区擦除命令
- ISP_ADDRH = add>>8;//设置高8位地址
- ISP_ADDRL = add&0x00ff;//设置低8位地址
- ISP_TRIG = 0x46;//发送46h到触发寄存器
- ISP_TRIG = 0xb9;//发送b9h到触发寄存器
- _nop_();//延时
- ISP_CONTR = 0;//关闭IAP 功能
- ISP_CMD = 0;//清空命令寄存器
- ISP_TRIG = 0;//清空命令触发寄存器
- ISP_ADDRH = 0;//清空地址高位
- ISP_ADDRL = 0;//清空地址低位
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函数:红外线解码初始化
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void IR_Init()
- {
- TMOD &= 0xF0; //清定时器0
- TMOD |= 0x01; //定时器0:16位定时器
- TL0 = TH_L; //每步时间
- TH0 = TH_H;
- ET0 = 1;
- EA = 1;
- TR0 = 1;
- }
- void Delayms(unsigned int dT)
- {
- unsigned int dA,dB;
- for(dA=0; dA<dT; dA++)
- for(dB=0; dB<113; dB++)
- ;
- }
- //从内部EEPROM中读取键值数据
- void ReadIRData(void)
- {
- unsigned char j;
- for (j=0; j<6; j++)
- {
- IR_KEY[j][0] = Byte_Read(3 * j);
- IR_KEY[j][1] = Byte_Read(3 * j + 1);
- IR_KEY[j][2] = Byte_Read(3 * j + 2);
- }
- }
- //键值保存到内部EEPROM中
- void WriteIRData(void)
- {
- unsigned char j;
- Sector_Erase(0);
- for (j=0; j<6; j++)
- {
- Byte_Program(3 * j, IR_KEY[j][0]);
- Byte_Program(3 * j + 1, IR_KEY[j][1]);
- Byte_Program(3 * j + 2, IR_KEY[j][2]);
- }
- }
- void main(void)
- {
- unsigned char j;
- unsigned char curCh = 0;
- #ifdef _DEBUG
- UART_init();
- Delayms(500);
- SendString("start");
- #endif
- ReadIRData(); //读EEPROM数据
- IR_Init(); //红外接收初始化
- while (1)
- {
- #ifdef _DEBUG
- P30 = 1;
- if (!P30)
- {
- ISP_CONTR = 0x60;
- }
- #endif
- if (IR_BT > 0) //正确解码
- {
- SendString("R:");
- SendChar(ITC[NEC[2]>>4]);
- SendChar(ITC[NEC[2]&0x0F]);
- if (!KEY_SET) //设置按键按下
- {
- if (curCh < 6) //6个通道,超过后丢弃
- {
- IR_KEY[curCh][0] = NEC[0]; //用户码高8位
- IR_KEY[curCh][1] = NEC[1]; //用户码低8位
- IR_KEY[curCh][2] = NEC[2]; //键值
- curCh++; //下一通道
- }
- } else { //设置按键未按下或刚松开
- if (curCh > 0) //通道值大于0说明刚才进行了设置,需要保存键值
- {
- curCh = 0; //清空通道值
- WriteIRData(); //保存键值
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码 代码要用vs code打开
所有资料51hei附件下载:
仿真程序.7z
(66.89 KB, 下载次数: 57)
|