| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> 51单片机用红外遥控变频空调的程序,带时钟走时DS1302,温度DS18B20带CRC,湿度HTU31D的I2C带CRC,电路图和二千行源代码全公开 -> 正文阅读 |
|
[嵌入式]51单片机用红外遥控变频空调的程序,带时钟走时DS1302,温度DS18B20带CRC,湿度HTU31D的I2C带CRC,电路图和二千行源代码全公开 |
2022.9 STC51单片机STC12C5A60S2,KEIL C,改了十多年的程序,二千行了。带时钟校正,走时DS1302,温度DS18B20带CRC,湿度HTU31D的I2C带CRC。 走时有程序上校正功能,可用频率计校到1PPM以下,一年都不用调时间。以前都是调振荡电容调到1ppm以下,累。后来发现可以程序中调,方便多了。 这次目的是用红外遥控奥克斯变频空调,顺便把所有程序发布一下吧。 电路图: //====================================================/ 主文件: //STC12C5A60S2?? FLASH 60K,? SRAM 1280字节=内部RAM低128字节+高128字节+内部扩展RAM1024字节 //温度和湿度值:均按值的10倍,有符号整数 bit??? bit_T0_interrupt_prohibited=0;???? // 是否禁用T0中断中的耗时代码 #define MACRO_WXL_INTERRUPT_PROHIBITED??? bit_T0_interrupt_prohibited=1; #define MACRO_WXL_INTERRUPT_ALLOWED?????? bit_T0_interrupt_prohibited=0; #include <STC\STC12C5A60S2.H> #include <INTRINS.h> #include "DELAY_STC12_WXL.H" //温度? DS18B20 sbit DQ_DS18_OUTDOOR=P3^4; sbit DQ_DS18_INDOOR=P1^4; #include "DS18B20_wxl.h" int data i_DS18_INDOOR=240;????????? //温度值(10倍)??????? 设成24度,以免空调制冷、制热控制失误 int data i_DS18_OUTDOOR=0; bit bit_DS18_OUTDOOR_exist=0; bit bit_DS18_INDOOR_exist=0; unsigned char data? dispbuf_DS18_INDOOR[3]={17,17,17};??? //保存各个显示值?? unsigned char data? dispbuf_DS18_OUTDOOR[3]={17,17,17}; /* 数组保存显示值。 [0]存十位及百位(A,b,C等表示)或负号 (可选带点) 。???? [1]存个位(可选带点)。?? [2]存小数位 第[0]位: 100 显示 A, 110 B, 120 C ,130 D ,140 E, 150 F,然后就没有了,所以最高是159.9 第[0]位: -10 显示 A, -20 B, -30 C, -40 D ,-50 E, -60 F,然后就没有了,所以最低是-69.9 比如: 25.6℃数组为{2,5,6}??? 即 2 5 6 -5.6℃数组为{17,5,6}?? 即 - 5 6 -15.6℃数组为{10,5,6}? 即 A 5 6 -25.6℃数组为{10,5,6}? 即 B 5 6 105.6℃数组为{10,5,6}? 即 A 5 6 115.6℃数组为{11,5,6}? 即 B 5 6 */ //温度? HTU31D? I2C //HTU31D模块,芯片焊板上,温度响应慢,用于空调控制一般般,于是仍采用DS18B20来控制温度 //HTU31D和DS18B20,静态温度HTU31D高0.5度不准,动态HTU31D反应慢 int idata?? i_HTU31D_INDOOR=0;????????? //温度值(10倍) int idata?? i_HTU31D_OUTDOOR=0; unsigned char idata? dispbuf_HTU31D_INDOOR[3]={17,17,17}; ???//保存各个显示值 unsigned char idata? dispbuf_HTU31D_OUTDOOR[3]={17,17,17}; //湿度 HF3223频率、 HTU31D I2C int idata i_HF32_INDOOR=0;?????? //湿度值10倍?????? //湿度HF3223采用频率计数,这里淘汰不用了,给HTU31D用 int idata i_HF32_OUTDOOR=0; unsigned char? idata?? dispbuf_HF32_INDOOR[3]={14,5,17};??? //保存各个显示值?????? //这里没用到,赋成E5- unsigned char? idata?? dispbuf_HF32_OUTDOOR[3]={17,17,17};????? sbit SDA=P3^2; sbit SCL=P3^3; #include "I2C_HTU31D.H" //按键相关 sbit P1_0=P1^0;??? sbit P1_1=P1^1;??? sbit P1_2=P1^2;??? unsigned char? idata? uc_keycount=0;????? //用于判断 20ms内均为高电平,则是键松开 //时钟相关 volatile unsigned int?? data? tcnt=0;??? ?????? ??//计数到1秒的次数(用于时钟) unsigned char data second=0; ?????? ??????//时钟 unsigned char data minute=0; unsigned char data hour=0; unsigned long idata?? ul_time_compensate=0;????? //晶振不准,在软件中进行时间补偿,经n秒后,加一秒或减一秒。? 最好是晶振调成偏快,然后程序中就不用加秒,比较方便 //传感器检测相关 unsigned char? idata do_what=0;???????????????? //传感器检测步序 volatile unsigned int? data?? i_dowhat_interval=1800;??? //中断中,do_what的时间计数 //工作模式 unsigned char? idata? uc_display_mode=0;???????? //工作模式?? 0正常 1制冷 2制热 unsigned char? idata? uc_display_mode_pre=0; unsigned char? code? displaybuf_display_mode[3]={0, 12, 42};???? //显示0、C、H //设置模式 unsigned char? idata? g_uc_setting_mode=0; volatile? unsigned int data??? g_ui_settingmode_timeout_cnt=0;? //设置时,进行计时 unsigned char idata? g_uc_settingmode_timeout_second=0; //显示LED相关 volatile unsigned char?? data? mstcnt=0;? ????? //计数到改变显示LED位的次数 //dispcode[]是 共“阳”极数码管的 笔划数据!! unsigned char? data?? dispcode[]={????????????????????????? //强行放在data中,以加快速度 0x48, 0xFC, 0x29, 0x38, 0x9C, 0x1A, 0x0A, 0x7C, 0x08, 0x18,??? //[0]。。。9 0x0C, 0x8A, 0x4B, 0xA8, 0x0B, 0x0F,??????????????? ????????????//[10](A),11(b),12(C),13(d),14(E),15(F) 0xFF, 0xBF, 0xBF, 0xBF,??????????????????????????????????????? //[16](空),17(负号), 18, 19 0x40, 0xF4, 0x21, 0x30, 0x94, 0x12, 0x02, 0x74, 0x00, 0x10,??? //[20](带小数点的0.)。。。29 0x04, 0x82, 0x43, 0xA0, 0x03, 0x07,??????????????????????????? //[30](A.)? 。。。 35(F.) 0xF7, 0xB7, 0xB7, 0xB7,??????????????????????????????????????? //[36](空带点.),37(负号带点.), 38, 39 0xAA, 0x4C, 0x8C?????????????????????????????????????????????? //[40](小o), 41(大N), 42(H) }; /* 8个数码管?? ? 时间???? 温度 ??????? [7]左 8 8 8 8? 8 8 8 8 右[0] */ unsigned char data dispbuf[8]={17,17,17,17,17,17,17,17};? ? //dispbuf保存显示数据,[7]最左数码管 --> [0]最右数码管 unsigned char data dispbitcode[8]={1,2,4,8,16,32,64,128}; ? //即选择数码管,依次是[0]最右数码管-->[7]最左数码管,即P2.0接置1(0000 0001)、P2.1置1... unsigned char data dispbitcnt=0;?????? //选择显示哪个数码管, 0表示最右那个数码管(温度小数位),7表示最左那个数码管 //串口 unsigned char idata??? sbuf[3],? sbufnum;?? //串口数据 //DS1302 //DS1302 走时不准!? 所以从单片机走时间,DS1302只是保存一下时间 sbit DS1302_CLK=P1^5;? sbit DS1302_IO=P1^6;? sbit DS1302_RST=P1^7; #include "DS1302_wxl.h" bit bitDS1302exist=0;????? //DS1302是否存在 unsigned char idata? ds1302_BCDdata[9]={0x59,0x32,0x23, 1, 1,? 1,??? 0x13,? 0,????? 0};???? //BCD格式的数据? ??????????????? ??????????????????? //? 0???? 1??? 2? ??3? 4?? 5?????? 6???? 7????? 8 ??????????????? ??????????????????? //? 秒??? 分?? 时?? 日 月 星期几? 年?? 写保护?? 充电 ??????????????? ??????????????????? //DS1302数据按BCD格式,0x59即是表示59。 ??????????????? ??????????????????? //秒最高位0表示不停止时钟。? 小时最高位0表示按24小时制。? 0不写保护。? 0不充电。 //空调红外遥控????? //发送时,低比特位优先!!?? 先发送低bit!! sbit? P_IR = P1^3; volatile? unsigned char data? g_uc_ir_time=0;??? //中断T0中执行多少次红外IR发射 volatile? bit data??? g_b_ir_onoff=0; unsigned char idata? uc_ir_state=0;?????????? // 空调状态:? 0表示关机?? 1表示开机+制冷??? 2表示只ECO??? 3表示ECO+静音?? (风都是1档) unsigned char code?? g_uc_irdata[5][13]=??????????? //红外数据 { 0xC3, 0xAD, 0xE0, 0x0, 0x60, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x45, 0x15,???? //关机0 0xC3, 0xAD, 0xE0, 0x0, 0x60, 0x0, 0x20, 0x0, 0x0, 0x20, 0x0, 0x45, 0x35,??? //开机+制冷1 0xC3, 0xAD, 0xE0, 0x0, 0x60, 0x0, 0x20, 0x0, 0x0, 0x28, 0x0, 0x53, 0x4B,??? //ECO2 0xC3 ,0xAD ,0xE0 ,0x0 ,0x60 ,0x80 ,0x20 ,0x0 ,0x0 ,0x28 ,0x0 ,0x53 ,0xCB,?? ? //ECO+静音3 0xC3, 0xC5, 0xE0, 0x00, 0x60, 0x80, 0x20, 0x00, 0x00, 0x28, 0x00, 0x40, 0xD0//32度ECO+静音3 };?? unsigned char code?? g_uc_irdata_with_disp[5][13]=???????? //红外数据?? 加空调屏显键 { 0xC3, 0xAD, 0xE0, 0x0, 0x60, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x55, 0x25,???? //关机0 0xC3, 0xAD, 0xE0, 0x0, 0x60, 0x0, 0x20, 0x0, 0x0, 0x20, 0x0, 0x55, 0x45,?? //开机+制冷1 0xC3, 0xAD, 0xE0, 0x0, 0x60, 0x0, 0x20, 0x0, 0x0, 0x28, 0x0, 0x55, 0x4D,?? //ECO2 0xC3, 0xAD, 0xE0, 0x0, 0x60, 0x80, 0x20, 0x0, 0x0, 0x28, 0x0, 0x55, 0xCD,?? ? //ECO+静音3 0xC3, 0xC5, 0xE0, 0x00, 0x60, 0x80, 0x20, 0x00, 0x00, 0x28, 0x00, 0x55, 0xE5//32度ECO+静音3 };?? unsigned char idata? uc_ir_heat_state=0;?? // 空调加热状态:? 0表示关机?? 1表示开机+制热??? 。。。??? 待完善 unsigned char code?? g_uc_ir_heat_data[5][13]; bit idata? b_ir_key_delay=0;??????? //按键检测延时 unsigned char idata? g_uc_ir_second=0;? //按键延时检测,按秒 unsigned char idata? g_uc_ir_minute=0;????? //空调温度延时时长,按分钟?? ,比如1分钟后检测温度 unsigned char idata? g_uc_ir_minute_pre=0;? //空调温度延时检测 unsigned int idata? ui_airtemp_set=260;????? //空调制冷温度设定值 (10倍) unsigned int idata? ui_airtemp_heat_set=200;????? //空调制热温度设定值 (10倍) unsigned char idata? dispbuf_ui_airtemp_set[3]; bit idata?? b_ECO_ON=0;???????????????? //ECO开7小时检测,开7小时ECO后需要关掉ECO再开,不然会自动消掉 unsigned char idata? ECO_hour_pre=0; /// //数值转换到显示值 void? INT10_TO_dispbuf_nodot(unsigned char? *c,? int? i)??????? //c[0]存十位及百位(A,b,C等表示),c[1]存个位,c[2]存小数。? 负数:c[0]为负号或A,b,C等表示-10、-20、-30等 { ??? if( i>1599? || i<-699) return;? //大于159.9度? 小于-69.9度 ??? ??? if( i < 0 )?? ? //如果是负数 ??? { ??????? i=-i; ??????? c[0]=i/100; //最高位 ??????? i=i%100; ??????? c[1]=i/10;? //个位 ??????? c[2]=i%10;? //小数 ??????? if (c[0] == 0) c[0]=17;??? //显示负号 ??????? else c[0]+=9;?????????? //用A,b,C等表示-10、-20、-30等??????????? ??? } ??? else??? //正数 ??? { ??????? c[0]=i/100; ??????? i=i%100; ??????? c[1]=i/10; ??????? c[2]=i%10; ??? } } void? INT10_TO_dispbuf(unsigned char? *c,?? int? i)?? { ??? if( i>1599? || i<-699) return;? //大于159.9度? 小于-69.9度 ??????? ??? INT10_TO_dispbuf_nodot( c,? i); ??? ??? //显示带点 ??? if( c[2] <3) ?? ;?? ????????????????? //显示带点的数字 ??? else if( c[2] < 5 ) ??? c[0]+=20;?? ?? //显示带点的数字?? [0]是十位 ??? else if( c[2] < 8) c[1]+=20;?? ???? //显示带点的数字 ??? else? {???? c[0]+=20;? c[1]+=20;??? }???? //显示带点的数字 } void sendSBUF(unsigned char? *a, unsigned char?? num)?????? //串口发送N字节数据 { ??? unsigned char idata? i; ??? if(num==0) return; ??? TI=0; ??? for(i=0;i<num;i++) ??? { ??????? SBUF = a[i]; //输出字符 ??????? while(!TI);???? //空语句判断字符是否发完,TI=1表示发完 ??????? TI = 0;???????? //要人工清TI ??? } } void readDS1302_and_setclock() { ??? BurstRead1302(ds1302_BCDdata) ; ??? second=( (ds1302_BCDdata[0]&0x7f) >>4)*10 + (ds1302_BCDdata[0] & 0x0f); ????? //去掉最高位"时钟停止"位,再运算 ??? minute=(ds1302_BCDdata[1]>>4)*10 + (ds1302_BCDdata[1] & 0x0f); ??? hour=? ( (ds1302_BCDdata[2]&0x7f) >>4)*10 + (ds1302_BCDdata[2] & 0x0f); ????? //去掉最高位"24小时"位,再运算 } //每个小时的30分时,写入时间到DS1302中,以使DS1302时间正确?? /// void DO_WRITETODS1302_EVERY_HALF_HOUR() { ??? if(bitDS1302exist) ??? { ??????? DS1302_WriteOne(DS1302_SEC_AD, (second/10)*16+second%10 ); ??????? DS1302_WriteOne(DS1302_MIN_AD, (minute/10)*16+minute%10 ); ??????? DS1302_WriteOne(DS1302_HOUR_AD, (hour/10)*16+hour%10 );???????? ??? } } //传感器检测? / void DO_WHAT_FUNC() { ??????? unsigned char idata? uc_DS18_temp1, uc_DS18_temp2,?? uc_DS18_temp[10]; ??????? EA=0; ??????? if(i_dowhat_interval<3600) { EA=1;? return;}?? //如果间隔时间未到,则不执行 ??????? i_dowhat_interval=0;??????? //间隔时间重新计时,即每隔1秒做一次检测 ??????? EA=1; ??????? switch(do_what) ??????? { ??????????? case 0: ??????????????? // 内DS18B20测温 ??????????????? RESET_DS18_INDOOR(? ); ??????????????? SEND_TO_DS18_INDOOR( 0xCC );?? //传送数据?? 0xcc表示SKIP ROM COMMAND指令 ??????????????? SEND_TO_DS18_INDOOR( 0x44 );?? //传送数据?? 0X44? CONVERT T指令 ??????????????? ??????????????? RESET_DS18_OUTDOOR(? ); ??????????????? SEND_TO_DS18_OUTDOOR( 0xCC );?? //传送数据?? 0xcc表示SKIP ROM COMMAND指令 ??????????????? SEND_TO_DS18_OUTDOOR( 0x44 );?? //传送数据?? 0X44? CONVERT T指令 ??????????????? ??????????????? HTU31D_conversion(? 0x40? );?? //addr地址接GND是0x40,接VCC是0x41 。?? 我室内用第一次买的接GND,室外以后用接VCC的 ??? ??????????????? do_what++; ??????????????? break; ??? ??? ??????????? case 1: ??????????????? if ( HTU31D_readTRH( &i_HTU31D_INDOOR,? &i_HF32_INDOOR? ,? 0x40 )? )???? //addr地址接GND是0x40,接VCC是0x41 ??????????????? { ??????????????????????? if(? i_HTU31D_INDOOR >=1100? )? //响应值太大,说明HTU数据异常 ??????????????????????? { ??????????????????????????? i_HTU31D_INDOOR=0;????????? //设成0 ??????????????????????????? dispbuf_HTU31D_INDOOR[0]=15;??? //显示F1????? [0]是十位 ??????????????????????????? dispbuf_HTU31D_INDOOR[1]=1; ??????????????????????????? dispbuf_HTU31D_INDOOR[2]=17;??? ??????????????????????? } ??????????????????????? else ??????????????????????? { ??????????????????????????? INT10_TO_dispbuf(dispbuf_HTU31D_INDOOR, i_HTU31D_INDOOR);?????? //存到显示缓存 ??????????????????????? } ??????????????????????? ??????????????????????? if(? i_HF32_INDOOR >=1100? )?????? //响应值太大,说明HTU数据异常 ??????????????????????? { ??????????????????????????????? i_HF32_INDOOR=0;????????? //湿度设成0 ??????????????????????????????? dispbuf_HF32_INDOOR[0]=15;? //显示F6???? [0]是十位 ??????????????????????????????? dispbuf_HF32_INDOOR[1]=6; ??????????????????????????????? dispbuf_HF32_INDOOR[2]=17;????????????????????????????????? ??????????????????????? } ??????????????????????? else ??????????????????????????? INT10_TO_dispbuf_nodot(dispbuf_HF32_INDOOR, i_HF32_INDOOR);???? //存到显示缓存?? 无点 ??????????????? } ??????????????? else??????? //HTU回应错误 ??????????????? { ??????????????????????? i_HTU31D_INDOOR=0;???????? //设成0 ??????????????????????? dispbuf_HTU31D_INDOOR[0]=15;??? //显示F0???????? [0]是十位 ??????????????????????? dispbuf_HTU31D_INDOOR[1]=0; ??????????? ??????????? dispbuf_HTU31D_INDOOR[2]=17;??????????????????????????? ??????????????????????? ??????????????????????? i_HF32_INDOOR=0;???????? //湿度设成0 ??????????????????????? dispbuf_HF32_INDOOR[0]=15;? //显示F5???????? [0]是十位 ??????????????????????? dispbuf_HF32_INDOOR[1]=5; ??????????????????????? dispbuf_HF32_INDOOR[2]=17;????? ??????????????? } ??????????????????????? ??????????????? do_what++; ??????????????? break; ??? ??? ??? ??????????? case 2: ??????????????? // 内DS18B20读温 ??????????????? if( RESET_DS18_INDOOR(? ) )???? //存在DS18B20 ??????????????? { ??????????????????? bit_DS18_INDOOR_exist=1; ??????????????????? SEND_TO_DS18_INDOOR( 0xCC );?? //传送数据?? 0xcc表示SKIP ROM COMMAND指令 ??????????????????? SEND_TO_DS18_INDOOR( 0xBE );?? //传送数据?? 0XBE? READ SCRATCHPAD指令 ??????????????????? ??????????????????? //接收9字节数据 ??????????????????? for(uc_DS18_temp1=0; uc_DS18_temp1<9 ; uc_DS18_temp1++) ??????????????????????????????????? uc_DS18_temp[ uc_DS18_temp1 ]=RECEIVE_FROM_DS18_INDOOR(? );?? //读取9字节=8字节数据+1字节CRC ??????????????????? ??????????????????? if( DS18_CRC(uc_DS18_temp,9 ))?? //为0则是CRC成功 ??????????????????? { ??????????????????????? //失败 ??????????????????????? i_DS18_INDOOR=240;?????????? //设成24度,以免空调控制失误 ??????????????????????? dispbuf_DS18_INDOOR[0]=14;? //显示E1??????? [0]是十位 ??????????????????????? dispbuf_DS18_INDOOR[1]=1; ??????????????????????? dispbuf_DS18_INDOOR[2]=17;????? ??????????????????? } ??????????????????? else ??????????????????? { ??????????????????????? uc_DS18_temp1=uc_DS18_temp[0];??? // 第1字节是LSB字节 ??????????????????????? uc_DS18_temp2=uc_DS18_temp[1];??? // 第2字节是MSB字节 ??????????????????????? i_DS18_INDOOR =? DS18_TEMP_TO_SIGNED_INT10( uc_DS18_temp1, uc_DS18_temp2 ); //转成int ??????????????????????? INT10_TO_dispbuf(dispbuf_DS18_INDOOR, i_DS18_INDOOR);?????? //存到显示缓存 ??????????????????? } ??????????????? } ??????????????? else??????? //不存在DS18B20 ??????????????? { ??????????????????? bit_DS18_INDOOR_exist=0; ??????????????????? ??????????????????? i_DS18_INDOOR=240;?????????? //设成24度,以免空调控制失误 ??????????????????? dispbuf_DS18_INDOOR[0]=14;? //显示E0??????? [0]是十位 ??????????????????? dispbuf_DS18_INDOOR[1]=0; ??????????????????? dispbuf_DS18_INDOOR[2]=17;????? ??????????????? } ??????????????? ??????????????? do_what++; ??????????????? break; ??? ??????????? case 3: ??????????????? // 外DS18B20读温 ??????????????? if( RESET_DS18_OUTDOOR(? ) )??????? //存在DS18B20 ??????????????? { ??????????????????? bit_DS18_OUTDOOR_exist=1; ??????????????????? SEND_TO_DS18_OUTDOOR( 0xCC );?? //传送数据?? 0xcc表示SKIP ROM COMMAND指令 ??????????????????? SEND_TO_DS18_OUTDOOR( 0xBE );?? //传送数据?? 0XBE? READ SCRATCHPAD指令 ??????????????????? ??????????????????? //接收9字节数据 ??????????????????? for(uc_DS18_temp1=0; uc_DS18_temp1<9 ; uc_DS18_temp1++) ??????????????????????????????????? uc_DS18_temp[ uc_DS18_temp1 ]=RECEIVE_FROM_DS18_OUTDOOR(? );?? //读取9字节=8字节数据+1字节CRC ??????????????????? ??????????????????? if( DS18_CRC(uc_DS18_temp,9 ))?? //为0则是CRC成功 ??????????????????? { ??????????????????????? //失败 ??????????????????????? i_DS18_OUTDOOR=0;?????????? //设成0 ??????????????????????? dispbuf_DS18_OUTDOOR[0]=14; //显示E1??????? [0]是十位 ??????????????????????? dispbuf_DS18_OUTDOOR[1]=1; ??????????????????????? dispbuf_DS18_OUTDOOR[2]=17;???? ??????????????????? } ??????????????????? else ??????????????????? { ??????????????????????? uc_DS18_temp1=uc_DS18_temp[0];??? // 第1字节是LSB字节 ??????????????????????? uc_DS18_temp2=uc_DS18_temp[1];??? // 第2字节是MSB字节 ??????????????????????? i_DS18_OUTDOOR =? DS18_TEMP_TO_SIGNED_INT10( uc_DS18_temp1, uc_DS18_temp2 );??? //转成int ??????????????????????? INT10_TO_dispbuf(dispbuf_DS18_OUTDOOR, i_DS18_OUTDOOR);???? //存到显示缓存 ??????????????????? } ??????????????? } ??????????????? else??????? //不存在DS18B20 ??????????? ??? { ??????????????????? bit_DS18_OUTDOOR_exist=0; ??????????????????? ??????????????????? i_DS18_OUTDOOR=0;?????????? //设成0 ??????????????????? dispbuf_DS18_OUTDOOR[0]=14; //显示E0??????? [0]是十位 ??????????????????? dispbuf_DS18_OUTDOOR[1]=0; ??????????????????? dispbuf_DS18_OUTDOOR[2]=17;???? ??????????????? } ??????????????? ??????????????? do_what++; ??????????????? ??????????????? break; ??????????? case 4: ??? ??????????? if ( HTU31D_readTRH( &i_HTU31D_OUTDOOR,? &i_HF32_OUTDOOR? ,? 0x41 )? )???? //addr地址接GND是0x40,接VCC是0x41 ??????????????? { ??????????????????????? if(? i_HTU31D_OUTDOOR >=1100? )? //响应值太大,说明HTU数据异常 ??????????????????????? { ??????????????????????????? i_HTU31D_OUTDOOR=0;????????? //设成0 ??????????????????????????? dispbuf_HTU31D_OUTDOOR[0]=15;?? //显示F1????? [0]是十位 ??????????????????????????? dispbuf_HTU31D_OUTDOOR[1]=1; ??????????????????????????? dispbuf_HTU31D_OUTDOOR[2]=17;?? ??????????????????????? } ??????????????????????? else ??????????????????????? { ??????????????????????????? INT10_TO_dispbuf(dispbuf_HTU31D_OUTDOOR, i_HTU31D_OUTDOOR);???? //存到显示缓存 ??????????????????????? } ??????????????????????? ??????????????????????? if(? i_HF32_OUTDOOR >=1100? )?????? //响应值太大,说明HTU数据异常 ??????????????????????? { ??????????????????????????????? i_HF32_OUTDOOR=0;????????? //湿度设成0 ??????????????????????????????? dispbuf_HF32_OUTDOOR[0]=15; //显示F6???? [0]是十位 ??????????????????????????????? dispbuf_HF32_OUTDOOR[1]=6; ??????????????????????????????? dispbuf_HF32_OUTDOOR[2]=17;???????????????????????????????? ??????????????????????? } ??????????????????????? else ??????????????????????????? INT10_TO_dispbuf_nodot(dispbuf_HF32_OUTDOOR, i_HF32_OUTDOOR);?????? //存到显示缓存?? 无点 ??????????????? } ??????????????? else??????? //HTU回应错误 ??????????????? { ??????????????????????? i_HTU31D_OUTDOOR=0;???????? //设成0 ??????????????????????? dispbuf_HTU31D_OUTDOOR[0]=15;?? //显示F0???????? [0]是十位 ??????????????????????? dispbuf_HTU31D_OUTDOOR[1]=0; ??????????????????????? dispbuf_HTU31D_OUTDOOR[2]=17;?????????????????????????? ??????????????????????? ??????????????????????? i_HF32_OUTDOOR=0;???????? //湿度设成0 ??????????????????????? dispbuf_HF32_OUTDOOR[0]=15; //显示F5???????? [0]是十位 ??????????????????????? dispbuf_HF32_OUTDOOR[1]=5; ??????????????????????? dispbuf_HF32_OUTDOOR[2]=17;???? ??????????????? } ??????????????????????? ??????????????? do_what++; ??????????????? do_what=0;???? //回零 ??????????????? break;? ??? ??????????? default: ??????????????? do_what=0; ??????? }?????? ??? } //发送时间和温度 到串口SD记录器? 进行记录 void SENDTXTEMP() { ??? ??????? unsigned char idata a[26]; ??????? char idata? i; ??????? ??????? for (i=0;i<26;i++)? a[i]=' '; ??????? ??????? ??????? if(bitDS1302exist) ??????? { ??????????????? BurstRead1302(ds1302_BCDdata) ; ??????????????? wxl_BCDToStr(ds1302_BCDdata,? a);? //17字节 ??????? } ??????? else ??????? { ??????????????? ??????????????? a[4]=minute%10+48; ??????????????? a[3]=minute/10+48; ??????????????? a[2]=':'; ??????????????? a[1]=hour%10+48; ??????????????? a[0]=hour/10+48;??????? ??????????????? ??????? } ??????? ??????? a[17]='\t'; ??????? a[18]=0; ??????? a[19]=0; ??????? a[20]=0; ??????? ??????? INT10_TO_dispbuf_nodot(a+18, i_DS18_INDOOR ); ??????? ??????? a[18]+=48; ??????? a[19]+=48; ??????? a[21]=a[20]+48; ??????? a[20]='.'; ??????? ??????? a[22]='\t'; ??????? a[23]=uc_ir_state+'0'; ??????? ??????? a[24]=0x0D; ??????? a[25]=0x0A; ??????? ??????? sendSBUF(a, 26); } //刷新显示?????????? /// void REFRESH_DISPLAY() {?????????? ??? switch(g_uc_setting_mode) ??? { ??????? case 0:????????????? //不在设置模式 ??????????? dispbuf[4]=minute%10; ??????????? dispbuf[5]=minute/10; ??????????? dispbuf[6]=hour%10; ??????????? dispbuf[7]=hour/10; ??????????? ??????????? switch(uc_display_mode)?????? // 显示模式,? 0=2个温度2个湿度????? 1=空调控制?? 2=空调控制 ??????????? { ??????????????? case 0:???? //正常显示 ??????????????????? if(second%10==0||second%10==5)?????? //?? 在0,5。。。????? ??????????????????? { ??????????????????????? dispbuf[0]=dispbuf_DS18_INDOOR[1];??????? //显示内DS18B20的温度??????? dispbuf[0]是低位??? INDOOR[0]是十位 ??????????????????????? dispbuf[1]=dispbuf_DS18_INDOOR[0];??????? ??????????????????????? dispbuf[2]=dispbuf_DS18_OUTDOOR[1];??????? //显示外DS18B20的温度 ??????????????????????? dispbuf[3]=dispbuf_DS18_OUTDOOR[0];???????? ??????????????????? } ??????????????????? else if(second%10==3||second%10==8)? //?? 在3,8。。。 ??????????????????? { ??????????????????????? dispbuf[0]=dispbuf_HTU31D_INDOOR[1];??????? //显示内HTU31D的温度 ??????????????????????? dispbuf[1]=dispbuf_HTU31D_INDOOR[0];????? ??????????????????????? dispbuf[2]=dispbuf_HTU31D_OUTDOOR[1];?????? //显示外HTU31D的温度 ??????????? ??????????? dispbuf[3]=dispbuf_HTU31D_OUTDOOR[0];????? ??????????????????? } ??????????????????? else if(second%10==4||second%10==9)? //?? 在4,9。。。 ??????????????????? { ??????????????????????? dispbuf[0]=dispbuf_HF32_INDOOR[1];??????? //显示内HF3223的湿度 ??????????????????????? dispbuf[1]=dispbuf_HF32_INDOOR[0];????? ??????????????????????? dispbuf[2]=dispbuf_HF32_OUTDOOR[1];?????? //显示外HF3223的湿度 ??????????????????????? dispbuf[3]=dispbuf_HF32_OUTDOOR[0];????? ??????????????????? }?????????????????? ??????????????????? break; ??????????????????? ??????????????? case 1:????? //空调制冷显示 ??????????????????? dispbuf[1]=? 12;?????????????? //[0]最右数码管?? 显示C表示制冷 ??????????????????? dispbuf[0]=uc_ir_state;??????? //[0]最右数码管 ??????????????????? goto CASE2_DISPLAY; ??????????????????? ??????????????? case 2:????? //空调加热显示???????????????? ??????????????????? dispbuf[1]=? 42;??????????????????? //[0]最右数码管?? 显示H表示制热 ??????????????????? dispbuf[0]=uc_ir_heat_state;??????? //[0]最右数码管 ??????????????????? ??????????????? CASE2_DISPLAY:?? //在0秒显示内温,3秒外温,5秒内湿,8秒外湿 ??????????????????????? ??????????????????? if(second%10==0)?????????? ??????????????????? { ??????????????????????? dispbuf[2]=dispbuf_DS18_INDOOR[1];?????? //? dispbuf[0]是低位??? INDOOR[0]是十位 ??????????????????????? dispbuf[3]=dispbuf_DS18_INDOOR[0];????????? ??????????????????? } ??????????????????? else if(second%10==3)? ??????????????????? { ??????????????????????? dispbuf[2]=dispbuf_DS18_OUTDOOR[1];?????? ??????????????????????? dispbuf[3]=dispbuf_DS18_OUTDOOR[0]; ??? ??????????????????? } ??????????????????? else if(second%10==6)? ??????????????????? { ??????????????????????? dispbuf[2]=dispbuf_HF32_INDOOR[1];??? ??????????????????????? dispbuf[3]=dispbuf_HF32_INDOOR[0];???? ??????????????????? } ??????????????????? else if(second%10==8)? ??????????????????? { ??????????????????????? dispbuf[2]=dispbuf_HF32_OUTDOOR[1];??? ??????????????????????? dispbuf[3]=dispbuf_HF32_OUTDOOR[0];????? ??????????????????? }?????????????????? ??????????????????? break; ??????????????????? ??????????????? default: ??????????????????? dispbuf[0]=16; ??????????????????? dispbuf[1]=16; ??????????????????? dispbuf[2]=16; ??????????????????? dispbuf[3]=16; ??????????? }? //SWITCH ??????????? break; ??????? ??????? ??????? //设置中 ??????? case 1:??????? ??????????? dispbuf[3]=16; ??????????? dispbuf[2]=5? ;? //显示5=S? 调节小时 ??????????? dispbuf[0]=hour%10; ??????????? dispbuf[1]=hour/10; ??????????? break; ??????? ??????? case 2: ??????????? dispbuf[3]=16; ??????????? dispbuf[2]=15? ;? //显示F? 调节分钟 ??????????? dispbuf[0]=minute%10; ??????????? dispbuf[1]=minute/10; ????????????????????????? ??????????? break; ??????????? ??????? case 3: ??????????? dispbuf[3]=16; ??????????? dispbuf[2]=40? ;? //显示o? 调节工作模式 ??????????? dispbuf[0]= displaybuf_display_mode[uc_display_mode]; ??????????? dispbuf[1]=16;????????????????????????????? ??????????? break;? ??????????? ??????? case 4: ??????????? dispbuf[3]=16; ??????????? dispbuf[2]=12? ;? //显示C? 调节制冷温度 ??????????? INT10_TO_dispbuf( dispbuf_ui_airtemp_set, ui_airtemp_set); ??????????? dispbuf[0]= dispbuf_ui_airtemp_set[1]; ??????????? dispbuf[1]= dispbuf_ui_airtemp_set[0];????????????????????? ??????????? break;? ??????????? ??????? case 5: ??????????? dispbuf[3]=16; ??????????? dispbuf[2]=42? ;? //显示H? 调节制热温度 ??????????? INT10_TO_dispbuf( dispbuf_ui_airtemp_set,?? ui_airtemp_heat_set); ??????????? dispbuf[0]= dispbuf_ui_airtemp_set[1]; ??????????? dispbuf[1]= dispbuf_ui_airtemp_set[0];????????????????????????? ??????????? break;? ??????????????????????? ??????? ??????? default: ??????????? dispbuf[3]=16; ??????????? dispbuf[2]=16; ??????????? dispbuf[0]=16; ??????????? dispbuf[1]=16;????????????????????????????? ??????????? break;? ??????? ??????? ??????? }//SWITCH } //时间走时? / void TIME_PROCESS() {?? ??????? //以下本来放在中断T0中,现在移出来,避免中断超时问题 ??????? ET0=0;????? //在对tcnt进行操作前,一定要将定时器的中断禁掉 ??????????????????? //因为tcnt是整型,在运算时要好几条指令,如果被定时器中断,中断中又修改了值!!? 则运算结果就不准了,造成时间严重不准!!! ??????? if(tcnt>=3600)?????? //3600次,表示过了一秒钟,晶体11.0592 ??????? { ??????????? tcnt-=3600; ??? // 这句,受中断影响,中断中又修改了值!!?? 如果只是用tcnt=0;这句,则没有问题。? 有可能别的程序在处理时(比如串口),tcnt会多计,故不能清零,不然时间不准 ??????????? ET0=1;????? //马上开定时器0的中断,这样不会影响到中断服务程序 ??????????? ??????????? ul_time_compensate++;??????????????? //时间补偿修正 ??????????? if (ul_time_compensate >= 151515UL )??????? //晶振偏快,经计算,XXXX秒后要减少一秒 ??????????? { ul_time_compensate=0;? }?????????? //不增秒 ??????????? else ??????????? { ??????????????? second++; ??????????????? ??????????????? if(second>=60) ??????????????? { ??????????????????? second=0; ??????????????????? minute++; ??????????????????? if(minute>=60) ??????????????????? { ??????????????????????? minute=0; ??????????????????????? hour++; ??????????????????????? if(hour>=24)? ? hour=0; ??????????????????? } ??????????????????? ??????????????????? SENDTXTEMP();???? //每分钟发送温度给TX串口记录仪 ??? ??????????????????? if( minute==30 ) DO_WRITETODS1302_EVERY_HALF_HOUR();? //30分时 记录时间 ??????????????? } ??????????? } ??????????? ??????????? //每秒 刷新显示 ??????????? REFRESH_DISPLAY(); ??????????????? ??????? } ??????? ET0=1; } //发射红外遥控全部信号???????? / //注意:不能用软延时,因为中断ISR会严重影响延时精度,造成红外发射数据错误。? 要用定时器中断来统计发射时长!? 这里用T0统计发射时长,用T1生成38KHZ。 void SendIRdata(unsigned char *ir_data) { ??? unsigned char idata? i,j; ??? unsigned char idata? irdata; ??? ??? //引导码高电平 9ms ??? g_uc_ir_time=32;????? //实际278us*32=8.9ms ??? g_b_ir_onoff=1; ??? while(g_uc_ir_time); ??? ??? //引导码低电平 4.5ms ??? g_uc_ir_time=16;????? //实际278us*16=4.45ms ??? g_b_ir_onoff=0; ??? while(g_uc_ir_time);??? ??? ??? //发送13字节数据 ??? for(i=0; i<13; i++)?? ??? { ??????? irdata=ir_data[i]; ??????? ??????? for(j=0;j<8;j++) ??????? { ??????????? g_uc_ir_time=2;?? //0.56ms 每bit高电平,实际278us*2=0.556ms ??????????? g_b_ir_onoff=1; ??????????? while(g_uc_ir_time);??????????????? ??????? ??????? ??? if(irdata & 1)??? //判断最低位为1还是0。?? 低位先发送!! ??????? ??? { ??????????? ??? g_uc_ir_time=6;???????? //1为 1.69ms长的低电平,实际278us*6=1.668ms ??????????????? g_b_ir_onoff=0; ??????????????? while(g_uc_ir_time); ??????? ??? } ??????? ??? else ??????? ??? { ??????????? ??? g_uc_ir_time=2;???????? //0为 0.565ms长的低电平,实际278us*2=0.556ms ??????????????? g_b_ir_onoff=0; ??????????????? while(g_uc_ir_time); ??????? ??? }??? ??????? ???? irdata=irdata>>1; ??????? } ??? } ??? ??? //发送总的结束位1bit 0.56ms ??? g_uc_ir_time=2;?? ????????? //实际278us*2=0.556ms ??? g_b_ir_onoff=1; ??? while(g_uc_ir_time); ??? ??? //此时还在执行发射1中,不能马上退出,故后续再发射一下0 ??? g_uc_ir_time=2;?? ????????? //实际278us*2=0.556ms ??? g_b_ir_onoff=0; ??? while(g_uc_ir_time); ??? ??? ET1=0; ??? P_IR=0;?? //关掉红外 } void? P1_0_key_waitfor_release()??????? //等待按键松开 { ??? Delay50ms(); //延时,用于消除毛刺信号,一般10~50ms ??? //判断键松开,判断 连续 20ms内 均为高电平,则是键松开 ??? uc_keycount=0; ??? while(uc_keycount<20) ??? { ??????? if(P1_0==0) uc_keycount=0; ??????? Delay1ms(); ??????? uc_keycount++; ??????? TIME_PROCESS();?? //处理时间事务,以免按键一直按着就无法处理 ??? } } void? P1_1_key_waitfor_release()??????? //等待按键松开 { ??? //等待按键松开 ??? Delay50ms(); //延时,用于消除毛刺信号,一般10~50ms ??? //判断键松开,判断20ms内均为高电平,则是键松开 ??? uc_keycount=0; ??? while(uc_keycount<20) ??? { ??????? if(P1_1==0) uc_keycount=0; ??????? Delay1ms(); ??????? uc_keycount++; ??????? TIME_PROCESS();?? //处理时间事务,以免按键一直按着就无法处理 ??? }?? } void? P1_2_key_waitfor_release()??????? //等待按键松开 { ??? Delay50ms(); //延时,用于消除毛刺信号,一般10~50ms ??? //判断键松开,判断20ms内均为高电平,则是键松开 ??? uc_keycount=0; ??? while(uc_keycount<20) ??? { ??????? if(P1_2==0) uc_keycount=0; ??????? Delay1ms(); ??? ??? uc_keycount++; ??????? TIME_PROCESS();?? //处理时间事务,以免按键一直按着就无法处理 ??? } } //切换制冷中的各种模式 void my_aircontrol_cold_turnto(unsigned char i,? unsigned char j) { ??? SendIRdata( &g_uc_irdata[i][0] );? ??? uc_ir_state=i; ??? ??? //设置下次检测空调温度时间 ??? g_uc_ir_minute=j;???????????? //延时j分钟 ??? g_uc_ir_minute_pre=minute; ??? ??? if(i<=1)?? b_ECO_ON=0; } //检测按键进入设置状态??? void DO_KEY_PRESS_SETTING() { ??? unsigned char idata? i; ??? ??? if( P1_1==1)? return; ??? ??? //进入设置模式 ??? for(i=0;? i<8;? i++)?? dispbuf[i]=16;? //全显示空 ??? g_uc_setting_mode=1; ??? REFRESH_DISPLAY(); ??? P1_1_key_waitfor_release();???? //等待按键松开 ??? g_uc_settingmode_timeout_second=0;?? //设置时,只进行时间走时,暂停了其它工作:不进行传感器检测、不进行串口通讯、不进行空调控制,所以需要判断一个超时,以免一直困在设置模式中 ??? g_ui_settingmode_timeout_cnt=0;??? ??? ??? while(1)? //设置中 ??? { ??????????? ET0=0; ??????????? if(g_ui_settingmode_timeout_cnt>=3600)???????? //超过1秒 ??????????? { ??????????????? g_ui_settingmode_timeout_cnt=0;???????? //(有点误差没关系) ??????????????? ET0=1; ??????????????? g_uc_settingmode_timeout_second++; ??????????????? if(g_uc_settingmode_timeout_second>60)?? break;??? //超时,退出循环? (有点误差没关系) ??????????? } ??????????? ET0=1;? ??????????????? ??????????? TIME_PROCESS();????? //处理时间事务,????? 每秒刷新显示 ??????? ??????????? if( P1_2==0 ) ??????????? {?? ??????????????? switch(g_uc_setting_mode) ??????????????? { ??????????????????? case 1:?????? //小时加1 ??????????????????????? hour++; ??????????????????????? if(hour>=24) hour=0; ??????????????????????? break; ??????????????????? ??????????????????? case 2:????? //分钟加1 ??????????????????????? minute++; ??????????????????????? if(minute>=60) minute=0;???? //小时不变 ??????????????????????? ??????????????????????? TL0=0;??????? ? //定时器重新置数 ??????????????????????? tcnt=0;???????????????? //程序计数清0 ??????????????????????? second=0; ??????????????????????? break; ??????????????????????? ??????????????????? case 3:????? //模式变化 ??????????????????????? uc_display_mode++; ??????? ??????????????? if(uc_display_mode > 2) uc_display_mode=0;???? ??????????????????????? break; ??????????????????????? ??????????????????? case 4:????? //制冷温度设定 ??????????????????????? ui_airtemp_set+=5; ??????????????????????? if(ui_airtemp_set > 270) ui_airtemp_set=260; ??????????????????????? break; ??????????????????????? ??????????????????? case 5:????? //制热温度设定 ??????????????????????? ui_airtemp_heat_set+=5; ??????????????? ??????? if(ui_airtemp_heat_set > 210) ui_airtemp_heat_set=200; ??????????????????????? break;????????????????????????????????????????????? ??????????????? } ??????????????? REFRESH_DISPLAY(); ??????????????? P1_2_key_waitfor_release();???? //等待按键松开 ??????????????? ??????????????? g_uc_settingmode_timeout_second=0; ??????????? } ??????????? ??????????? else?? if? ( P1_1==0 )??????? //设置下一项 ??????????? { ??????????????? g_uc_setting_mode++; ??????????????? REFRESH_DISPLAY(); ??????????????? ??????????????? P1_1_key_waitfor_release();???? //等待按键松开 ??????????????????????????????? ??????????????? g_uc_settingmode_timeout_second=0; ??????????????? ??????????????? if(g_uc_setting_mode > 5 ) break; ??????????? }?? ??? }? //WHILE ??? //退出设置了,恢复显示,如果工作模式切换,则关空调 ??? if(uc_display_mode != uc_display_mode_pre) ??? { ??????? //关空调 ??????? if(uc_display_mode_pre==1) ??????? { ??????????? my_aircontrol_cold_turnto(0, 0); //关空调 ??????? } ??????? else if(uc_display_mode_pre==2) ??????? { ??????????? //待完善 ??????? } ??????? uc_display_mode_pre=uc_display_mode; ??? } ??? ??? g_uc_setting_mode=0; ??? REFRESH_DISPLAY(); ??? } //检测按键进行红外开关空调on off??????? void DO_KEY_PRESS_AIRCONTROL() { ??? if( !uc_display_mode )? return;???? //没在控制模式 ??????? ??? ??? //进行时间延时 ??? if(b_ir_key_delay==1) ??? { ??????? if(second > g_uc_ir_second? &&? second-g_uc_ir_second > 5)? b_ir_key_delay=0;????????? //没跨分钟 ??????? if(second < g_uc_ir_second? &&? second+60-g_uc_ir_second > 5)? b_ir_key_delay=0;??? //跨分钟了 ??? } ??? ??? if( b_ir_key_delay)??? return; ??????? ??? if(P1_0==1)? return; ??? //按键有按下了 ??? if(uc_display_mode==1)????? //制冷 ??? { ??????? if( uc_ir_state)??? my_aircontrol_cold_turnto(0, 0);????? //如果已开机,则关机 ??????? else????? my_aircontrol_cold_turnto(1, 1);?????????????? //没开机,则开机??????????? //1分钟后检测温度, 以免太快发送下一个 ??? } ??? else if(uc_display_mode==2)?? //制热 ??? { ??????? //待未来加入程序 ??????? if( uc_ir_heat_state)???? ????//如果已开机,则关机 ??????????? ; ??????? else?? //没开机,则开机 ??????????? ; ??? } ??????????????? ??? P1_0_key_waitfor_release();???? //等待按键松开 ??? ??? //按键后需要延时后才接受下一次按键,以免一直快速按键 ??? b_ir_key_delay=1;?????? ??? g_uc_ir_second=second; }?? //红外控制空调制冷?? / void DO_IR_COLD_AIRCONTROL() { ??? if( uc_display_mode!=1 )? return;???? //没在制冷模式 ??????? ??? if( !bit_DS18_INDOOR_exist &&? uc_ir_state? )????? my_aircontrol_cold_turnto(0, 0);?????? // 如果传感器突然掉线 ??? ??? ??? if(b_ECO_ON) ??? { ??????? if( hour > ECO_hour_pre? &&? hour - ECO_hour_pre > 7)? ???? my_aircontrol_cold_turnto(1, 1);??????? //没跨天 ??????? if( hour < ECO_hour_pre? &&? hour+24 - ECO_hour_pre > 7 )?? my_aircontrol_cold_turnto(1, 1);??????? //跨天了 ??? } ??? ??? //按键进行切换屏显 ??? if(P1_2==0) ??? { ??????? SendIRdata( &g_uc_irdata_with_disp[ uc_ir_state ][0] ); ??????? P1_2_key_waitfor_release(); ??? } ??? ??? ??? //进行时间延时 ??? if( g_uc_ir_minute )?? //需要延时 ??? { ??????? if( minute > g_uc_ir_minute_pre? &&? minute - g_uc_ir_minute_pre > g_uc_ir_minute)? g_uc_ir_minute=0;????????? //没跨小时 ??????? if( minute < g_uc_ir_minute_pre? &&? minute+60 - g_uc_ir_minute_pre > g_uc_ir_minute )? g_uc_ir_minute=0;????? //跨小时了 ??? } ??? ??? if( g_uc_ir_minute )??? return; ??? switch( uc_ir_state ) ??? { ??? case 0:?? //关机0中 ??????? break; ??????? ??? case 1:?? //全力制冷1中 ??????? if( i_DS18_INDOOR <= ui_airtemp_set )?? { my_aircontrol_cold_turnto(2, 10);?? ECO_hour_pre=hour;? b_ECO_ON=1; }//温度小于,转成ECO?? //n分钟后检测温度, 因为温度会先回升,再下降,不能马上检测 ??????? break; ??????? ??? case 2:?? //ECO2中 ??????? if( i_DS18_INDOOR <= ui_airtemp_set )?? my_aircontrol_cold_turnto(3, 10);??? //温度小于,转成静音+ECO??? //10分钟后检测温度, 以免太快发送下一个????? 如果ECO自动消掉,则温度会下降 ??????? else if( i_DS18_INDOOR >= ui_airtemp_set+10 )??? my_aircontrol_cold_turnto(1, 1);??? //大于,回退至全力制冷?? //1分钟后检测温度, 以免太快发送下一个 ??????? break; ??? case 3:?? //ECO+静音3 ??????? if( i_DS18_INDOOR <= ui_airtemp_set-3?? )? ??my_aircontrol_cold_turnto(4, 10);? //ECO+静音很省电,也可能会温度太低 ??????? else if( i_DS18_INDOOR > ui_airtemp_set+5 )? my_aircontrol_cold_turnto(2, 10);?? //大于,回退至ECO??????????? //10分钟后检测温度, 以免太快发送下一个 ??????? break; ??? case 4:?? //太冷了,32度ECO+静音4 ??????? if( i_DS18_INDOOR > ui_airtemp_set+5 )? my_aircontrol_cold_turnto(2, 10);?? //大于,回退至ECO??????????? //10分钟后检测温度, 以免太快发送下一个 ??????? break;? ??? } } ??????? ??? //红外控制空调制热???? /// void DO_IR_HEAT_AIRCONTROL() { ??? if( uc_display_mode!=2 )?? return;???? //没在控制模式 ??????? ??? if( !bit_DS18_INDOOR_exist &&? uc_ir_heat_state )????? ;??????????????????????????? // 如果传感器突然掉线 ??? //程序待补充 ??? }?? ??? //检测串口进行通讯??????? //串口接受2个字节为一组,第一字节是命令,第二字节是数据 //没有用串口中断,4800bps的2个字节之间只有2ms,如果程序做别的事,就会收不全数据,故电脑发送时,一个字节、一个字节慢慢发 void DO_PROCESS_SERIAL_COM() { ??? ??????? if(RI==1) ????? //串口收到数据,进行处理 ??????? { ??????????? sbuf[sbufnum]=SBUF; ??????????? RI=0;?? //要人工清RI ??????????? sbufnum++;????? ??????????? ??????????? if(sbufnum>=2)? ??????????? { ??????????????? sbufnum=0; ??????????????? //sendSBUF( "COM=", 4 );??? //回显命令 ??????????????? sendSBUF( sbuf, 2 ); ??????????????? //sendSBUF( "!", 1 ); ??????????????? ??????????????? if(sbuf[0]>=0x80)?????? ? //第一字节是命令,如果是0X80以上,发送温度、湿度;?? 0x80以下留给DS1302 ??????????????? { ??????????????????? sendSBUF( dispbuf_DS18_OUTDOOR, 3 ); ??????????????????? sendSBUF( dispbuf_DS18_INDOOR, 3 ); ??????????????? } ??????????????? else if(bitDS1302exist) ??????????????? { ??????????????????? switch (sbuf[0])??? ???//第一字节是0~8,则写入DS1302。?? 如果是9等,则读出DS1302 ??????????????????? { ??????????????????????? case 0:? //second RAW data ??????????????????????????????? if( (sbuf[1]&0x0f)>9 || ((sbuf[1]&0xf0)>>4)>5 ) {sendSBUF("secoER!",7);break;} ??????????????????????????????? DS1302_WriteOne(DS1302_SEC_AD,sbuf[1]); ??????????????????????????????? readDS1302_and_setclock(); ??????????? ??????????????????? sendSBUF("secoOK!",7); ??????????????????????????????? break; ??????????????????????? case 1:? //minute RAW data ??????????????????????????????? if( (sbuf[1]&0x0f)>9 || ((sbuf[1]&0xf0)>>4)>5 ) {sendSBUF("minuER!",7);break;} ??????????????????????????????? DS1302_WriteOne(DS1302_MIN_AD,sbuf[1]); ??????????????????????????????? readDS1302_and_setclock(); ??????????????????????????????? sendSBUF("minuOK!",7); ??????????????????????????????? break; ??????????????????????? case 2:? //hour RAW data ??????????????????????????????? if(?? (sbuf[1]&0x0f)>9 ||?? ((sbuf[1]&0xf0)>>4)>2? ||???? ( ((sbuf[1]&0xf0)>>4)*10+(sbuf[1]&0x0f) )>23? ) {sendSBUF("hourER!",7);break;} ??????????????????????????????? DS1302_WriteOne(DS1302_HOUR_AD,sbuf[1]); ??????????????????????????????? readDS1302_and_setclock(); ??????????????????????????????? sendSBUF("hourOK!",7); ??????????????????????????????? break; ??????????????????????? case 3:? //date RAW data ??????????????????????????????? if( ( ((sbuf[1]&0xf0)>>4)*10+(sbuf[1]&0x0f) )>31? ) {sendSBUF("dateER!",7);break;} ??????????????????????????????? DS1302_WriteOne(DS1302_DATE_AD,sbuf[1]); ??????????????????????????????? //readDS1302_and_setclock(); ??????????????????????????????? sendSBUF("dateOK!",7); ??????????????????????????????? break; ??????????????????????? case 4:? //month RAW data ??????????????????????????????? if( ( ((sbuf[1]&0xf0)>>4)*10+(sbuf[1]&0x0f) )>12? ) {sendSBUF("montER!",7);break;} ??????????????????????????????? DS1302_WriteOne(DS1302_MONTH_AD,sbuf[1]); ??????????????????????????????? //readDS1302_and_setclock(); ??????????????????????????????? sendSBUF("montOK!",7); ??????????????????????????????? break; ??????????????????????? case 5:? //week RAW data ??????????????????????????????? if( ( ((sbuf[1]&0xf0)>>4)*10+(sbuf[1]&0x0f) )>7? ) {sendSBUF("weekER!",7);break;} ??????????????????????????????? DS1302_WriteOne(DS1302_WEEK_AD,sbuf[1]); ??????????????????????????????? //readDS1302_and_setclock(); ??????????????????????????????? sendSBUF("weekOK!",7); ??????????????????????????????? break;? ??????????????????????? case 6:? //year RAW data ??????????????????????????????? if( ( ((sbuf[1]&0xf0)>>4)*10+(sbuf[1]&0x0f) )>99? ) {sendSBUF("yearER!",7);break;} ??????????????????????????????? DS1302_WriteOne(DS1302_YEAR_AD,sbuf[1]); ??????????????????????????????? //readDS1302_and_setclock(); ??????????????????????????????? sendSBUF("yearOK!",7); ??????????????????????????????? break;????????????????????????????????????????????????????????????????? ??????????????????? ??????????????????????? case 7: //设置CONTROL字节? 写保护 ??????????????????????????????? sbuf[1]=sbuf[1] & 0x80; //只有最高位bit7有效,其它都是0 ??????????????????????????????? DS1302_WriteOne(DS1302_CONTROL, sbuf[1]); ??????????????????????????????? sendSBUF("ContOK!",7); ??????????????????????????????? break; ??????????????????????? case 8: //设置TRICKLE CHARGER字节? 充电 ??????????????????????????????? DS1302_WriteOne(DS1302_CHARGER_AD, sbuf[1]); ??????????????????????????????? sendSBUF("charOK!",7); ??????????????????????????????? break;????????????????????????? ??????????????????????? default:??? //读出全部DS1302字节,并串口发送出去 ??????????????????????????????? BurstRead1302(ds1302_BCDdata) ; ??????????????????????????????? ds1302_BCDdata[8]=DS1302_ReadOne(DS1302_CHARGER_AD); ??????????????????????????????? sendSBUF( ds1302_BCDdata, 9 ); ??????????????????????????????? break; ??????????????????? } ??????????????? } ??????????????? else ??????????????? { ??????????????????? sendSBUF("DS1302 NOT exist!",17); ??????????????? } ??????????? }//END 二个字节处理 ??????? } //END RI==1 ??????? } /// void main(void) { /* 测试晶振的频率,用来校准晶振的误差 AUXR = (AUXR | 0x04);? //独立波特率发生器工作在1T 模式? 0000 0100?? --BRTCLKOUT(CLKOUT2)?????? BRT = (256-5);???????? //预置数,BRT独立波特率发生器的8位重装载值??? //输出频率= 晶振11.0592MHz/5/2=1.10592MHz?? --BRTCLKOUT(CLKOUT2) WAKE_CLKO = (WAKE_CLKO | 0x04);? //允许 独立波特率发生器脚BRTCLKO(CLKOUT2)(P1.0) 输出时钟频率,?? 输出频率=定时器溢出率/2 AUXR = (AUXR | 0x10);??????????? //启动独立波特率发生器开始计数工作 ??--BRTCLKOUT(CLKOUT2) while(1) ;? ??? */ ??? ??? ??? ??? ??? //红外状态 ??? uc_ir_state=0; ??? uc_ir_heat_state=0; ??? P_IR=0; ??? ??? ??? uc_display_mode=0;??????????????????? //按走时模式 ??? uc_display_mode_pre=uc_display_mode; ??? ??? //开机是弱上拉 ??? P0M1=0;??? //P0推挽 ??? P0M0=0xFF; ??? ??? P2M1=0;?? //P2推挽 ??? P2M0=0xFF; ??? P0=0; ????? //P0接各个笔划,共阳极,接地时点亮 ??? P2=0xFF;??? //P2,置1时选择数码管 ??? ??? ??? P1M1=0;?? ??? P1M0=0x08;? // 0000 1000? //空调口设成推挽(红外) ??? P1=0xF7;??? //1111 0111? 关闭空调口(红外) ??? ??? P3=0xFF;? //弱上拉 ??? DS1302_RST = 0;? ??? DS1302_CLK = 0; ??? Delay20ms();???????? //延时,让DS1302等外设上电复位 ??? ??? DS1302_SetProtect(0); ? ??????????????????//上电后要取消写保护,才能对DS1302的RAM进行写入 ??? ??? DS1302_WriteOne( 0xC0 , 0xAB);??????????? //测试DS1302的RAM,判断DS1302是存在 ??? if (DS1302_ReadOne( 0xC0 ) == 0xAB) ??? ??? { ??????? bitDS1302exist=1; ??????? DS1302_WriteOne(DS1302_CHARGER_AD,? 0);?? //取消对电池充电 ??? } ??? else ?? bitDS1302exist=0; ??? if(bitDS1302exist)? readDS1302_and_setclock(); ???? //读取和设置时间 ??????? ??? //先显示一下,以免黑屏 ??? dispbuf[4]=minute%10; ??? dispbuf[5]=minute/10; ??? dispbuf[6]=hour%10; ??? dispbuf[7]=hour/10; ??? //设置定时器T0 ??? //TMOD=0x52;??? // 0101 0010 =? T1的GATE=0选通,C/T选择为外部计数方式=1,工作方式=1 (16位计数器);? T0的GATE选通,C/T选择为C定时方式=0,工作方式=2 ??? TMOD = 0x22; //(定时器0和1:? GATE选通,定时方式,?? 工作方式2,自动重装,8位) ??? ??? TH0=0;???? //预置数=0 ??? TL0=0;???? //从0开始计数 即:(256-0)=256次 ,11.0592/12/256=3600 次/S ??? TR0=1;??????? //开始计数 ??? ET0=1;??????? //允许T0的中断 ??? ??? ??? //设置定时器T1? --用于红外遥控 ??? TH1=244;???? ?? //预置数???????? //即计数12次中断一次,11.0592MHZ,即:11.0592/12/12=76.8K 次/S ??? TL1=244;???? ?? //开始计数值 ??? TR1=1;??????? ? //开始计数?? ??? ET1=0;??????? ??? PT1=1;????? //中断优先级IP中的PT1=1,提高中断优先级比T0高!? ?????这样T1中断可以中断掉T0中断 ??? ??? ??? //设置 "独立波特率发生器",用于串口 --V2版新增 ??? AUXR=AUXR | 1;? //不可位AUXR中的BIT0的S1BRS=1,即选用独立波特率发生器,定时器1得到释放! ??? SCON=0x50;? ??? //01 0 1 0000 模式1,无多处理机,允许接收,发送8位,接收8位,清TI=0,RI=0 ??? BRT=250;????? ? //从0开始计数 即:(256-250)=6次 ,11.0592/12/6/32=4800bps,需要 波特率倍增位SMOD=0。?? 波特率低一些,以免处理不过来 ??? AUXR=AUXR | 0x10;?? //不可位AUXR中的BIT4的BRTR=1,即允许独立波特率发生器运行 ??? ES=0;?????? ????? ? //不允许串口总断??? ??? EA=1;???????? //允许总中断 ??? ??? ??? //串口接收到一个数据后,这时RI要为0,才会放入SBUF中并且自动置RI=1,否则丢弃这个数据。如果RI为1,则后续数据都丢掉了。 ??? //串口发送时,就会马上发,发完自动置TI=1。如果TI=1,不影响数据发送。?? ??? RI=0;?????? //清理一下串口 ??? sbufnum=0;? //串口接收到的数量 ??? I2C_Init();?? //HTU31D /* 测试 红外发射信号是否正常 uc_ir_state=1; while(1) { ??? if(P1_0==0) ??? { ??????? SendIRdata( &g_uc_irdata[uc_ir_state][0] ); ??????? uc_ir_state++;????? ??????? if(uc_ir_state>=4) uc_ir_state=0; ??????? ??????? P1_0_key_waitfor_release();???? //等待按键松开 ??? } } */ ??? while(1)?? ??? { ??????? DO_PROCESS_SERIAL_COM();??? //检测串口进行通讯 ??????? DO_KEY_PRESS_SETTING();???? //检测按键进入设置状态 ??? ??????? DO_KEY_PRESS_AIRCONTROL();?? //检测按键进行红外开关空调 ??????? DO_IR_COLD_AIRCONTROL();?? //红外控制空调制冷 ??????? ??????? DO_IR_HEAT_AIRCONTROL();?? //红外控制空调制热 ??????? TIME_PROCESS();???? ?? //走时 ??????? ??????? DO_WHAT_FUNC();????? //传感器检测 ??? } } /// //中断TSR??? 中断处理时间不能超过一次计数时间277.777US /* 中断每秒3600次,每次277.7777us。时间计算在主程序中进行。 //---注意:这个会影响软延时delay函数,执行一次如果是10us,则对于277us来说误差就是4%(实际执行时间未知) */ void t0(void) interrupt 1 { ??? tcnt++; ??? ??? i_dowhat_interval++;?? //如果按键一直按住,则会多计数,或溢出,没关系,就是dowhat间隔时间再延长而已 ??? ??? mstcnt++; ??? ??? ??? if(bit_T0_interrupt_prohibited)??? return;??? //时序要求强的操作,则后序代码不执行 ??????? ??????? ??? if( mstcnt>=4 )????? //计数器每计数n次,改变一次显示位(定时器是3600HZ,数码管闪烁频率=3600/9次/8个管=50HZ,数码管闪烁频率=3600/4次/16个管=56HZ) ??? { ??????? mstcnt=0; ??????? if(dispbitcnt<8) ??????? { ??????????? P0= dispcode[dispbuf[dispbitcnt]];? ??//P0输出笔划。? dispbuf中是显示数据,[0]是最右那个数码管。? dispcode中是笔划。 ??????? ??????????? P2= dispbitcode[dispbitcnt];???????? //P2选择哪个数码管,dispbitcode是数码管选择码,[0]是最右那个数码管 ??????? } ??????? else ??????????? P2=0;?? //不显示,16管只显示8管,用于减少一半显示亮度,以免太亮 ??????????? ??????? dispbitcnt++;??????? //选LED的下一显示位 ??????? if(dispbitcnt>=16)? dispbitcnt=0;??????????? //这里数值大,则亮度小,但闪烁。闪烁频率在25HZ,明显会闪。闪烁频率在50HZ,不闪。 ??? } ??? ??? ??? //红外发射IR控制 ??? if(g_uc_ir_time) ??? { ??????? if(g_b_ir_onoff)?? ET1=1;?? //本次发射IR? 278us ??????? else??? ET1=0;????????????? //本次不发射IR? 278us ??????? g_uc_ir_time--; ??? } ??? else??? ET1=0;?? //把红外IR关了 ??????? ??? ??? //在设置模式中,需要进行计时 ??? if(g_uc_setting_mode)??? g_ui_settingmode_timeout_cnt++; ??? } /// //T1? --用于红外发射38KHZ //只进行端口翻转,处理时间要短。?? 76.8K 次/S,? 13.021us一次中断。38KHZ是26.316us周期。 1%的误差,对载波来说,没有问题。 //---这个会严重影响软延时delay函数,执行一次可能要1us,对于13us来说误差就是10%,软延时就被影响10%!!造成红外发射严重不准或其它问题 void t1(void) interrupt 3 { ??? P_IR=~P_IR;??????? //端口翻转就有了38KHZ信号 }?? //====================================================/ DELAY_STC12_WXL.H文件: //? STC12C5A60S2 单片机 1T? 11.0592MHZ void Delay2us()???? //@11.0592MHz { ??? unsigned char i; ??? _nop_(); ??? _nop_(); ??? i = 2; ??? while (--i); } // void Delay8us()???? //@11.0592MHz { ??? unsigned char i; ??? i = 19; ??? while (--i); } // void Delay10us()??????? //@11.0592MHz { ??? unsigned char i; ??? _nop_(); ??? _nop_(); ??? _nop_(); ??? i = 24; ??? while (--i); } // void Delay80us()??????? //@11.0592MHz { ??? unsigned char i, j; ??? _nop_(); ??? _nop_(); ??? _nop_(); ??? i = 1; ??? j = 216; ??? do ??? { ??????? while (--j); ??? } while (--i); } // void Delay600us()?????? //@11.0592MHz { ??? unsigned char i, j; ??? _nop_(); ??? _nop_(); ??? i = 7; ??? j = 112; ??? do ??? { ??????? while (--j); ??? } while (--i); } // void Delay1ms()???? //@11.0592MHz { ??? unsigned char i, j; ??? _nop_(); ??? i = 11; ??? j = 190; ??? do ??? { ??????? while (--j); ??? } while (--i); } /// void Delay20ms()??????? //@11.0592MHz { ??? unsigned char i, j, k; ??? i = 1; ??? j = 216; ??? k = 35; ??? do ??? { ??????? do ??????? { ??????????? while (--k); ??????? } while (--j); ??? } while (--i); } void Delay50ms()??????? //@11.0592MHz { ??? unsigned char i, j, k; ??? i = 3; ??? j = 26; ??? k = 223; ??? do ??? { ??????? do ??????? { ??????????? while (--k); ??????? } while (--j); ??? } while (--i); } ///以下是红外遥控用的??????????? void Delay9ms()???? //@11.0592MHz { ??? unsigned char i, j; ??? _nop_(); ??? _nop_(); ??? _nop_(); ??? i = 97; ??? j = 206; ??? do ??? { ??????? while (--j); ??? } while (--i); } void Delay4500us()????? //@11.0592MHz { ??? unsigned char i, j; ??? i = 49; ??? j = 101; ??? do ??? { ??????? while (--j); ??? } while (--i); } void Delay560us()?????? //@11.0592MHz { ??? unsigned char i, j; ??? _nop_(); ??? _nop_(); ??? _nop_(); ??? i = 7; ??? j = 1; ??? do ??? { ??????? while (--j); ??? } while (--i); } void Delay1690us()????? //@11.0592MHz { ??? unsigned char i, j; ??? i = 19; ??? j = 42; ??? do ??? { ??????? while (--j); ??? } while (--i); } //====================================================/ DS18B20_WXL.H文件: /*? 先设置端口 sbit DQ_DS18_OUTDOOR=P3^4; sbit DQ_DS18_INDOOR=P1^4; */ // unsigned char? DS18_CRC( unsigned char?? *addr, unsigned char? len) //计算8位CRC,输入是一串字节流数据。? 数据不需要扩展CRC位的0。 //注意:这里的addr[]中是原始数据,不需要扩展的一字节0,len长度为原始数据长度!!? 重要!! { ??? unsigned char? idata? crc = 0, inbyte, i, mix; ??? while (len--) ??? { ??????? // inbyte 存储当前参与计算的新字节 ??????? inbyte = *addr++; ??????? for (i = 8; i; i--) ??????? { ??????????? mix = (crc ^ inbyte) & 0x01; // CRC寄存器最低位 与 数据的最低位 进行XOR(高位都是忽略的),看结果是1还是0,如果是1,则需要用POLY对CRC寄存器进行XOR ??????????? crc >>= 1;????? //高位移入的是0 ??????????? if (mix) ??????????? { ?? ?????????????crc ^= 0x8C;?? //颠倒后的POLY ??????????? } ??????????? inbyte >>= 1;?? ??????? } ??? } ??? return crc; } // int? DS18_TEMP_TO_SIGNED_INT10(unsigned char? uc_DS18_temp1, unsigned char? uc_DS18_temp2) //LSB字节 , MSB字节。 //返回值:? 温度的10倍,有符号整数 //ds18b20的2个字节:? 负数是全部bit取反,再加1,比如: //55度:0000 0011 0111 0000 //取反:1111 1100 1000 1111 //加1:1111 1100 1001 0000 得-55度 //ds18b20的低4bit是小数,需要单独处理,不能合在一起转成十进制。?? 高5bit是符号位。? 中间7bit是非小数 { ??? unsigned char? idata? uc_fraction=0; ??? int? idata? i_temp=0; ??? bit bitminus=0; ??? unsigned char? code? DS18_decimaltable[16]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};? //小数换算表,二进制温度数据0001是0.0625度,即小数显示1;0010是0.125度,即小数还是显示1;... ??? ??? if((uc_DS18_temp2 & 0xf8)!=0x00)???? //如果是负数 ??? {??????? //是负数,2个字节合在一起整个减一,再取反,就是正数值(小数还要乘以精度) ??? ??????? //或者,2个字节合在一起整个取反再加1 ??????? bitminus=1;??? //表示是负数 ??? ??? uc_DS18_temp2=~uc_DS18_temp2;???? ??? ??? uc_DS18_temp1=~uc_DS18_temp1;????? //取反 ??? ??? uc_DS18_temp1++;???????????????? //加1 ??????? if (uc_DS18_temp1==0) uc_DS18_temp2++;? //如果有进位,则要加1 ??? } ??? ??? uc_fraction=DS18_decimaltable[ uc_DS18_temp1 & 0x0f ];?? //查表得到小数部分 ??? ??? uc_DS18_temp2=uc_DS18_temp2<<4;???????? ??? uc_DS18_temp2=uc_DS18_temp2 & 0x70; ??? //保证MSB其它位均为0 ??? uc_DS18_temp1=uc_DS18_temp1>>4;??? //移掉LSB中的小数 ??? uc_DS18_temp1=uc_DS18_temp1 & 0x0f; ??? //保证LSB其它位均为0 ??? uc_DS18_temp2=uc_DS18_temp2 | uc_DS18_temp1;??? //MSB与LSB的非小数部分合并,这样就是温度的绝对值的整数值 ??? ??? i_temp=uc_DS18_temp2*10; ??? i_temp+=uc_fraction; ??? ??? if(bitminus)??? return -i_temp; ??? else??? return i_temp; } /* // unsigned int DS18_TEMP_TO_INT(unsigned char? uc_DS18_temp1, unsigned char? uc_DS18_temp2) ? //LSB字节 , MSB字节。 //返回值 低15位=温度绝对值的10倍。如果是负数,则最高位是1。同AM2321的表达方式 //ds18b20的2个字节: ?负数是全部bit取反,再加1,比如: //55度:0000 0011 0111 0000 //取反:1111 1100 1000 1111 //加1:1111 1100 1001 0000 得-55度 //ds18b20的低4bit是小数,需要单独处理,不能合在一起转成十进制。?? 高5bit是符号位。 { ??? unsigned char? idata? uc_fraction=0; ??? unsigned int? idata? ui_temp=0; ??? bit bitminus=0; ??? unsigned char? idata? DS18_decimaltable[16]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};? //小数换算表,二进制温度数据0001是0.0625度,即小数显示1;0010是0.125度,即小数还是显示1;... ??? ??? if((uc_DS18_temp2 & 0xf8)!=0x00)???? //如果是负数 ??? {??????? //是负数,2个字节合在一起整个减一,再取反,就是正数值(小数还要乘以精度) ??? ??????? //或者,2个字节合在一起整个取反再加1 ??????? bitminus=1;??? //表示是负数 ??? ??? uc_DS18_temp2=~uc_DS18_temp2;???? ??? ??? uc_DS18_temp1=~uc_DS18_temp1;????? //取反 ??? ??? uc_DS18_temp1++;???????????????? //加1 ??????? if (uc_DS18_temp1==0) uc_DS18_temp2++;? //如果有进位,则要加1 ??? } ??? ??? uc_fraction=DS18_decimaltable[ uc_DS18_temp1 & 0x0f ];?? //查表得到小数部分 ??? ??? uc_DS18_temp2=uc_DS18_temp2<<4;???????? ??? uc_DS18_temp2=uc_DS18_temp2 & 0x70; ??? //保证MSB其它位均为0 ??? uc_DS18_temp1=uc_DS18_temp1>>4;??? //移掉LSB中的小数 ??? uc_DS18_temp1=uc_DS18_temp1 & 0x0f; ??? //保证LSB其它位均为0 ??? uc_DS18_temp2=uc_DS18_temp2 | uc_DS18_temp1;??? //MSB与LSB的非小数部分合并,这样就是温度的绝对值的整数值 ??? ??? ui_temp=uc_DS18_temp2*10; ??? ui_temp+=uc_fraction; ??? ??? if(bitminus) ui_temp=ui_temp | 0x8000;????? //如果是负数,则最高位变1 ??? ??? return ui_temp; } */ // void SEND_TO_DS18_OUTDOOR( unsigned char? command ) //DQ_DS18_OUTDOOR表示哪一个DS1302,调用前DQ_DS18_OUTDOOR为高电平 { ??? unsigned char? idata? i; ??? for(i=0;i<8;i++) ??? { ??????? if((command & 0x01)==0)?? //command为待发送的数据。 现要发送“0”???? 60至120us之间 ??????? { ??????????? DQ_DS18_OUTDOOR=0; ???? //DATA=0,DATA从高到低,表示开始传送数据(传送开始到传送完的整个时间在60-120US之内) ??????????? Delay80us();??? //延时120us(不能太大,不然就变成复位了)?? (先经过15US,然后DS18会开始检测DATA数据) ??????????? DQ_DS18_OUTDOOR=1;?? ?? //“0”发送完成,拉高 ,然后需要至少1US的恢复时间(即高电平时间) ??????????? Delay2us(); ??????? } ??????? else??????????? //现要发送“1”?????? 最小 60? us ??????? { ??????????? MACRO_WXL_INTERRUPT_PROHIBITED????? //自定义宏,强时序操作时中断服务简化 ??????????? DQ_DS18_OUTDOOR=0; ???? //DATA=0,DATA从高到低,表示开始传送数据(传送开始到传送完的整个时间在60-120US之内) ??????????? Delay2us(); //延时(经过15US后DS18会开始检测DATA数据,因此应尽快变1) ??????????? DQ_DS18_OUTDOOR=1; ???? //DATA=1,送出DATA值 ??????????? MACRO_WXL_INTERRUPT_ALLOWED ??????????? Delay80us();??? //延时80~∝us ??????? } ??????? command=_cror_(command,1);?? //循环移位 ??? } }?? //END,调用后DQ_DS18_OUTDOOR为高电平 // unsigned char RECEIVE_FROM_DS18_OUTDOOR( )? //DQ_DS18_OUTDOOR表示哪一个DS1302,调用前DQ_DS18_OUTDOOR为高电平 { ??? unsigned char? idata? i,temp; ??? temp=0; ??? for(i=0;i<8;i++)??? ??? { ??????? temp=_cror_(temp,1);??? //移位,LSb先传送 ??????? MACRO_WXL_INTERRUPT_PROHIBITED?????? //自定义宏,强时序操作时中断服务简化 ??????? DQ_DS18_OUTDOOR=0;?????????????????? //DATA=0,从高到低,表示开始数据接收 ??????? Delay2us();???? //开始数据接收后,需先DATA=0至少1US进行INIT ??????? DQ_DS18_OUTDOOR=1;?????????????????? //DATA=1,以进行检测 ??????? Delay8us(); //延时8us??? (开始数据接收后,DS18只输出数据15US) ??????? if(DQ_DS18_OUTDOOR==1)??? temp=temp | 0x80;?????????? //读DATA ??????? MACRO_WXL_INTERRUPT_ALLOWED ??????? Delay80us();??? //延时80~∝us??? (整个读取时间至少是60US,再加1US的恢复时间(即高电平时间) ??? } ??? return temp; }?? //END,调用后DQ_DS18_OUTDOOR为高电平 // bit RESET_DS18_OUTDOOR(? )? //DQ_DS18_OUTDOOR表示哪一个DS1302,调用前DQ_DS18_OUTDOOR为高电平。?? 返回0表示出错 { ??? DQ_DS18_OUTDOOR=1; ??? Delay2us(); ??? if(DQ_DS18_OUTDOOR==0) return 0; ??? ??? DQ_DS18_OUTDOOR=0; ??? Delay600us();?????? //延时750us ??? DQ_DS18_OUTDOOR=1; ??? Delay80us();??????? //延时80us? ??? if(DQ_DS18_OUTDOOR==1) return 0;?? //如果DS18B20有下拉,则存在DS18B20 ??? Delay600us();?????? //延时670us ??? return 1; }?? //END,调用后DQ_DS18_OUTDOOR为高电平 // // void SEND_TO_DS18_INDOOR( unsigned char? command )? //DQ_DS18_INDOOR表示哪一个DS1302,调用前DQ_DS18_INDOOR为高电平 { ??? unsigned char? idata? i; ??? for(i=0;i<8;i++) ??? { ??????? if((command & 0x01)==0)?? //command为待发送的数据。 现要发送“0”???? 60至120us之间 ??????? { ??????????? DQ_DS18_INDOOR=0; ????? //DATA=0,DATA从高到低,表示开始传送数据(传送开始到传送完的整个时间在60-120US之内) ??????????? Delay80us();??? //延时120us(不能太大,不然就变成复位了)?? (先经过15US,然后DS18会开始检测DATA数据) ??????????? DQ_DS18_INDOOR=1;?? ??? //“0”发送完成,拉高 ,然后需要至少1US的恢复时间(即高电平时间) ??????????? Delay2us(); ??????? } ??????? else??????????? //现要发送“1”?????? 最小 60? us ??????? { ??????????? MACRO_WXL_INTERRUPT_PROHIBITED??? //自定义宏,强时序操作时中断服务简化 ??????????? DQ_DS18_INDOOR=0; ????? //DATA=0,DATA从高到低,表示开始传送数据(传送开始到传送完的整个时间在60-120US之内) ??????????? Delay2us(); //延时(经过15US后DS18会开始检测DATA数据,因此应尽快变1) ??????????? DQ_DS18_INDOOR=1; ????? //DATA=1,送出DATA值 ??????????? MACRO_WXL_INTERRUPT_ALLOWED ??????????? Delay80us();??? //延时80~∝us ??????? } ??????? command=_cror_(command,1);?? //循环移位 ??? } }?? //END,调用后DQ_DS18_INDOOR为高电平 // unsigned char RECEIVE_FROM_DS18_INDOOR( )?? //DQ_DS18_INDOOR表示哪一个DS1302,调用前DQ_DS18_INDOOR为高电平 { ??? unsigned char? idata? i,temp; ??? temp=0; ??? for(i=0;i<8;i++)??? ??? { ??????? temp=_cror_(temp,1);??? //移位,LSb先传送 ??????? MACRO_WXL_INTERRUPT_PROHIBITED???? //自定义宏,强时序操作时中断服务简化 ??????? DQ_DS18_INDOOR=0;?????????????????? //DATA=0,从高到低,表示开始数据接收 ??????? Delay2us();???? //开始数据接收后,需先DATA=0至少1US进行INIT ??????? DQ_DS18_INDOOR=1;?????????????????? //DATA=1,以进行检测 ??????? Delay8us(); //延时8us??? (开始数据接收后,DS18只输出数据15US) ??????? if(DQ_DS18_INDOOR==1)??? temp=temp | 0x80;?????????? //读DATA ??????? MACRO_WXL_INTERRUPT_ALLOWED ??????? Delay80us();??? //延时80~∝us??? (整个读取时间至少是60US,再加1US的恢复时间(即高电平时间) ??? } ??? return temp; }?? //END,调用后DQ_DS18_INDOOR为高电平 // bit RESET_DS18_INDOOR(? )?? //DQ_DS18_INDOOR表示哪一个DS1302,调用前DQ_DS18_INDOOR为高电平。?? 返回0表示出错 { ??? DQ_DS18_INDOOR=1; ??? Delay2us(); ??? if(DQ_DS18_INDOOR==0) return 0; ??? ??? DQ_DS18_INDOOR=0; ??? Delay600us();?????? //延时750us ??? DQ_DS18_INDOOR=1; ??? Delay80us();??????? //延时80us? ??? if(DQ_DS18_INDOOR==1) return 0;?? ? //如果DS18B20有下拉,则存在DS18B20 ??? Delay600us();?????? //延时670us ??? return 1; }?? //END,调用后DQ_DS18_INDOOR为高电平 //====================================================/ I2C_HTU31D.H文件: //根据别人的程序修改的 void I2C_Delay(unsigned char t) { ??? while(t--) ??? { ??? ??? Delay10us(); ??? } } /*================================================================ 【名 称】unsigned char I2CWRByte(unsigned char WriteData) 【功 能】I2C写一个字节数据,返回ACK或者NACK 【备 注】从高到低,依次发送 ================================================================*/ unsigned char I2C_WriteByte(unsigned char?? WriteData) { ??? unsigned char idata i; ??? //SCL = 0;??????????????? //写之前,SCL、SDA已经是0 ??? for(i = 0;i < 8;i++)?????? //第1~8位,写给对方,? MSb先发 ??? { ??????? I2C_Delay(10);?? //稳定SCL低电平 ??????? if(WriteData & 0x80)??????????? SDA = 1;??? ??????? else??????????? SDA = 0; ??????? I2C_Delay(40);?? //稳定SDA ??????? ??????? SCL = 1;??? ?????? //输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样 ??????? I2C_Delay(50);?? //高电平500us ??????? SCL = 0; ??????????? ??????? WriteData <<= 1; ??? } ??? ??? I2C_Delay(10);???? //稳定SCL低电平 ??? SDA = 1; ??? I2C_Delay(40); ??? ??? SCL = 1;???????????????? //第9位,读对方发来的是ACK还是NACK。?? 注意: I2C里,回应ACK是SDA拉低电平,NACK是释放SDA(高电平)!!对于主机设备、外设都是这样!! ??? I2C_Delay(50); ??? if( SDA )?? i=1;??????? ??? //SDA为高,收到NACK ??? else ?????? i=0;??? ??????? //SDA为低,收到ACK ??? SCL = 0; ??? ??? //_nop_(); _nop_(); ?? _nop_(); ?? _nop_(); ??? I2C_Delay(1);??????????????????????????? //稳定SCL低电平 ??? SDA=0;??????????????????????????????????? //返回时,SCL、SDA都是0 ??? return i; } /*================================================================ 【名 称】unsigned char I2CRDByte(unsigned char AckValue) 【功 能】I2C读一个字节数据,入口参数用于控制应答状态,ACK或者NACK 【备 注】从高到低,依次接收 ================================================================*/ unsigned char I2C_ReadByte(unsigned char?? AckValue) { ??? unsigned char idata i; ??? unsigned char idata ReadData = 0; ??? ??? ?//读之前,SCL、SDA已经是0 ??? ? ??? SDA = 1;??????????? //释放SDA ??? ??? for(i = 0;i < 8;i++) ??? { ??????? ??????? I2C_Delay(50);? //稳定SCL低电平??? ??????? ??????? SCL = 1;??????? ?????? //SCL上升沿 ??????? I2C_Delay(50);? ?? //延时SCL高电平500us等待信号稳定??? 注:在后期测比较好,相当于速率更慢,SDA信号更稳定 ??????? ReadData <<= 1; ??????? if(SDA == 1) ?????? //采样获取数据????? 数据是MSB最高字节在先、MSb最高位在先 ??????????? ReadData |= 0x01; ??????? else ??????????? ReadData &= 0xfe; ??????? SCL = 0;?? ???? ??? }?? ??? ??? I2C_Delay(10);??? //稳定SCL低电平 ??? SDA = AckValue; ? //应答状态 ??? I2C_Delay(40); ??? SCL = 1;?? ? I2C_Delay(50);????????? ? SCL = 0; ??? I2C_Delay(1); ??? SDA=0;?????????????????????????? //返回时,SCL、SDA都是0 ??? ??? return ReadData; } /*================================================================ 【名 称】void I2CStart(void) 【功 能】I2C启动信号 【备 注】SCL、SDA同为高,SDA跳变成低之后,SCL跳变成低 ================================================================*/ void I2C_Start(void) { ? ? SDA = 1; ? ? I2C_Delay(1); ? ? SCL = 1; ? ? I2C_Delay(20);?????? // SCL高电平200us ? ? SDA = 0; ? ? I2C_Delay(10);?????? // SCL高电平100us ? ? SCL = 0; ? ? I2C_Delay(1);??????? //返回时,SCL、SDA都是0 } /*================================================================ 【名 称】void I2CStop(void) 【功 能】I2C停止信号 【备 注】SCL、SDA同为低,SCL跳变成高之后,SDA跳变成高 ================================================================*/ void I2C_Stop(void) { ??????? //之前,SCL、SDA已经是0 ??????? I2C_Delay(10);??????? // SCL低电平500us ??????? SDA = 0; ??????? I2C_Delay(40); ??????? ? ? SCL = 1; ? ? I2C_Delay(10);?????? // SCL高电平100us ? ? SDA = 1;?????????????? //返回时,SCL、SDA都是0 } /*================================================================ 【名 称】void I2C_Init(void) 【功 能】I2C初始化,空闲状态 ================================================================*/ void I2C_Init(void) { ??? unsigned char idata? i; ??? for(i = 0;i < 99;i++)?????? //做99次,如果 外设 有发送什么数据什么的,可以让它全部发完 ??? { ??? I2C_Start(); ??? I2C_Stop(); ??? } } / unsigned char HTU31D_conversion( unsigned char addr )??? //返回? 0表示HTU回应错误,? 1表示成功 { ??? ??? I2C_Start(); ??? ??? if(I2C_WriteByte( addr<<1 ) == 0)?? //发送地址+wr,? addr接GND是0x40,接VCC是0x41,? wr是LSB位是0。?? HTU会反馈ACK0 ??? { ??????? if(I2C_WriteByte( 0x5E ) == 0)?? //发送精度要求, 按最大精度,? 01011110= 0x5E。?? HTU会反馈ACK0 ??????? { ??????????? I2C_Stop(); ??????????? return 1;?? //成功 ??????? } ??? } ??? I2C_Stop(); ??? return 0;? //不成功 } unsigned char? CRC_noadd0(unsigned char?? ?*addr, unsigned char??? len)?? //计算8位CRC,输入是一串字节流数据。? 按变种计算方式,数据不需要扩展CRC位的0,可以扩展CRC值。 //注意:这里的addr[]中是原始数据,不需要扩展的一字节0,len长度为原始数据长度!!? 重要!! //注意:这里的addr[]中可以扩展一字节CRC值,len长度为原始数据长度+1,这样计算出来CRC值就是0。 { ??? unsigned char? idata?? crc = 0, inbyte, i; ??? while (len--) ??? { ??????? // inbyte 存储当前参与计算的新字节 ??????? inbyte = *addr++; ??????? for (i = 8; i; i--) ??????? { ??????? ??? ?//CRC寄存器移出的高位与待测数据移出的高位相XOR,是1则要把CRC寄存器XOR ??????? ??? if(??? (crc & 0x80) ^ (inbyte & 0x80)? ) ??????? ??? { ??????? ??????????? crc<<=1; ? ????????????????? crc^=0x31; ???????????????????????????? ??????? ??? } ??????? ??? else ??????? ??????? ??crc<<=1; ??????? ??????? ??????????????????? inbyte<<=1; ??????? } ??? } ??? return crc; } unsigned char HTU31D_CRC(unsigned char? MSB,? unsigned char LSB,?? unsigned char?? CRC)????? //HTU31D发送数据是MSB最高字节在先、MSb最高位在先,计算CRC也这样 { ??? unsigned char? idata? ucdata[3]; ??? ucdata[0]=MSB; ??? ucdata[1]=LSB; ??? ucdata[2]=CRC; ??? return CRC_noadd0(ucdata, 3); } unsigned char HTU31D_readTRH(int?? *wendu,? int?? *shidu,? unsigned char addr )???? //返回0表示HTU回应错误,? 1表示成功。?? 值低15位= 温度或湿度 绝对值的10倍。如果是负数,则最高位是1。 { ??? ??? unsigned char idata MSB, LSB, CRC; ??? unsigned int idata temp; ??? float idata ftemp; ??? ??? I2C_Start(); ??? ??? if(I2C_WriteByte( addr<<1 ) == 0)?? //发送地址+wr,? addr接GND是0x40,接VCC是0x41,? wr是LSB位是0。?? HTU会反馈ACK0 ??? { ??????? if(I2C_WriteByte( 0 ) == 0)?? //发送Read T & RH。?? HTU会反馈ACK0 ??????? { ??????????? I2C_Stop(); ??????????? I2C_Start(); ??????????? if(I2C_WriteByte( (addr<<1) + 1 ) == 0)?? //发送地址+rd,? addr接GND是0x40,接VCC是0x41,? rd是LSB位是1。?? HTU会反馈ACK0 ??????????? { ??????????????? MSB = I2C_ReadByte(0);??? //读取温度MSB,并发送ACK0来确认 ??????????????? LSB = I2C_ReadByte(0);???? //读取温度LSB,并发送ACK0来确认 ??????????????? CRC = I2C_ReadByte(0);????????? //读取CRC,并发送ACK0来确认 ??????????????? if(HTU31D_CRC(MSB,LSB,CRC))????????? //CRC出错 ??????????????? { ??????????????????? *wendu=1200; ??????????????? }?????? ??????????????? else??? //CRC正常 ??????????????? { ??????????????????? temp = MSB; ??????????????????? temp<<=8; ??????????????????? temp += LSB; ??????????????????? ??????????????????? ftemp= -40. + 165. * ( (float)temp / 65535. ) ;??????? //温度:T ℃= -40 + 165 * ST / 65535??? ,float 约精确到6位数,可以满足??????????????? ??????????????????? if(ftemp>=0) ??????????????????????? *wendu=? (int)(? (ftemp+0.05) *10.);?????????????? //四舍五入? ??????????????????? else ??????????????????????? *wendu=? (int)(? (ftemp-0.05) *10.);????????????????? ??????????????? } ??????????????? ??????????????? MSB = I2C_ReadByte(0);??? //读取湿度MSB,并发送ACK0来确认 ??????????????? LSB = I2C_ReadByte(0);???? //读取湿度LSB,并发送ACK0来确认 ??????????????? CRC = I2C_ReadByte(1);????????? //读取CRC,并发送 NACK1 来确认要停止了 ??????????????? I2C_Stop(); ??????????????? if(HTU31D_CRC(MSB,LSB,CRC))????????? //CRC出错 ??????????????? { ??????????????????? *shidu=1200; ??????????????? }?????? ??????????????? else??? //CRC正常?????????????? ??????????????? { ??????????????????? temp = MSB; ??????????????????? temp<<=8; ??????????????????? temp += LSB; ??????????????????? *shidu=(int)( (100.*( (float)temp / 65535.) + 0.05) *10. ) ;?? //四舍五入???? //湿度: RH%= 100 * SRH / 65535?? ,float 约精确到6位数,可以满足 ??????????????? } ??????????????? ??????????????? //在主程序判断数值是否异常。比如温度值太大,说明数据异常 ??????????????? ??????????????? return 1;? //成功 ??????????? } ??????? } ??? } ??? I2C_Stop(); ??? return 0;? //不成功 } //====================================================/ DS1302_wxl.H文件: /******************************************************************** 文件名称: DS1302.H 创建人:kuloqiu 描述: ?? 完成于2010.9.9 硬件测试通过 ********************************************************************/???? //硬件接口定义 /* sbit DS1302_CLK=P1^5;? sbit DS1302_IO=P1^6;? sbit DS1302_RST=P1^7; */ //DS1302内部寄存器地址 #define DS1302_SEC_AD??? 0x80 //秒数据地址?? //秒寄存器地址?? 1000 000X??? BIT0是1表示读,是0表示写。? BIT7恒为1。?? BIT6是1表示内存RAM区,0表示CLOCK区。 #define DS1302_MIN_AD?? 0x82 //分数据地址 #define DS1302_HOUR_AD?? 0x84 //时数据地址 #define DS1302_DATE_AD??? 0x86 //日数据地址 #define DS1302_MONTH_AD?? 0x88 //月数据地址 #define DS1302_WEEK_AD??? 0x8A //星期数据地址??? #define DS1302_YEAR_AD??? 0x8C //年数据地址 #define DS1302_CONTROL??? 0x8E //WP写保护控制 #define DS1302_CHARGER_AD 0x90 //充电涓电流????????????????? 1001 000X //传输方式 #define DS1302_NWCLOCK??? 0xBE?? //多字节突发方式写时钟 #define DS1302_NRCLOCK??? 0xBF?? //多字节突发方式读时钟 #define DS1302_NWRAM??? 0xFE?? //多字节突发方式写RAM #define DS1302_NRRAM??? 0xFF?? //多字节突发方式读RAM #define DS1302_RAM(X) (0xC0+(X)*2)?? //用于计算 RAM 地址的宏。? 1100 000X? ~ 1111 111X? ,即 写C0/读C1、写C2/读C3、写C4/读C5、 ~? 写FE/读FF ,即地址按C0、C2、C4。。。再赋BIT0 #define BCD(X) ((X/10)<<4|(X%10))???? //数值? 转成 BCD格式 //地址命令0位 #define DS1302_READ?????? 0X01 //读 #define DS1302_WRITE????? 0X00 //写 //函数定义 extern void DS1302_innerWriteByte(unsigned char cdata); extern unsigned char DS1302_innerReadByte(); extern void DS1302_WriteOne(unsigned char address,unsigned char cdata); extern unsigned char DS1302_ReadOne(unsigned char address); extern void DS1302_SetProtect(bit flag); extern void DS1302_SetRtc(unsigned char *tible); extern void DS1302_ReadRtc(unsigned char *timeread); extern void Display_TimePROESS(unsigned char dplay[8],unsigned char *tible);? extern void DS1302_NReadRam(unsigned char *rstr); extern void DS1302_NWriteRam(unsigned char *wstr); /******************************************************************** 文件名称: DS1302.c ********************************************************************/? void DS1302delay(void ) { _nop_(); _nop_(); _nop_(); _nop_(); ??? } void DS1302_innerWriteByte(unsigned char cdata) //实时时钟写入一字节(内部函数),调用时需要CLK=0,返回时CLK=0, IO=1 //写入DS1302是CLK=0时准备数据,上升沿写入; //读取DS1302是CLK下降沿后的CLK=0时可以读 { ??? unsigned char? idata? i; ??? unsigned char? idata? acc; ??? acc = cdata; ??? for(i=8; i>0; i--) ?? ?{ ??????? DS1302_IO? =acc & 1;??????????? //低位先传送 ??????? DS1302delay();????????????????????????????? //(进入时,CLK先进行延时一下) ??????? DS1302_CLK = 1;??????? //上升沿写入 ??????? DS1302delay(); ??????? DS1302_CLK = 0;??????????????? ??????? acc = acc >> 1; ??? } ??? DS1302_IO? =1; }? //返回时CLK=0,IO=1,没有延时一下 unsigned char? DS1302_innerReadByte() //实时时钟读取一字节(内部函数),调用时需要CLK=0,数据IO处于可读状态,返回时CLK=0, IO=1 //写入DS1302是CLK=0时准备数据,上升沿写入; //读取DS1302是CLK下降沿后的CLK=0时可以读 { ??? unsigned char? idata? i; ??? unsigned char? idata ?acc,temp; ??? for(i=8; i>0; i--) ??? {??? ??????? acc = acc >>1;??????????? //低位先传送 ??????? DS1302_IO=1; ??????? DS1302delay();?????????????????????????????????? //(进入时,CLK先进行延时一下) ??????? temp=DS1302_IO;????????? //先读数,再 CLK 上升沿 ??????? acc = (temp<<7) | acc; ??????? DS1302_CLK = 1; ??????? DS1302delay(); ??????? DS1302_CLK = 0;????????? ??? } ??? return(acc); }? //返回时CLK=0,IO=1,没有延时一下 /******************************************************************** 函数名称: DS1302_WriteOne(unsigned char address,unsigned char cdata) 函数功能: 向指定地址写单个数据 输入参数: address要写入对象的地址, cdata 要写的数据 输出参数:????? ********************************************************************/ void DS1302_WriteOne(unsigned char address,unsigned char cdata) //ucAddr: DS1302地址,?? ucData: 要写的数据 { ? ??DS1302_RST = 0; ??? DS1302_CLK = 0; ??? DS1302delay();??? //RST变上升要有1us以上间隔 ??? DS1302_RST = 1; ??? ??? DS1302_innerWriteByte(address & 0xFE);?????? // 地址 | "写命令"?? BIT0是0 ??? DS1302_innerWriteByte(cdata);?????? // 写1Byte数据 ??? ??? DS1302delay();????? //延时一下CLK低电平 ??? DS1302_CLK = 0;?? ??? DS1302_RST = 0; } /******************************************************************** 函数名称: DS1302_ReadOne(unsigned char address) 函数功能: 向指定地址读出单个数据 输入参数: address要读出对象的地址 输出参数:????? ********************************************************************/ unsigned char DS1302_ReadOne(unsigned char address) //读取DS1302某地址的数据 { ??? unsigned char? idata? ucData; ??? DS1302_RST = 0; ??? DS1302_CLK = 0; ??? DS1302delay();??? //RST变上升要有1us以上间隔 ? ??DS1302_RST = 1; ??? ??? DS1302_innerWriteByte(address | 0x01);??????? // 地址 | "读命令"??? BIT0是1 ??? ucData = DS1302_innerReadByte();???????? // 读1Byte数据 ??? ??? DS1302delay();??????? //延时一下CLK低电平 ??? DS1302_CLK = 0; ??? DS1302_RST = 0; ??? return(ucData); } /******************************************************************** 函数名称: DS1302_SetProtect(bit flag) 函数功能: wp保护开关 输入参数: flag:1保护,0不保护 输出参数:????? ********************************************************************/ void DS1302_SetProtect(bit flag)??????? //是否写保护? { if(flag) ?? DS1302_WriteOne(DS1302_CONTROL,0x80);??? //DS1302_CONTROL=0x8E,WP写保护 else ?? DS1302_WriteOne(DS1302_CONTROL,0x00); } /******************************************************************** 函数名称: DS1302_SetRtc(unsigned char *settime) 函数功能: 设置实时时钟 输入参数: *settime:设置的具体时间数组首地址 输出参数:????? ********************************************************************/ /* 未使用 void DS1302_SetRtc(unsigned char *settime)?? { unsigned char i; unsigned char tible[7]; for(i=0;i<7;i++) {?????? ?? tible[i]=BCD(settime[i]); //BCD转换 } DS1302_SetProtect(0);?? //关写保护 DS1302_WriteOne((DS1302_YEAR_AD|DS1302_WRITE),tible[6]);?? //年 DS1302_WriteOne((DS1302_WEEK_AD|DS1302_WRITE),tible[5]);?? //周 DS1302_WriteOne((DS1302_MONTH_AD|DS1302_WRITE),tible[4]); //月 DS1302_WriteOne((DS1302_DATE_AD|DS1302_WRITE),tible[3]); //日 DS1302_WriteOne((DS1302_HOUR_AD|DS1302_WRITE),tible[2]); //时 DS1302_WriteOne((DS1302_MIN_AD|DS1302_WRITE),tible[1]); //分 DS1302_WriteOne((DS1302_SEC_AD|DS1302_WRITE),tible[0]); //秒 //DS1302_SetProtect(1);?? //开写保护 } */ /******************************************************************** 函数名称: DS1302_ReadRtc(unsigned char *timeread) 函数功能: 读取时钟 输入参数: *timeread:读到的时间数据存放的地址 输出参数:????? ********************************************************************/ /* 未使用 void DS1302_ReadRtc(unsigned char *timeread) {???? timeread[6]=DS1302_ReadOne(DS1302_YEAR_AD); timeread[5]=DS1302_ReadOne(DS1302_WEEK_AD); timeread[4]=DS1302_ReadOne(DS1302_MONTH_AD); timeread[3]=DS1302_ReadOne(DS1302_DATE_AD); timeread[2]=DS1302_ReadOne(DS1302_HOUR_AD); timeread[1]=DS1302_ReadOne(DS1302_MIN_AD); timeread[0]=DS1302_ReadOne(DS1302_SEC_AD); } */ /******************************************************************** 函数名称: Display_TimePROESS(unsigned char dplay[8],unsigned char tible[7]) 函数功能: 处理显示的数据 __仅显示时分秒 ,因为时间寄存器内存放的是BCD码 输入参数: dplay[8]:处理后的数据?? tible[7]:读到后未处理的数据 输出参数:???????? ********************************************************************/ /* 未使用 void Display_TimePROESS(unsigned char dplay[8],unsigned char tible[7]) //BCD分成两部分转十六进制 { dplay[0]=tible[2]/16; //时 dplay[1]=tible[2]%16; dplay[2]=10; dplay[3]=tible[1]/16; //分 dplay[4]=tible[1]%16; dplay[5]=10; dplay[6]=tible[0]/16; //秒 dplay[7]=tible[0]%16; }??? */ /******************************************************************** 函数名称: DS1302_NReadRam(unsigned char *rstr) 函数功能: 多字节突发模式读RAM, ??? DS1302_NRRAM 一次可进行31个片内RAM单元读 输入参数: *rstr:存放读到的N个数据 输出参数:???????? ********************************************************************/ void DS1302_NReadRam(unsigned char *rstr) { unsigned char? idata? i; DS1302_RST=0; DS1302_CLK=0; DS1302delay();??? //RST变上升要有1us以上间隔 DS1302_RST=1;??????? DS1302_innerWriteByte(DS1302_NRRAM);?? // 写0xFF,多字节突发方式读RAM for(i=0;i<31;i++)???? //连续31 字节 { ?? *rstr=DS1302_innerReadByte() ; ?? rstr++; } DS1302delay();??????? //延时一下CLK低电平 DS1302_RST=0; DS1302_CLK=0; } /******************************************************************** 函数名称: DS1302_NReadRam(unsigned char *rstr) 函数功能: 多字节突发模式写RAM, ??? DS1302_NRRAM 一次可进行31个片内RAM单元写 输入参数: *wstr:要被写入的N个数据 输出参数:???????? ********************************************************************/ void DS1302_NWriteRam(unsigned char *wstr) { unsigned char? idata? i; unsigned char? idata? *tmpstr;?? tmpstr=wstr ; DS1302_SetProtect(0);?? //关写保护 DS1302_RST=0; DS1302_CLK=0; DS1302delay();??? //RST变上升要有1us以上间隔 DS1302_RST=1; DS1302_innerWriteByte(DS1302_NWRAM);?? //写 0xFE ,多字节突发方式写RAM for(i=0;i<31;i++)???? //连续31 字节 { ?? DS1302_innerWriteByte(*tmpstr) ;?????? ?? tmpstr++; } DS1302delay();????? //延时一下CLK低电平 DS1302_RST=0; DS1302_CLK=0; //DS1302_SetProtect(1);?? //开写保护 } // void BurstWrite1302(unsigned char *pWClock)? //往DS1302写入时钟数据(多字节方式) { ??? unsigned char? idata? i; ??? ??? DS1302_SetProtect(0);?? //关写保护 ??? ??? DS1302_RST = 0; ??? DS1302_CLK = 0; ??? DS1302delay();??? //RST变上升要有1us以上间隔 ??? DS1302_RST = 1; ??? ??? DS1302_innerWriteByte(0xbe);???????? // 0xbe为时钟多字节写时钟命令 ??? for (i = 8; i>0; i--)???????? //8Byte = 7Byte 时钟数据 + 1Byte 控制?????? //时钟块写时,必须至少写8个字节。 ??? { ??????? DS1302_innerWriteByte(*pWClock);? // 写1Byte数据?? //返回时CLK=0 ??????? pWClock++; ??? } ??? ??? DS1302delay();????? //延时一下CLK低电平 ??? DS1302_CLK = 0; ??? DS1302_RST = 0;???? //? RST? 0=复位? 1=运行 } ? //返回时? RST=0 // void BurstRead1302(unsigned char *pRClock) //读取DS1302时钟数据(时钟多字节方式) { ??? unsigned char? idata? i; ??? ??? DS1302_RST = 0;???????????? //? RST? 0=复位? 1=运行。复位后都是先写 ??? DS1302_CLK = 0;???? //? CLK ??????????? //写入DS1302是CLK=0时准备数据,上升沿写入; ??????????? //读取DS1302是CLK下降沿后的CLK=0时可以读 ??? DS1302delay();??? //RST变上升要有1us以上间隔 ??? DS1302_RST = 1;???????????? //? RST? 0=复位? 1=运行 ??? ??? DS1302_innerWriteByte(0xbf);? ????? // 0xbf:?? 时钟多字节读命令 ??? for (i=8; i>0; i--) ??? { ?????? *pRClock = DS1302_innerReadByte();?? // 读1Byte数据??? //返回时CLK=0 ?????? pRClock++; ??? } ??? ??? DS1302delay();????? //延时一下CLK低电平 ??? DS1302_CLK = 0; ??? DS1302_RST = 0;???? //? RST? 0=复位? 1=运行 }?????? //返回时? RST=0 // void? wxl_BCDToStr(unsigned char? *ds1302_BCDdata,? char? *ds1302_strtime)???? //ds1302_strtime[18]时间字串,用于串口输出。时间18字节。 { ds1302_strtime [0] = ((ds1302_BCDdata[6]>>4) & 0x0F) + '0';? //年 ds1302_strtime [1] = ((ds1302_BCDdata[6]) & 0x0F) + '0'; ds1302_strtime [2] ='.'; ds1302_strtime [3] = ((ds1302_BCDdata[4]>>4) & 0x0F) + '0';? //月 ds1302_strtime [4] = ((ds1302_BCDdata[4]) & 0x0F) + '0'; ds1302_strtime [5] ='.'; ds1302_strtime [6] = ((ds1302_BCDdata[3]>>4) & 0x0F) + '0';? //日 ds1302_strtime [7] = ((ds1302_BCDdata[3]) & 0x0F) + '0'; ds1302_strtime [8] =' '; ds1302_strtime [9] = ((ds1302_BCDdata[2]>>4) & 0x0F) + '0';? //时 ds1302_strtime [10] = ((ds1302_BCDdata[2]) & 0x0F) + '0'; ds1302_strtime [11] =':'; ds1302_strtime [12] = ((ds1302_BCDdata[1]>>4) & 0x0F) + '0';? //分 ds1302_strtime [13] = ((ds1302_BCDdata[1]) & 0x0F) + '0'; ds1302_strtime [14] =':'; ds1302_strtime [15] = ((ds1302_BCDdata[0]>>4) & 0x0F) + '0';? //秒 ds1302_strtime [16] = ((ds1302_BCDdata[0]) & 0x0F) + '0'; ds1302_strtime [17] =0; } ? |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 22:38:16- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |