IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 02:09:57  更:2022-09-15 02:11:51 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码