找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4017|回复: 7
收起左侧

用STM8S103K单片机制作通风机控制器 有源码有说明无图纸

  [复制链接]
ID:386877 发表于 2018-8-16 14:10 | 显示全部楼层 |阅读模式
刚开始学习单片机,这是我第一次做着玩的,希望别喷,所有模块除了电源都买的成品,没有画图.主要由外壳,LCD1602显示屏, 4×4单线键盘, DS3231时钟模块, STM8S103最小系统板,电源模块,DS18B20温度传感器,4继电器模块组成.
用途就是无线电业余中继控制柜里散热用通风机的逻辑控制,能够控制通风机运行时间段,根据不同的当前温度调整通风机转速工况

FB-9B型通风机控制器使用说明书

目录
1. 概述
1.1. 适用范围
1.2. 功能
2. 主要技术参数
2.1. 环境条件
2.2. 技术参数
3. 安装
3.1. 存储
3.2. 安装
4. 控制器组成
5. 使用与操作
5.1. 操作说明
5.2. 设置参数:
5.2.1. “日期时间参数设置”说明:
5.2.2. “温度判定参数设置”说明:
5.2.3. “季节与时间段参数设置”说明:
6. 常见故障与处理
7. 装箱单

  • 概述
    • 适用范围

通风机控制器是为FB-9B横流风机而设计的专用控制器。

1 控制器总图

1.LCD1602液晶显示屏;2.模拟量单线4×4键盘;3.DS18B20温度传感器插座;

4.通风机插座;5.电源插座与电源开关



    • 功能

时间显示:通过DS3231时钟芯片进行时钟显示,时间格式:24小时制,XX年XX月XX日,XX小时XX分XX秒。

温度显示: 通过DS18B20温度传感器对温度进行测量温度显示范围:-55℃~125℃。

通风机工况控制: 继电器K1/K2/K3,根据日期、时间、当前温度,可以控制通风机的启动、停止、中速运行、高速运行。

显示屏背光控制:继电器K4控制显示屏背光。

键盘输入操作:主要实现参数信息输入,功能界面变换,显示屏背光控制触发。

参数设置:可设定通风机允许工作的日期范围,可设定通风机允许工作的时间范围,可设定通风机中速运行的温度范围,可设定大于多少温度通风机高速运行;可设定小于多少温度通风机停止运行。

  • 主要技术参数
    • 环境条件

使用环境温度                                          -25℃~60℃

空气的相对湿度                            在95%以下(温度为25℃时);

控制器禁止放在含有腐蚀性或爆炸性气体(如灰尘、蒸汽或煤气、石油液化气等)的环境中。



    • 技术参数

                                 电   源:                                            AC220V. N. PE. 50Hz. 0.2kVA

显   示:           LCD1602

键   盘:           模拟信号单线4×4小键盘

MCU芯片:                                            STM8S103K

时钟芯片:                                 DS3231

温度采集:                                 单路DS18B20

温度测量范围:      -55℃~125℃

显示分辨率:        1℃

继电器输出:                              4组单触点

       调试接口:          ST-LINK V2

控制电源:                                                        DC 5V 2A线性电源

控制器重量:                   300g

外形尺寸(L×W×H): 250×150×100 mm                           

  • 安装
    • 存储

长期储存前,须对控制器进行保养、修复损坏器件,并对其进行彻底清理,保持技术状态良好;

存放前,用保鲜膜将屏幕及键盘覆盖;

应将控制器面板四个螺丝必须完全锁闭;

应储存在清洁、干燥、无腐蚀性气体的环境中,避免周围环境剧烈变化,无阳光直接照射并且不能堆放。

存储温度              -10~60℃;

空气的相对湿度在95%以下(温度为25℃时);



    • 安装

FB-9B型通风机控制器安装管理人员要仔细研究和分析控制器的设计方案和设计图纸,理解使用方法、控制原理。

校验控制器外型尺寸,确认安装位置。

按照图3连接控制器供电的电源线、连接控制器与通风机的线缆、连接控制器与DS18B20温度传感器的线缆,即安装完毕。

图片1.png

2 控制面板实物图片


3 接口实物图片

  • 控制器组成

通风机控制器主要由DS18B20温度传感器,DS3231时钟芯片,STM8S103K八位单片机,LCD1602液晶显示器显示,模拟量单线4×4键盘,继电器K1/K2/K3/K4,供电模块等组成。

4 DS18B20温度传感器实物图片

5 DS3231时钟芯片实物图片

6 STM8S103K八位单片机实物图片

7 LCD1602液晶显示器实物图片

8 继电器K1/K2/K3/K4实物图片

9 电源模块实物图片

10模拟量单线4×4键盘实物图片

11通风机电机实物图片

12 MCU控制系统原理框图

  • 使用与操作
    • 操作说明

              键盘按键定义请参考图10。

              通风机控制器正常使用只需要将图1电源开关打开即可,无需其它操作。

该控制器控制通风机逻辑:

              当首次打开电源开关后,LCD1602屏幕背光开启,进入系统初始化界面,初始化一切正常则进入图13正常工作界面。

              开机首次进入正常工作界面后,LCD1602的背光将被自动关闭,如果需要打开背光按下键盘F1键,背光将被开启,随便按下任意按键之后再次按下F1键背光关闭。程序设计重复的按键操作是不被执行的,正常工作推荐关闭LCD1602背光。

              控制器正常工作状态,每5秒左右更新一次温度,通过温度值控制通风机运行状态,当温度小于用户设定温度时通风机停止工作, 此时显示屏工作状态位显示S。

              当大于用户设定温度上限时通风机高速运行, 此时显示屏工作状态位显示H。

              当温度设定在用户设定温度之间时通风机中速运行, 此时显示屏工作状态位显示M。

              每个小时发生变化则对用户设定的时间范围参数进行检查,当在用户设定小时范围内则通风机允许工作,否则不允许工作,这个判定优先级大于温度判定, 此时显示屏工作状态位显示C。

  每个月发生变化则对用户设定的日期范围参数进行检查,当前值在用户设月范围内则通风机允许工作,否则不允许工作,这个判定优先级最高,此时显示屏工作状态位显示C。

13正常工作界面

              第一行显示XX年XX月XX日 星期几 最后一个字符代表工作状态位:S代表停机 M代表风机中速运行 H代表风机高速运行 C特殊季节或者特殊时间段风机不允许工作,这个参数可以根据使用情况自行设置,具体设置方法后面详细描述

              第二行显示XX小时XX分XX秒 T:代表温度,系统大概5秒检测一次温度并在屏幕更新温度值。



    • 设置参数:
      • 日期时间参数设置说明:
                            在图13正常工作界面按下F2键进入图14日期时间参数设置界面,在该界面下可以设置DS3231时钟芯片的日期时间参数,其格式为XX年XX月XX日X星期XX小时XX分XX秒,也就是如图14第一行YYMMDD W hhmmss。
第二行光标对应第一行的相应位,这时候按照顺序输入即可,但是每输入一个字符必须按下OK键确认,输入数据举例,18年08月08日星期三12点30分30秒,则这样操作:"1OK8OK0OK8OK0OK8OK OK1OK2OK3OK0OK3OK0OK",当敲入最后一个OK时自动更新数据并返回正常工作界面,如果输入错误或者不想修改,只要最后一个OK没有按下则随时按下ESC键,则不更新数据并返回工作界面。

14 日期时间参数设置界面





      • 温度判定参数设置说明:
                            在图13正常工作界面按下F3键进入图15温度判定参数设置界面。
                            S:T<XX代表温度小于XX通风机为停机状态。
                            H:T>XX代表温度大于XX通风机为高速运行状态。
                            M:XX<T>XX代表温度大于XX并且小于XX通风机为中速运行状态。
                            每输入一个字符必须按下OK键确认,输入数据举例,S:T<30 H:>40 M:40<T>30,则这样操作:"3OK0OK4OK0OK4OK0OK3OK0OK",当敲入最后一个OK时自动更新数据并返回正常工作界面,如果输入错误或者不想修改,只要最后一个OK没有按下则随时按下ESC键,则不更新数据并返回工作界面。

15 温度判定参数设置界面





      • 季节与时间段参数设置说明:
                            在图13正常工作界面按下F4键进入图16季节与时间段参数设置界面。
                            RUN_H:XX<hh>XX代表小时大于多少XX并且小于多少XX通风机允许工作。
                            RUN_M:XX<MM>MM代表月份大于多少XX并且小于多少XX通风机允许工作。
                            每输入一个字符必须按下OK键确认,输入数据举例,RUN_h:21<hh>08 RUN_M:10<MM>07。则这样操作:"2OK1OK0OK8OK1OK0OK0OK7OK",当敲入最后一个OK时自动更新数据并返回正常工作界面,如果输入错误或者不想修改,只要最后一个OK没有按下则随时按下ESC键,则不更新数据并返回工作界面。

16季节与时间段参数设置界面


  • 常见故障与处理

常见故障及处理方法:

序号

故障现象

处理方法

1

控制器不工作

1更换检查FU1玻璃管保险丝;

2.检查维修供电模块;

3.更换检查总开关;

4.检查线路。

2

继电器无动作

1检查更换继电器板;

2.检查线路。

3

LCD1602屏幕不亮

  • 检查供电线路;
  • 检查K4继电器动作是否正常。

4

无法进入系统界面

1.检查DS18B20温度传感器电缆以及连接器;

2.检查更换DS18B20温度传感器;

3.检查线路。

5

通风机控制失效,控制标志位一直显示C或S或M或H

  • 检查时间条件参数的设置;
  • 检查温度条件参数的设置;
  • 当以上参数写入不符合规则有可能造成,控制逻辑失常。

0.png

单片机源程序如下:


  1. /*****************************************************************
  2. * 实验名称及内容:风机控制
  3. * 实验平台及编程人员:stm8s103k3开发版 Hao
  4. ******************************************************************/
  5. #include "iostm8s103k3.h"//主控芯片的头文件
  6. /*************************常用数据类型定义*************************/
  7. #define u8  uint8_t
  8. #define u16 uint16_t
  9. #define u32 uint32_t
  10. typedef unsigned char    uint8_t;//自定义类型
  11. typedef unsigned short   uint16_t;//自定义类型
  12. typedef unsigned long    uint32_t;//自定义类型
  13. /*************************端口/引脚定义区域************************/
  14. #define  LCDRS          PC_ODR_ODR1     //LCD1602数据/命令选择端口
  15. #define  LCDRW          PC_ODR_ODR2     //LCD1602读写控制端口
  16. #define  LCDEN          PC_ODR_ODR3     //LCD1602使能信号端口
  17. #define  LCDDATA        PB_ODR          //LCD1602数据端口D0至D7
  18. #define  LCDBUSY        PB_IDR_IDR7     //LCD1602数据端口D7
  19. #define  DS18B20_DQ     PA_ODR_ODR3     //PA3单总线引脚位定义
  20. #define  K1             PD_ODR_ODR2     //PD2控制K1继电器引脚定义
  21. #define  K2             PD_ODR_ODR3     //PD3控制K2继电器引脚定义
  22. #define  K3             PD_ODR_ODR4     //PD4控制K3继电器引脚定义
  23. #define  K4             PD_ODR_ODR5     //PD5控制K4继电器引脚定义
  24. #define  SDA_OUT        PC_ODR_ODR7     //I2C总线时钟引脚PC7(输出)
  25. #define  SDA_IN         PC_IDR_IDR7     //I2C总线时钟引脚PC7(输入)
  26. #define  SCL            PC_ODR_ODR6     //I2C总线时钟引脚PC6
  27. /***********************用户自定义数据区域***********************/
  28. u8 table0[]="==Sys FAN init==";//LCD1602显示字符串数组1显示效果用初始化界面
  29. u8 table3[]={'0','1','2','3','4','5','6','7','8','9'};//0至9字符数组
  30. u8 add_word_year[]={0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02};//LCD1602自造字“年”地址00H
  31. u8 add_word_month[]={0x0F,0x09,0x0F,0x09,0x0F,0x09,0x11,0x00};//LCD1602自造字“月”地址01H
  32. u8 add_word_day[]={0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00};//LCD1602自造字“日”地址02H
  33. u8 add_word_Temp[]={0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00};//LCD1602自造字“℃”地址05H
  34. static u16 Tem_u16=0;                   //整数温度值变量
  35. static float Tem_f=0;                   //浮点数温度值变量
  36. u8 flag=0;                               //温度值正负标志变量
  37. u8 flag_DIS=0;                           //界面选择标志位
  38. u8 cj=1;                                 //风机切换标志位
  39. u8 flag_time=0;                          //时间日期读取标志位
  40. u8 flag_KOC=0,stemp1,stemp2;             //继电器逻辑控制标志位
  41. u8 flag_save=0;//按键存储数据标志位
  42. static u16 AD_Vtemp[10]={0};//装载10次ADC采样数据
  43. static u16 AD_val=0;//ADC单次采样数据
  44. static u8 KEY_NO=0,KEY_NO1=0;;//按键键值码
  45. static u16 GETvoltage=0;//获取到的电压
  46. u8 GETDS3231_DAT; //定义全局变量用于保存DS3231读回数据值
  47. u8 OPT[8]={0x30,0x30,0x40,0x40,0x09,0x20,0x06,0x10};//用户自定义选项参数数组
  48. u8 OPT1[8]={0x30,0x30,0x40,0x40,0x09,0x20,0x06,0x10};//用户自定义选项参数数组
  49. u8 KS=0,qian,bai,shi,ge;//KS为按键按下标志位,qian为千位、百、十、个
  50. u8 year,month,day,week,hour,branch,second;//修改时间临时存储变量
  51. u8 mt,lt;//高位存储临时变量,低位存储临时变量

  52. /***************************函数声明区域***************************/
  53. void delay(u16 Count);//延时函数声明
  54. void delay_u(u16 Count);//us延时函数声明
  55. void delay_ms(u16 Count);//ms延时函数声明
  56. void GPIO_Init(void);//GPIO配置函数声明
  57. void LCD1602_Write(u8 cmdordata,u8 writetype);//写入液晶模组命令或数据函数声明
  58. void LCD1602_init(void);//LCD1602初始化函数声明
  59. void LCD1602_DIS(u8 val);//显示字符函数声明
  60. void LCD1602_Busy(void);//LCD1602判忙函数
  61. void add_word(void);//LCD1602自造字添加到CGRAM函数声明
  62. void LCD1602_DIS_CHAR(u8 x,u8 y,u8 z);//在设定地址写入字符数据函数声明
  63. void LCD1602_DIS_CHAR_S(u8 x,u8 y,u8 z);//在设定地址写入光标函数声明
  64. void LCD1602_screen_sidesway(u8 x);//LCD1602屏幕移动函数声明
  65. void LCD1602_cursor_sidesway(u8 x,u8 y);//LCD1602光标移动函数声明
  66. void LCD1602_DIS_swich(u8 x,u8 y,u8 z);//LCD1602屏幕开关与光标开关函数声明
  67. void LCD1602_DIS_Clear();//LCD1602屏幕清屏命令函数声明
  68. void DS18B20_reset(void);               //DS18B20初始化时序
  69. void DS18B20_DQ_DDR(u8 ddr);            //DG单总线引脚方向配置函数
  70. void DS18B20_init(void);                //DS18B20初始化函数
  71. void DS18B20_Wbyte(u8 x);               //DS18B20写字节函数
  72. u8 DS18B20_Rbit(void);                  //DS18B20读总线位函数
  73. u8 DS18B20_Rbyte(void);                 //DS18B20读字节函数
  74. void DS18B20_get_Temperature(void);     //温度取值和处理函数
  75. void ADC_init(void);            //ADC2初始化函数声明
  76. void ADC_GET(void);             //ADC2模数转换函数声明
  77. void AVG_AD_Vtemp(void);        //平均值滤波函数声明
  78. void I2C_SDA_DDR(u8 ddr);//I2C_SDA串行数据引脚方向性配置函数声明
  79. void I2C_START(void);//I2C总线起始信号配置函数声明
  80. void I2C_STOP(void);//I2C总线终止信号配置函数声明
  81. u8 I2C_Write8Bit(u8 DAT);//I2C总线单字节数据写入函数声明
  82. u8 I2C_Read8BitNACK(void);//单字节数据读出(发送无应答)函数声明
  83. u8 I2C_Read8BitACK(void);//单字节数据读出(发送应答)函数声明
  84. u8 DS3231_ReadByte(u8 ADDR);//DS3231读出单个字节函数声明
  85. void DS3231_WriteByte(u8 ADDR,u8 DAT);//DS3231写入单个字节函数声明
  86. u8 BCD2HEX(u8 val); //BCD转换为Byte函数声明
  87. u8 HEX2BCD(u8 val); //Byte转换为BCD码函数声明
  88. u8 unlock_EEPROM(void);//解锁EEPROM函数声明
  89. void OPTconfig(void);//OPT选项字节配置函数声明
  90. void read_DS3231(void);//读取日期函数声明
  91. void read_18b20_flag(void);//上电读取温度判断工作位标志函数声明
  92. void key_Testing(void);//键盘检测函数声明
  93. void OPT_Load(void);//参数初始化函数声明
  94. void K_OC(void);//继电器逻辑控制函数声明
  95. u8 ASC_shi(u8 val);//取十位变换0~9ASCII码函数声明
  96. u8 ASC_ge(u8 val);//取个位变换0~9ASCII码函数声明
  97. /**************************主函数区域****************************/
  98. int main( void )
  99. {
  100.     //************HSI->HSE时钟自动切换流程及注释说明************
  101.     //如果CLK_CMSR中的主时钟源为HSI,则CLK_CMSR=0xE1
  102.     //如果CLK_CMSR中的主时钟源为LSI,则CLK_CMSR=0xD2
  103.     //如果CLK_CMSR中的主时钟源为HSE,则CLK_CMSR=0xB4
  104.     if(CLK_CMSR!=0xB4)
  105.     //判断主时钟状态寄存器CLK_CMSR中的主时钟源是否是HSE
  106.     //若不是则进入if程序段
  107.     {
  108.       //1.首先要配置时钟切换使能位SWEN=1,使能切换过程
  109.       CLK_SWCR|=0x02;//展开为二进制0000 0010 SWEN位=1
  110.       //2.选择主时钟源,对主时钟切换寄存器CLK_SWR写入欲切换时钟
  111.       CLK_SWR=0xB4;//配置CLK_CMSR中的主时钟源为HSE
  112.       //3.等待时钟切换控制寄存器CLK_SWCR中的切换中断标志位SWIF=1
  113.       while((CLK_SWCR & 0x08)==0);
  114.       //4.清除相关标志位
  115.       CLK_SWCR=0;
  116.     }
  117.    
  118.     GPIO_Init();                         //配置GPIO
  119.     LCD1602_init();                      //LCD1602初始化   
  120.     K4=1;                                //打开LCD1602背光
  121.     LCD1602_DIS(0);                      //显示系统初始化界面   
  122.     LCD1602_DIS(1);                      //显示控制系统正常运行界面
  123.     delay_ms(500);
  124.     K4=0;                                //进入正常运行界面后关闭LCD1602背光
  125.     ADC_init();                          //初始化ADC   
  126.     OPT_Load();                          //读取系统参数
  127.     DS18B20_init();                      //初始化DS18B20设备
  128.     read_18b20_flag();                   //读取18B20温度确定标志位
  129.     u8 time=255;                         //温度采集标志
  130.    
  131.    
  132.     IWDG_KR=0xCC;//软件程序启用IWDG
  133.     IWDG_KR=0x55;//允许对受保护的IWDG_PR和IWDG_RLR寄存器进行操作
  134.     //*********************预分频因子配置语句**********************
  135.     //IWDG_PR=0;//设定预分频因子为4分频
  136.     //IWDG_PR=0x01;//设定预分频因子为8分频
  137.     //IWDG_PR=0x02;//设定预分频因子为16分频
  138.     //IWDG_PR=0x03;//设定预分频因子为32分频
  139. //    IWDG_PR=0x04;//设定预分频因子为64分频
  140.     //IWDG_PR=0x05;//设定预分频因子为128分频
  141.     IWDG_PR=0x06;//设定预分频因子为256分频
  142.     //*************************************************************
  143.     IWDG_RLR=0xFF;//配置重装载寄存器数值为最大0xFF
  144.     IWDG_KR=0xAA;//刷新IWDG相关配置
  145.    
  146.     while(1)
  147.     {      
  148.       IWDG_KR=0xAA;//执行完成delay函数后“喂狗”
  149.       key_Testing();//键盘检测
  150.       if(flag_DIS==1)
  151.       {
  152.         read_DS3231();//读取DS3231时钟数据
  153.         
  154.         if(time>20)
  155.         {
  156.           time=0;        
  157.           DS18B20_init();       //初始化DS18B20设备
  158.           delay(15);
  159.           DS18B20_get_Temperature();//温度取值和处理
  160.           delay(15);//等待采样转换完成   
  161.           if(flag==1)//温度正负判断
  162.             LCD1602_DIS_CHAR(2,11,'+');//在第2行第10列显示+
  163.           else
  164.             LCD1602_DIS_CHAR(2,11,'-');//在第2行第10列显示-
  165.       
  166.           bai=Tem_u16%1000/100;//取转换百位
  167.           shi=Tem_u16%100/10;//取转换十位
  168.           ge=Tem_u16%10;//取转换个位      

  169.           LCD1602_DIS_CHAR(2,12,table3[bai]);//在设定地址写入百位
  170.           LCD1602_DIS_CHAR(2,13,table3[shi]);//在设定地址写入十位
  171.           LCD1602_DIS_CHAR(2,14,table3[ge]);//在设定地址写入个位
  172.                         
  173.           if(stemp2==1)//判定月份是否在范围内   
  174.           {      
  175.             if(stemp1==1)//判断小时是否在范围内  
  176.             {        
  177.               flag_KOC=1;//判断在月份内,符合小时范围内,继电器逻辑控制允许启动
  178.             }
  179.             else
  180.             {
  181.               flag_KOC=0;      
  182.             }
  183.           }
  184.           else//如果月份不在范围内,继电器逻辑控制不允许启动
  185.           {      
  186.             flag_KOC=0;   
  187.           }   
  188.           if(flag_KOC==1)
  189.           {
  190.             K_OC();//继电器逻辑控制
  191.           }
  192.           else
  193.           {
  194.             cj=1;            
  195.             K3=0;            
  196.             K2=0;            
  197.             K1=0;            
  198.             LCD1602_DIS_CHAR(1,15,'C');//在第1行第15列显示风机停止运转状态           
  199.           }
  200.         }
  201.         else
  202.         {
  203.           time=time+1;
  204.         }
  205.       }
  206.     }
  207. }
  208. /****************************************************************/
  209. //延时函数delay(),有形参Count用于控制延时函数执行次数,无返回值
  210. /****************************************************************/
  211. void delay(u16 Count)//延时函数
  212. {
  213.   Count=Count*200;
  214.   u8 i,j;
  215.   while (Count--)//Count形参控制延时次数
  216.   {
  217.     IWDG_KR=0xAA;//执行完成delay函数后“喂狗”
  218.     for(i=0;i<50;i++)
  219.       for(j=0;j<20;j++);
  220.   }
  221. }
  222. /****************************************************************/
  223. //延时函数delay_u(),有形参Count,无返回值
  224. /****************************************************************/
  225. void delay_u(u16 Count)
  226. {  
  227.   do{ }//直到型循环执行空操作
  228.   while(Count--);//Count形参控制执行次数影响延时时间
  229. }
  230. /****************************************************************/
  231. //延时函数delay_ms(),有形参Count用于控制延时函数执行次数,无返回值
  232. /****************************************************************/
  233. void delay_ms(u16 Count)//延时函数
  234. {
  235.   u16 i;     
  236.   while(Count--)
  237.     IWDG_KR=0xAA;//执行完成delay函数后“喂狗”
  238.     for(i=900;i>0;i--)
  239.     delay_u(1);
  240. }
  241. /****************************************************************/
  242. //LCD1602判忙函数LCD1602_Busy(),无形参和返回值
  243. /****************************************************************/
  244. void LCD1602_Busy(void)
  245. {     
  246.     LCDRS=0;              //判断写入类型0为命令1为数据      
  247.     LCDRW=1;
  248.     PB_DDR_DDR7=0;        //配置PB7为输入模式
  249.     PB_CR1_C17=0;         //配置PB7为悬浮输入模式
  250.     PB_CR2_C27=0;         //配置PB7关闭
  251.     do
  252.     {      
  253.       LCDEN=0;//使能清“0”   
  254.       LCDEN=1;//使能置“1”
  255.     }while(LCDBUSY==1);
  256.     LCDEN=0;
  257.     LCDRW=0;
  258.     delay(50);
  259.     PB_DDR_DDR7=1;        //配置PB7为输出模式
  260.     PB_CR1_C17=1;         //配置PB7为推挽输出模式
  261.     PB_CR2_C27=0;         //配置PB7低速
  262.     delay(50);
  263. }
  264. /****************************************************************/
  265. //LCD1602初始化函数LCD1602_init(),无形参和返回值
  266. /****************************************************************/
  267. void LCD1602_init(void)
  268. {
  269.   LCD1602_Write(0x02,0);//数据总线为4位
  270.   LCD1602_Write(0x28,0);//数据总线为4位,显示2行,5*7点阵/每字符  
  271.   LCD1602_DIS_swich(1,0,0);//设置开显示,不显示光标
  272.   LCD1602_Write(0x06,0);//写入新数据后显示屏整体不移动仅光标右移
  273.   LCD1602_DIS_Clear();//LCD1602清屏命令
  274.   add_word();//加载自造字到CGRAM
  275. }
  276. /****************************************************************/
  277. //显示字符函数LCD1602_DIS(),有形参无返回值
  278. /****************************************************************/
  279. void LCD1602_DIS(u8 val)
  280. {
  281.   if(val==0)//系统初始化界面显示
  282.   {
  283.     LCD1602_Write(0x01,0);//写入清屏命令
  284.     u8 i;//定义控制循环变量i
  285.     LCD1602_Write(0x80,0);//选择第一行
  286.     for(i=0;i<16;i++)
  287.     {
  288.       LCD1602_Write(table0[i],1);//写入table1[]内容
  289.       delay(5);
  290.     }
  291.     LCD1602_Write(0xC0,0);//选择第二行
  292.     for(i=0;i<16;i++)
  293.     {
  294.       LCD1602_Write('>',1);//带延时逐一显示字符“*”模拟进度条
  295.       delay(100);
  296.     }
  297.     flag_DIS=0;//屏幕标志位 ,系统初始化界面
  298.   }  
  299.   if(val==1)//正常工作界面显示,时钟 温度 风机工作状态
  300.   {
  301.     LCD1602_Write(0x01,0);//写入清屏命令
  302.     LCD1602_Write(0x80,0);//选择第一行
  303.     LCD1602_DIS_CHAR(1,0,' ');
  304.     LCD1602_DIS_CHAR(1,1,' ');
  305.     LCD1602_DIS_CHAR(1,2,0x00);
  306.     LCD1602_DIS_CHAR(1,3,' ');
  307.     LCD1602_DIS_CHAR(1,4,' ');
  308.     LCD1602_DIS_CHAR(1,5,0x01);
  309.     LCD1602_DIS_CHAR(1,6,' ');
  310.     LCD1602_DIS_CHAR(1,7,' ');
  311.     LCD1602_DIS_CHAR(1,8,0x02);
  312.     LCD1602_DIS_CHAR(1,9,' ');
  313.     LCD1602_DIS_CHAR(1,10,' ');
  314.     LCD1602_DIS_CHAR(1,11,' ');
  315.     LCD1602_DIS_CHAR(1,12,' ');
  316.     LCD1602_DIS_CHAR(1,13,' ');
  317.     LCD1602_DIS_CHAR(1,14,' ');
  318.     LCD1602_DIS_CHAR(1,15,' ');

  319.     LCD1602_DIS_CHAR(2,0,' ');
  320.     LCD1602_DIS_CHAR(2,1,' ');
  321.     LCD1602_DIS_CHAR(2,2,':');
  322.     LCD1602_DIS_CHAR(2,3,' ');
  323.     LCD1602_DIS_CHAR(2,4,' ');
  324.     LCD1602_DIS_CHAR(2,5,':');
  325.     LCD1602_DIS_CHAR(2,6,' ');
  326.     LCD1602_DIS_CHAR(2,7,' ');
  327.     LCD1602_DIS_CHAR(2,8,' ');
  328.     LCD1602_DIS_CHAR(2,9,'T');
  329.     LCD1602_DIS_CHAR(2,10,':');
  330.     LCD1602_DIS_CHAR(2,11,' ');
  331.     LCD1602_DIS_CHAR(2,12,' ');
  332.     LCD1602_DIS_CHAR(2,13,' ');
  333.     LCD1602_DIS_CHAR(2,14,' ');
  334.     LCD1602_DIS_CHAR(2,15,0x05);//在设定地址写入个位
  335.     read_18b20_flag();//进入正常工作界面后,重新检测温度并且对控制风机状态标志位初始化
  336.     flag_DIS=1;//屏幕标志位 ,正常工作界面显示,时钟 温度 风机工作状态     
  337.   }  
  338.   if(val==2)//设置风机调速控制温度值界面
  339.   {
  340.     LCD1602_Write(0x01,0);//写入清屏命令
  341.     LCD1602_Write(0x80,0);//选择第一行
  342.     LCD1602_DIS_CHAR(1,0,'S');
  343.     LCD1602_DIS_CHAR(1,1,':');
  344.     LCD1602_DIS_CHAR(1,2,'T');
  345.     LCD1602_DIS_CHAR(1,3,'<');
  346.     LCD1602_DIS_CHAR(1,4,ASC_shi(OPT[0]));
  347.     LCD1602_DIS_CHAR(1,5,ASC_ge(OPT[0]));
  348.     LCD1602_DIS_CHAR(1,6,' ');
  349.     LCD1602_DIS_CHAR(1,7,' ');
  350.     LCD1602_DIS_CHAR(1,8,'H');
  351.     LCD1602_DIS_CHAR(1,9,':');
  352.     LCD1602_DIS_CHAR(1,10,'T');
  353.     LCD1602_DIS_CHAR(1,11,'>');
  354.     LCD1602_DIS_CHAR(1,12,ASC_shi(OPT[1]));
  355.     LCD1602_DIS_CHAR(1,13,ASC_ge(OPT[1]));
  356.     LCD1602_DIS_CHAR(1,14,' ');
  357.     LCD1602_DIS_CHAR(1,15,' ');

  358.     LCD1602_DIS_CHAR(2,0,'M');
  359.     LCD1602_DIS_CHAR(2,1,':');
  360.     LCD1602_DIS_CHAR(2,2,ASC_shi(OPT[2]));
  361.     LCD1602_DIS_CHAR(2,3,ASC_ge(OPT[2]));
  362.     LCD1602_DIS_CHAR(2,4,'<');
  363.     LCD1602_DIS_CHAR(2,5,'T');
  364.     LCD1602_DIS_CHAR(2,6,'>');
  365.     LCD1602_DIS_CHAR(2,7,ASC_shi(OPT[3]));
  366.     LCD1602_DIS_CHAR(2,8,ASC_ge(OPT[3]));
  367.     LCD1602_DIS_CHAR(2,9,' ');
  368.     LCD1602_DIS_CHAR(2,10,' ');
  369.     LCD1602_DIS_CHAR(2,11,' ');
  370.     LCD1602_DIS_CHAR(2,12,' ');
  371.     LCD1602_DIS_CHAR(2,13,' ');
  372.     LCD1602_DIS_CHAR(2,14,' ');
  373.     LCD1602_DIS_CHAR(2,15,' ');//在设定地址写入个位
  374.     LCD1602_DIS_CHAR_S(1,4,1);//在设定地址显示光标闪烁
  375.     flag_DIS=2;//屏幕标志位 ,设置风机调速控制温度值界面
  376.   }
  377.   if(val==3)//设置系统时钟界面
  378.   {
  379.     LCD1602_Write(0x01,0);//写入清屏命令
  380.     LCD1602_Write(0x80,0);//选择第一行第1列
  381.     LCD1602_DIS_CHAR(1,0,'Y');
  382.     LCD1602_DIS_CHAR(1,1,'Y');
  383.     LCD1602_DIS_CHAR(1,2,'M');
  384.     LCD1602_DIS_CHAR(1,3,'M');
  385.     LCD1602_DIS_CHAR(1,4,'D');
  386.     LCD1602_DIS_CHAR(1,5,'D');
  387.     LCD1602_DIS_CHAR(1,6,' ');
  388.     LCD1602_DIS_CHAR(1,7,'W');
  389.     LCD1602_DIS_CHAR(1,8,' ');
  390.     LCD1602_DIS_CHAR(1,9,'h');
  391.     LCD1602_DIS_CHAR(1,10,'h');
  392.     LCD1602_DIS_CHAR(1,11,'m');
  393.     LCD1602_DIS_CHAR(1,12,'m');
  394.     LCD1602_DIS_CHAR(1,13,'s');
  395.     LCD1602_DIS_CHAR(1,14,'s');
  396.     LCD1602_DIS_CHAR(1,15,' ');

  397.     LCD1602_DIS_CHAR(2,0,' ');
  398.     LCD1602_DIS_CHAR(2,1,' ');
  399.     LCD1602_DIS_CHAR(2,2,' ');
  400.     LCD1602_DIS_CHAR(2,3,' ');
  401.     LCD1602_DIS_CHAR(2,4,' ');
  402.     LCD1602_DIS_CHAR(2,5,' ');
  403.     LCD1602_DIS_CHAR(2,6,' ');
  404.     LCD1602_DIS_CHAR(2,7,' ');
  405.     LCD1602_DIS_CHAR(2,8,' ');
  406.     LCD1602_DIS_CHAR(2,9,' ');
  407.     LCD1602_DIS_CHAR(2,10,' ');
  408.     LCD1602_DIS_CHAR(2,11,' ');
  409.     LCD1602_DIS_CHAR(2,12,' ');
  410.     LCD1602_DIS_CHAR(2,13,' ');
  411.     LCD1602_DIS_CHAR(2,14,' ');
  412.     LCD1602_DIS_CHAR(2,15,' ');//在设定地址写入个位
  413.     LCD1602_DIS_CHAR_S(2,0,1);//在设定地址显示光标闪烁
  414.     flag_DIS=3;//屏幕标志位 ,设置系统时钟界面
  415.   }
  416.   if(val==4)//设置风机允许运行时间的参数界面
  417.   {
  418.     LCD1602_Write(0x01,0);//写入清屏命令
  419.     LCD1602_Write(0x80,0);//选择第一行
  420.     LCD1602_DIS_CHAR(1,0,'R');
  421.     LCD1602_DIS_CHAR(1,1,'U');
  422.     LCD1602_DIS_CHAR(1,2,'N');
  423.     LCD1602_DIS_CHAR(1,3,'_');
  424.     LCD1602_DIS_CHAR(1,4,'h');
  425.     LCD1602_DIS_CHAR(1,5,':');
  426.     LCD1602_DIS_CHAR(1,6,ASC_shi(OPT[4]));
  427.     LCD1602_DIS_CHAR(1,7,ASC_ge(OPT[4]));
  428.     LCD1602_DIS_CHAR(1,8,'<');
  429.     LCD1602_DIS_CHAR(1,9,'h');
  430.     LCD1602_DIS_CHAR(1,10,'h');
  431.     LCD1602_DIS_CHAR(1,11,'>');
  432.     LCD1602_DIS_CHAR(1,12,ASC_shi(OPT[5]));
  433.     LCD1602_DIS_CHAR(1,13,ASC_ge(OPT[5]));
  434.     LCD1602_DIS_CHAR(1,14,' ');
  435.     LCD1602_DIS_CHAR(1,15,' ');

  436.     LCD1602_DIS_CHAR(2,0,'R');
  437.     LCD1602_DIS_CHAR(2,1,'U');
  438.     LCD1602_DIS_CHAR(2,2,'N');
  439.     LCD1602_DIS_CHAR(2,3,'_');
  440.     LCD1602_DIS_CHAR(2,4,'M');
  441.     LCD1602_DIS_CHAR(2,5,':');
  442.     LCD1602_DIS_CHAR(2,6,ASC_shi(OPT[6]));
  443.     LCD1602_DIS_CHAR(2,7,ASC_ge(OPT[6]));
  444.     LCD1602_DIS_CHAR(2,8,'<');
  445.     LCD1602_DIS_CHAR(2,9,'M');
  446.     LCD1602_DIS_CHAR(2,10,'M');
  447.     LCD1602_DIS_CHAR(2,11,'>');
  448.     LCD1602_DIS_CHAR(2,12,ASC_shi(OPT[7]));
  449.     LCD1602_DIS_CHAR(2,13,ASC_ge(OPT[7]));
  450.     LCD1602_DIS_CHAR(2,14,' ');
  451.     LCD1602_DIS_CHAR(2,15,' ');//在设定地址写入个位
  452.     LCD1602_DIS_CHAR_S(1,6,1);//在设定地址显示光标闪烁
  453.     flag_DIS=4;//屏幕标志位 ,设置风机允许运行时间的参数界面
  454.   }
  455. }
  456. /****************************************************************/
  457. //写入液晶模组命令或数据函数LCD1602_Write(),有形参cmdordata
  458. //和writetype,无返回值。
  459. /****************************************************************/
  460. void LCD1602_Write(u8 cmdordata,u8 writetype)
  461. {
  462.     LCD1602_Busy();//LCD1602判忙
  463.     LCDRS=writetype;//判断写入类型0为命令1为数据   
  464.     LCDDATA &= 0x0F; //清高四位   
  465.     LCDDATA|=cmdordata & 0xF0; //写高四位   
  466.     LCDEN=1;delay(5);//使能置“1”
  467.     LCDEN=0;delay(5);//使能清“0”
  468.     cmdordata=cmdordata << 4; //低四位移到高四位
  469.     LCDDATA &= 0x0F; //清高四位  
  470.     LCDDATA |= cmdordata & 0xF0; //写低四位
  471.     LCDEN=1;delay(5);//使能置“1”
  472.     LCDEN=0;delay(5);//使能清“0”
  473. }
  474. /****************************************************************/
  475. //写入液晶模组自造字“月”add_yue(),无形参和返回值
  476. /****************************************************************/
  477. void add_word() //自造字库“年、月、日、$、元、℃、↑、10”
  478. {
  479.   int a,b;
  480.   for (a=0x40;a<0x48;a++)//年
  481.   {
  482.     LCD1602_Write(a,0);   
  483.     b=a&0x0f;
  484.     LCD1602_Write(add_word_year[b],1);   
  485.   }  
  486.   for (a=0x48;a<0x50;a++)//月
  487.   {
  488.     LCD1602_Write(a,0);   
  489.     b=a&0x07;
  490.     LCD1602_Write(add_word_month[b],1);   
  491.   }
  492.   for (a=0x50;a<0x58;a++)//日
  493.   {
  494.     LCD1602_Write(a,0);   
  495.     b=a&0x0f;
  496.     LCD1602_Write(add_word_day[b],1);   
  497.   }  
  498.   for (a=0x68;a<0x70;a++)//℃
  499.   {
  500.     LCD1602_Write(a,0);
  501.     b=a&0x07;
  502.     LCD1602_Write(add_word_Temp[b],1);   
  503.   }
  504. }
  505. /****************************************************************/
  506. //设定地址写入字符函数LCD1602_DIS_CHAR(),有形参x、y、z无返回值
  507. //x表示1602液晶的行,y表示列地址,z表示欲写入的字符
  508. /****************************************************************/
  509. void LCD1602_DIS_CHAR(u8 x,u8 y,u8 z)
  510. {
  511.   LCD1602_DIS_swich(1,0,0);//设置开显示,不显示光标
  512.   u8 address;
  513.   if(x==1)//若欲显示在第一行
  514.     address=0x80+y;//第一行的行首地址+列地址
  515.   else
  516.     address=0xC0+y;//第二行的行首地址+列地址
  517.   LCD1602_Write(address,0);//设定显示地址
  518.   LCD1602_Write(z,1);//写入字符数据
  519. }
  520. /****************************************************************/
  521. //设定地址写入光标函数声明LCD1602_DIS_CHAR_S(),有形参x、y无返回值
  522. //x表示1602液晶的行,y表示列地址,z=1表示开显示,显示光标,z=0表示开显示,不显示光标
  523. /****************************************************************/
  524. void LCD1602_DIS_CHAR_S(u8 x,u8 y,u8 z)
  525. {
  526.   if(z==1)   
  527.     LCD1602_DIS_swich(1,1,1);//设置开显示,显示光标
  528.   else
  529.     LCD1602_DIS_swich(1,0,0);//设置开显示,不显示光标
  530.   u8 address;
  531.   if(x==1)//若欲显示在第一行
  532.     address=0x80+y;//第一行的行首地址+列地址
  533.   else
  534.     address=0xC0+y;//第二行的行首地址+列地址
  535.   LCD1602_Write(address,0);//设定显示地址
  536. }
  537. /****************************************************************/
  538. //设定LCD1602液晶显示与光标显示的函数LCD1602_DIS_swich(),有形参x、y、z无返回值
  539. //x表示1602显示,y表示1602光标显示,z表示1602光标闪动
  540. /****************************************************************/
  541. void LCD1602_DIS_swich(u8 x,u8 y,u8 z)
  542. {
  543.   int a=0x08;
  544.   if(x==1)   
  545.   {
  546.     a=a|0x04;
  547.   }
  548.   if(y==1)
  549.   {
  550.     a=a|0x02;
  551.   }
  552.   if(z==1)
  553.   {
  554.    a=a|0x01;
  555.   }
  556.   LCD1602_Write(a,0);
  557. }
  558. /****************************************************************/
  559. //设定LCD1602液晶画面平移的函数LCD1602_screen_sidesway(),有形参x无返回值
  560. //x=1画面向右移动一个字符;X=0画面向左移动一个字符
  561. /****************************************************************/
  562. void LCD1602_screen_sidesway(u8 x)
  563. {
  564.   if(x==1)
  565.   {
  566.     LCD1602_Write(0x1c,0);//画面向右平移一个字符位
  567.   }
  568.   else
  569.   {
  570.     LCD1602_Write(0x18,0);//画面向左平移一个字符位
  571.   }
  572. }
  573. /****************************************************************/
  574. //设定LCD1602液晶画面平移的函数LCD1602_cursor_sidesway(),有形参x,y无返回值
  575. //x=1光标向右移动;X=0光标向左移动 y代表多少个字符
  576. /****************************************************************/
  577. void LCD1602_cursor_sidesway(u8 x,u8 y)
  578. {
  579.   for(int i=0;i<y;i++)
  580.   {
  581.     if(x==1)
  582.     {  
  583.       LCD1602_Write(0x14,0);//光标向右平移一个字符位
  584.     }
  585.     else
  586.     {
  587.       LCD1602_Write(0x10,0);//光标向左平移一个字符位
  588.     }
  589.   }
  590. }
  591. /****************************************************************/
  592. //设定LCD1602液晶清屏LCD1602_DIS_Clear(),无形参无返回值
  593. /****************************************************************/
  594. void LCD1602_DIS_Clear()
  595. {
  596.   LCD1602_Write(0x01,0);//写入清屏命令
  597. }
  598. /****************************************************************/
  599. //GPIO配置函数GPIO_Init(),无返回值
  600. /****************************************************************/
  601. void GPIO_Init(void)
  602. {
  603.   PD_DDR_DDR2=1;        //配置PD2为输出模式 K1
  604.   PD_CR1_C12=1;         //配置PD2为推挽输出模式 K1
  605.   PD_CR2_C22=0;         //配置PD2低速率输出 K1
  606.   PD_DDR_DDR3=1;        //配置PD3为输出模式 K2
  607.   PD_CR1_C13=1;         //配置PD3为推挽输出模式 K2
  608.   PD_CR2_C23=0;         //配置PD3低速率输出 K2
  609.   PD_DDR_DDR4=1;        //配置PD4为输出模式 K3
  610.   PD_CR1_C14=1;         //配置PD4为推挽输出模式 K3
  611.   PD_CR2_C24=0;         //配置PD4低速率输出 K3
  612.   PD_DDR_DDR5=1;        //配置PD5为输出模式 K4
  613.   PD_CR1_C15=1;         //配置PD5为推挽输出模式 K4
  614.   PD_CR2_C25=0;         //配置PD5低速率输出 K4
  615.   K4=0;                 //K4初始化为不输出
  616.   
  617.   PC_DDR_DDR1=1;        //配置PC1为输出模式
  618.   PC_CR1_C11=1;         //配置PC1为推挽输出模式
  619.   PC_CR2_C21=0;         //配置PC1低速率输出
  620.   
  621.   PC_DDR_DDR2=1;        //配置PC2为输出模式
  622.   PC_CR1_C12=1;         //配置PC2为推挽输出模式
  623.   PC_CR2_C22=0;         //配置PC2低速率输出
  624.   LCDRW=0;              //配置LCD1602为写入模式
  625.   
  626.   PC_DDR_DDR3=1;        //配置PC3为输出模式
  627.   PC_CR1_C13=1;         //配置PC3为推挽输出模式
  628.   PC_CR2_C23=0;         //配置PC3低速率输出
  629.   
  630.   PC_DDR_DDR6=1;        //配置PC6引脚(SCL)为输出模式
  631.   PC_CR1_C16=1;         //配置PC6引脚(SCL)为推挽输出模式
  632.   PC_CR2_C26=0;         //配置PC6引脚(SCL)低速率输出模式
  633.   
  634.   PB_DDR=0xF0;          //配置PB端口为输出模式
  635.   PB_CR1=0xFF;          //配置PB端口为推挽输出模式
  636.   PB_CR2=0x00;          //配置PB端口低速率输出
  637.   LCDDATA=0xFF;         //初始化PB端口全部输出高电平
  638.   
  639.   DS18B20_DQ_DDR(1);    //配置DQ单总线为输出模式
  640.   DS18B20_DQ=1;         //配置DQ单总线为高电平状态
  641.   delay(300);           //延时等待配置稳定  
  642. }
  643. /****************************************************************/
  644. //设备初始化时序产生函数DS18B20_reset(),无形参和返回值
  645. /****************************************************************/
  646. void DS18B20_reset(void)
  647. {
  648.   u8 x;//变量x用于取回总线电平状态
  649.   DS18B20_DQ_DDR(1);//改变DQ引脚方向性为输出方式
  650.   DS18B20_DQ=1;//控制器首先应为高电平状态
  651.   delay_u(910);//延时大约800us
  652.   DS18B20_DQ=0;//控制器拉低总线发送复位脉冲
  653.   delay_u(910);//拉低时间大约800us
  654.   DS18B20_DQ=1;//控制器释放总线
  655.   delay_u(30);//DS18B20等待大约30us
  656.   DS18B20_DQ_DDR(0);//改变DQ引脚方向性为输入方式
  657.   delay_u(30);//等待DS18B20应答脉冲大约30us
  658.   x=PA_IDR_IDR3;//取回总线电平状态
  659.   while(x);//等待应答脉冲出现低电平  
  660.   delay_u(900);//控制器等待至少480us
  661. }
  662. /****************************************************************/
  663. //设备DQ引脚方向性配置函数DS18B20_DQ_DDR(),有形参ddr无返回值
  664. /****************************************************************/
  665. void DS18B20_DQ_DDR(u8 ddr)
  666. {
  667.   if(ddr==1)//配置为输出方式
  668.   {
  669.     PA_DDR_DDR3=1;//配置PA3引脚为输出引脚
  670.     PA_CR1_C13=1;//配置PA3引脚为推挽输出模式
  671.     PA_CR2_C23=0;//配置PA3引脚低速率输出模式
  672.   }
  673.   else//配置为输入方式
  674.   {
  675.     PA_DDR_DDR3=0;//配置PA3引脚为输入引脚
  676.     PA_CR1_C13=1;// 配置PA3引脚为弱上拉模式   
  677.     PA_CR2_C23=0;//禁止PA3引脚外部中断功能
  678.   }
  679. }
  680. /****************************************************************/
  681. //设备初始化函数DS18B20_init(),无形参和返回值
  682. /****************************************************************/
  683. void DS18B20_init(void)
  684. {
  685.   DS18B20_reset();//DS18B20初始化时序
  686.   delay_u(500);//等待初始化结束
  687.   DS18B20_Wbyte(0xCC);//写ROM指令(跳过ROM)
  688.   DS18B20_Wbyte(0x44);//写功能指令(温度转换)  
  689. }
  690. /****************************************************************/
  691. //设备写一个字节函数DS18B20_Wbyte(),有形参xbyte无返回值
  692. /****************************************************************/
  693. void DS18B20_Wbyte(u8 xbyte)
  694. {
  695.   u8 i,x=0;//i为循环控制变量,x为取位运算变量
  696.   DS18B20_DQ_DDR(1);//改变DQ引脚方向性为输出方式
  697.   for(i=0;i<8;i++)//8次循环实现逐位写入
  698.   {
  699.     x=xbyte & 0x01;//从最低位取值到最高位
  700.     if(x)//写“1”
  701.     {
  702.       DS18B20_DQ=0;//DQ单总线拉低
  703.       delay_u(13);//延时大约15us
  704.       DS18B20_DQ=1;//DQ单总线写入“1”
  705.       delay_u(42);//延时大约45us
  706.       DS18B20_DQ=1;//最终保持高电平
  707.       delay_u(2);
  708.     }
  709.     else//写“0”
  710.     {
  711.       DS18B20_DQ=0;//DQ单总线拉低
  712.       delay_u(13);//延时大约15us
  713.       DS18B20_DQ=0;//DQ单总线写入“0”
  714.       delay_u(42);//延时大约45us
  715.       DS18B20_DQ=1;//最终保持高电平
  716.       delay_u(2);
  717.     }
  718.     xbyte=xbyte>>1;//右移一位实现逐位移出
  719.   }
  720. }
  721. /****************************************************************/
  722. //设备读字节函数DS18B20_Rbyte(),无形参有返回值rbyte
  723. /****************************************************************/
  724. u8 DS18B20_Rbyte(void)
  725. {
  726.   u8 rbyte=0,i=0,tempbit=0;//rbyte是最终得到的字节,i为循环控制变量
  727.   //tempbit为逐位取出的中间运算变量
  728.   for(i=0;i<8;i++)//8次循环实现逐位拼合
  729.   {
  730.     tempbit=DS18B20_Rbit();//读取单个位
  731.     rbyte=rbyte>>1;//右移实现将高低位排列
  732.     rbyte=rbyte|tempbit;//或运算移入数据
  733.   }
  734.   return rbyte;//返回最终字节
  735. }
  736. /****************************************************************/
  737. //设备读取单个位函数DS18B20_Rbit(),无形参有返回值rbit
  738. /****************************************************************/
  739. u8 DS18B20_Rbit(void)
  740. {
  741.   u8 rbit=0,x=0;//rbit是最终位数据,x是取状态变量
  742.   DS18B20_DQ_DDR(1);//改变DQ引脚方向性为输出方式
  743.   DS18B20_DQ=0;//DQ单总线写入“0”
  744.   delay_u(13);//延时大约15us
  745.   DS18B20_DQ=1;//释放DQ单总线
  746.   DS18B20_DQ_DDR(0);//改变DQ引脚方向性为输入方式
  747.   //delay_u(30);//延时大约15us【旧版本,应适当缩小这个时间】
  748.   delay_u(9);//延时小于15us,在10us左右【新版本】
  749.   x=PA_IDR_IDR3;//获取单总线电平状态
  750.   if(x)//状态判定
  751.     rbit=0x80;//若为高电平则最高位“1”得到0x80反之为初始值0
  752.   delay_u(54);//延时大约60us
  753.   return rbit;////返回最终位数据
  754. }
  755. /****************************************************************/
  756. //设备温度获取和转换函数DS18B20_get_Temperature(),无形参和返回值
  757. /****************************************************************/
  758. void DS18B20_get_Temperature(void)
  759. {
  760.   u8 msb_byte=0,lsb_byte=0;//msb是温度值高位,lsb是温度值低位
  761.   DS18B20_reset();//初始化时序
  762.   delay_u(900);//等待初始化稳定
  763.   DS18B20_Wbyte(0xCC);//写ROM指令(跳过ROM)
  764.   DS18B20_Wbyte(0xBE);//写功能指令(读暂存器)
  765.   delay_u(900);//等待配置稳定  
  766.   lsb_byte=DS18B20_Rbyte();//读取第一个低位数据字节
  767.   msb_byte=DS18B20_Rbyte();//读取第二个高位数据字节  
  768.   Tem_u16=msb_byte;//先将高位给全局变量Tem_u16
  769.   Tem_u16=Tem_u16<<8;//然后将Tem_u16低8位左移为高8位
  770.   Tem_u16=Tem_u16|lsb_byte;//拼合低位给Tem_u16低8位  
  771.   if(Tem_u16<=0x07FF)//温度值正负判断
  772.     flag=1;//温度值为正
  773.   else
  774.     flag=0;//温度值为负
  775.   Tem_f=Tem_u16*0.0625;//乘以0.0625最小分辨值得到12位温度实际值
  776.   Tem_u16=(u16)(Tem_f+0.5);//4舍5入得到温度整数值  
  777. }
  778. /****************************************************************/
  779. //ADC2初始化函数ADC_init(),无形参,无返回值
  780. /****************************************************************/
  781. void ADC_init(void)
  782. {
  783.   //1.选择模拟通道,按需配置中断
  784.   ADC_CSR=0x00;//选择通道AIN0(PB0),禁止中断
  785.   //2.配置分频系数,明确转换模式
  786.   ADC_CR1=0x02;//配置预分频为fMaster/2,连续转换模式
  787.   //3.配置触发事件,明确对齐方式
  788.   ADC_CR2=0x08;//禁止外部触发,数据右对齐(先读低再读高)
  789.   //ADC_CR2=0x00;//禁止外部触发,数据左对齐(先读高再读低)
  790.   //4.初始配置模拟通道(无中断悬浮输入)
  791.   PB_DDR_DDR0=0;//配置PB0端口为输入模式
  792.   PB_CR1_C10=0;//配置PB0端口为悬浮输入模式
  793.   PB_CR2_C20=0;//配置PB0端口禁止外部中断
  794.   //5.按需禁止/使能施密特触发器功能
  795.   ADC_TDRL=0x00;//使能斯密特触发器
  796.   //6.使能ADC上电唤醒并禁用I/O输出功能
  797.   ADC_CR1|=0x01;//首次将ADON位置1用于唤醒
  798.   //7.启动ADC转换并获取转换数据
  799.   //ADC_GET();//用户编写的ADC转换函数
  800. }
  801. /****************************************************************/
  802. //ADC2模数转换函数ADC_GET(),无形参,无返回值
  803. /****************************************************************/
  804. void ADC_GET(void)
  805. {
  806.   u8 num=0;//循环控制变量,用于控制次数
  807.   ADC_CR1=0x02;//配置预分频为fMaster/2,连续转换模式
  808.   ADC_CR1|=0x01;//首次将ADON位置1用于唤醒
  809.   ADC_CR1|=0x01;//再次将ADON位置1用于启动ADC转换
  810.   while(num<10)//采10次结果
  811.   {   
  812.     while((ADC_CSR & 0x80)==0);//等待ADC转换结束
  813.     ADC_CSR &= 0x7F;//清除ADC转换完成标志位
  814.     AD_Vtemp[num]=(u16)ADC_DRL;//先将ADC转换数据低位赋值
  815.     AD_Vtemp[num]|=(u16)ADC_DRH<<8;//再将左移8位后的高位数据与原低位数据进行或连接
  816.     //(高位数据)+(低位数据)=完整ADC采样数据结果
  817.     num++;//循环控制变量自增
  818.   }
  819.   ADC_CR1 &= 0xFD;//关闭ADC转换
  820. }
  821. /****************************************************************/
  822. //平均值滤波函数AVG_AD_Vtemp(),无形参,无返回值
  823. /****************************************************************/
  824. void AVG_AD_Vtemp(void)
  825. {
  826.   u8 i,j;//定义排序用内外层循环变量i和j
  827.   u16 temp;//定义中间“暂存”变量temp
  828.   for(i=10;i>=1;i--)//外层循环
  829.   {
  830.     for(j=0;j<(i-1);j++)//内层循环
  831.     {
  832.       if(AD_Vtemp[j]>AD_Vtemp[j+1])//数值比较
  833.       {
  834.         temp=AD_Vtemp[j];//数值换位
  835.         AD_Vtemp[j]=AD_Vtemp[j+1];
  836.         AD_Vtemp[j+1]=temp;
  837.       }
  838.     }
  839.   }
  840.   for(i=2;i<=7;i++)//去掉2个最低去掉2个最高
  841.     AD_val+=AD_Vtemp[i];//将中间6个数值累加
  842.   AD_val=(u16)(AD_val/6);//累加和求平均值
  843. }
  844. /****************************************************************/
  845. //I2C_SDA串行数据引脚方向性配置函数I2C_SDA_DDR(),有形参ddr,无返回值
  846. /****************************************************************/
  847. void I2C_SDA_DDR(u8 ddr)
  848. {
  849.   if(ddr==1)//配置为输出方式
  850.   {
  851.     PC_DDR_DDR7=1;//配置PC7引脚(SDA)为输出引脚
  852.     PC_CR1_C17=1;//配置PC7引脚(SDA)为推挽输出模式
  853.     PC_CR2_C27=0;//配置PC7引脚(SDA)低速率输出模式
  854.   }
  855.   else//配置为输入方式
  856.   {
  857.     PC_DDR_DDR7=0;//配置PC7引脚(SDA)为输入引脚
  858.     PC_CR1_C17=1;//配置PC7引脚(SDA)为弱上拉输入模式
  859.     PC_CR2_C27=0;//禁止PC7引脚(SDA)外部中断功能
  860.   }
  861. }
  862. /****************************************************************/
  863. //I2C总线起始信号配置函数I2C_START(),无形参,无返回值
  864. /****************************************************************/
  865. void I2C_START(void)
  866. {
  867.   I2C_SDA_DDR(1);//配置SDA引脚为推挽输出模式
  868.   SDA_OUT=1;//SDA引脚置为高电平
  869.   SCL=1;//SCL引脚置为高电平
  870.   delay(1);//延时等待
  871.   SDA_OUT=0;//将SDA置低产生下降沿(产生起始信号)
  872.   delay(1);//延时等待
  873.   SCL=0;//将SCL置低产生下降沿(允许SDA数据传送)
  874.   delay(1);//延时等待
  875. }
  876. /****************************************************************/
  877. //I2C总线终止信号配置函数I2C_STOP(),无形参,无返回值
  878. /****************************************************************/
  879. void I2C_STOP(void)
  880. {
  881.   I2C_SDA_DDR(1);//配置SDA引脚为推挽输出模式
  882.   SDA_OUT=0;//SDA引脚置为低电平
  883.   SCL=0;//SCL引脚置为低电平
  884.   delay(1);//延时等待
  885.   SCL=1;//将SCL引脚置高产生上升沿
  886.   delay(1);//延时等待
  887.   SDA_OUT=1;//将SDA引脚置高产生上升沿(产生终止信号)
  888.   delay(1);//延时等待
  889. }
  890. /****************************************************************/
  891. //I2C总线单字节数据写入函数I2C_Write8Bit(u8 DAT),有形参DAT
  892. //有返回值I2C_Write_ACK(应答信号变量值),若返回值为“0”则有从机应答
  893. //若返回值为“1”则从机无应答
  894. /****************************************************************/
  895. u8 I2C_Write8Bit(u8 DAT)
  896. {
  897.   u8 num,I2C_Write_ACK=0;//定义循环控制变量num
  898.   //定义应答信号变量I2C_Write_ACK
  899.   I2C_SDA_DDR(1);//配置SDA引脚为推挽输出模式
  900.   delay(1);//延时等待
  901.   for(num=0x80;num!=0;num>>=1)//执行8次循环
  902.   {
  903.     if((DAT&num)==0)//按位“与”判断DAT每一位值
  904.       SDA_OUT=0;//判断数值为“0”送出低电平
  905.     else
  906.       SDA_OUT=1;//判断数值为“1”送出高电平
  907.     delay(1);//延时等待
  908.     SCL=1;//拉高SCL引脚以保持SDA引脚数据稳定
  909.     delay(1);//延时等待
  910.     SCL=0;//拉低SCL引脚以允许SDA引脚数据变动
  911.     delay(1);//延时等待
  912.   }
  913.   SDA_OUT=1;//置高SDA引脚电平(释放数据线)
  914.   delay(1);//延时等待
  915.   SCL=1;//拉高SCL产生应答位时钟
  916.   delay(1);//延时等待
  917.   I2C_SDA_DDR(0);//配置SDA引脚为弱上拉输入模式
  918.   delay(1);//延时等待
  919.   I2C_Write_ACK=SDA_IN;//取回SDA线上电平赋值给应答信号变量
  920.   delay(1);//延时等待
  921.   SCL=0;//将SCL引脚置低
  922.   delay(5);
  923.   return I2C_Write_ACK;//将应答信号变量值进行返回
  924. }
  925. /****************************************************************/
  926. //单字节数据读出函数(发送无应答)I2C_Read8BitNACK()
  927. //无形参,有返回值(读出的单字节数据)
  928. /****************************************************************/
  929. u8 I2C_Read8BitNACK(void)
  930. {
  931.   u8 x,I2CDATA;//定义循环控制变量x,读出数据暂存变量I2CDATA
  932.   I2C_SDA_DDR(1);//配置SDA引脚为推挽输出模式
  933.   SDA_OUT=1;//首先确保主机释放SDA
  934.   SCL=0;//置低SCL引脚以允许从机发送下一位
  935.   delay(1);//延时等待
  936.   I2C_SDA_DDR(0);//配置SDA引脚为弱上拉输入模式
  937.   delay(1);//延时等待
  938.   for(x=0x80;x!=0;x>>=1)//从高位到低位依次进行
  939.   {
  940.     delay(1);//延时等待
  941.     SCL=1;//将SCL引脚置为高电平
  942.     if(SDA_IN==0)//读取SDA引脚的电平状态并进行判定
  943.       I2CDATA&=~x;//判定为“0”则将I2CDATA中对应位清零
  944.     else
  945.       I2CDATA|=x;//判定为“1”则将I2CDATA中对应位置“1”
  946.     delay(1);//延时等待
  947.     SCL=0;//置低SCL引脚以允许从机发送下一位
  948.   }
  949.   I2C_SDA_DDR(1);//配置SDA引脚为推挽输出模式
  950.   delay(1);//延时等待
  951.   SDA_OUT=1;//8位数据发送后拉高SDA引脚发送“无应答信号”
  952.   delay(1);//延时等待
  953.   SCL=1;//将SCL引脚置为高电平
  954.   delay(1);//延时等待
  955.   SCL=0;//将SCL引脚置为低电平完成“无应答位”并保持总线
  956.   return I2CDATA;//将读出的单字节数据进行返回
  957. }
  958. /****************************************************************/
  959. //单字节数据读出函数(发送应答)I2C_Read8BitACK()
  960. //无形参,有返回值(读出的单字节数据)
  961. /****************************************************************/
  962. u8 I2C_Read8BitACK(void)
  963. {
  964.   u8 x,I2CDATA;//定义循环控制变量x,读出数据暂存变量I2CDATA
  965.   I2C_SDA_DDR(1);//配置SDA引脚为推挽输出模式
  966.   delay(1);//延时等待
  967.   SDA_OUT=1;//首先确保主机释放SDA
  968.   delay(1);//延时等待
  969.   I2C_SDA_DDR(0);//配置SDA引脚为弱上拉输入模式
  970.   delay(1);//延时等待
  971.   for(x=0x80;x!=0;x>>=1)//从高位到低位依次进行
  972.   {
  973.     delay(1);//延时等待
  974.     SCL=1;//将SCL引脚置为高电平
  975.     if(SDA_IN==0)//读取SDA引脚的电平状态并进行判定
  976.       I2CDATA&=~x;//判定为“0”则将I2CDATA中对应位清零
  977.     else
  978.       I2CDATA|=x;//判定为“1”则将I2CDATA中对应位置“1”
  979.     delay(1);//延时等待
  980.     SCL=0;//置低SCL引脚以允许从机发送下一位
  981.   }
  982.   I2C_SDA_DDR(1);//配置SDA引脚为推挽输出模式
  983.   delay(1);//延时等待
  984.   SDA_OUT=0;//8位数据发送后置低SDA引脚发送“应答信号”
  985.   delay(1);//延时等待
  986.   SCL=1;//将SCL引脚置为高电平
  987.   delay(1);//延时等待
  988.   SCL=0;//将SCL引脚置为低电平完成“应答位”并保持总线
  989.   return I2CDATA;//将读出的单字节数据进行返回
  990. }
  991. /****************************************************************/
  992. //DS3231读出单个字节函数DA3231_ReadByte(),有形参ADDR
  993. //ADDR为欲读出数据的地址,有返回值DS3231_DATA(读出的单字节数据)
  994. /****************************************************************/
  995. u8 DS3231_ReadByte(u8 ADDR)
  996. {
  997.   u8 DS3231_DATA;//定义变量用于存放读出数据
  998.   I2C_START();//产生I2C通信起始信号
  999.   I2C_Write8Bit(0xD0);//写入(器件地址+写)指令
  1000.   I2C_Write8Bit(ADDR);//指定欲读取DS3231芯片的地址
  1001.   I2C_START();//产生I2C通信起始信号
  1002.   I2C_Write8Bit(0xD1);//写入(器件地址+读)指令  
  1003.   DS3231_DATA=I2C_Read8BitNACK();//单字节读取(发送无应答)
  1004.   I2C_STOP();//产生I2C通信终止信号
  1005.   return DS3231_DATA;//返回实际读取到的数据值
  1006. }
  1007. /****************************************************************/
  1008. //DS3231写入单个字节函数DS3231_WriteByte(),有形参ADDR、DAT
  1009. //ADDR为欲写入地址,DAT为欲写入数据,无返回值
  1010. /****************************************************************/
  1011. void DS3231_WriteByte(u8 ADDR,u8 DAT)
  1012. {
  1013.   I2C_START();//产生I2C通信起始信号
  1014.   I2C_Write8Bit(0xD0);//写入(器件地址+写)指令
  1015.   I2C_Write8Bit(ADDR);//指定欲写入DS3231芯片的地址
  1016.   I2C_Write8Bit(DAT);//写入实际数据
  1017.   I2C_STOP();//产生I2C通信终止信号
  1018. }
  1019. /****************************************************************/
  1020. //BCD转换为Byte函数BCD2HEX(),有形参val
  1021. //val为欲转换的BCD码,返回Byte
  1022. /****************************************************************/
  1023. u8 BCD2HEX(u8 val)    //BCD转换为Byte
  1024. {
  1025.     u8 temp;
  1026.     temp=val&0x0f;
  1027.     val>>=4;
  1028.     val&=0x0f;
  1029.     val*=10;
  1030.     temp+=val;   
  1031.     return temp;
  1032. }
  1033. /****************************************************************/
  1034. //Byte码转换为BCD码函数HEX2BCD(),有形参val
  1035. //val为欲转换Byte码,返回值为BCD码
  1036. /****************************************************************/
  1037. u8 HEX2BCD(u8 val)    //Byte码转换为BCD码
  1038. {
  1039.     u8 i,j,k;
  1040.     i=val/10;
  1041.     j=val;
  1042.     k=j+(i<<4);
  1043.     return k;
  1044. }
  1045. /****************************************************************/
  1046. //解锁EEPROM函数unlock_EEPROM(),无形参,有返回值“0”或者“1”
  1047. //若返回值为“1”则解锁失败,若返回值为“0”则解锁成功
  1048. /****************************************************************/
  1049. u8 unlock_EEPROM(void)
  1050. {
  1051.   //1.首先写入MASS密匙以解锁EEPROM
  1052.   FLASH_DUKR=0xAE;
  1053.   FLASH_DUKR=0x56;
  1054.   //2.判断DUL位是否解锁成功
  1055.   if(FLASH_IAPSR & 0x80)
  1056.     return 1;//解锁失败
  1057.   else
  1058.     return 0;//解锁成功
  1059. }
  1060. /****************************************************************/
  1061. //OPT选项字节配置函数OPTconfig(),无形参,无返回值
  1062. /****************************************************************/
  1063. void OPTconfig(void)
  1064. {
  1065.   do//输入MASS密匙用于解锁DATA EEPROM的写保护
  1066.   {
  1067.     FLASH_DUKR=0xAE;//硬件密匙1
  1068.     FLASH_DUKR=0x56;//硬件密匙2
  1069.   }
  1070.   while(!(FLASH_IAPSR & 0x08));//等待解锁Flash完成
  1071.   FLASH_CR2 =0x80;//对选项字节进行写操作被使能
  1072.   FLASH_NCR2=0x7F;//互补控制寄存器FLASH_NCR2中的NOPT位要为“0”
  1073.   *((u8*)0X4000)= OPT[0];//配置低于多少温度风机停机条件
  1074.   *((u8*)0x4001)= OPT[1];//配置大于多少温度风机中速启动条件
  1075.   *((u8*)0x4002)= OPT[2];//配置小于多少温度风机中速启动条件
  1076.   *((u8*)0x4003)= OPT[3];//配置大于多少温度风机高速启动条件
  1077.   *((u8*)0x4004)= OPT[4];//配置小于哪个小时风机允许启动条件
  1078.   *((u8*)0x4005)= OPT[5];//配置大于哪个小时风机允许启动条件
  1079.   *((u8*)0x4006)= OPT[6];//配置小于哪个月份风机允许启动条件
  1080.   *((u8*)0x4007)= OPT[7];//配置大于哪个月份风机允许启动条件
  1081.   FLASH_IAPSR=0x40;//程序存储区(FLASH)上锁,数据存储区(EEPROM)上锁
  1082. }
  1083. /****************************************************************/
  1084. //读取时钟并显示函数read_DS3231(),无形参,无返回值
  1085. /****************************************************************/
  1086. void read_DS3231(void)
  1087. {
  1088.   u8 stemp,shi1,ge1;
  1089.   GETDS3231_DAT=DS3231_ReadByte(0x00);//读取指定地址的数据秒
  1090.   stemp=BCD2HEX(GETDS3231_DAT);
  1091.   shi1=stemp/10;//取转换十位
  1092.   ge1=stemp%10;//取转换个位
  1093.   LCD1602_DIS_CHAR(2,6,table3[shi1]);//在第2行第6列显示读回数据   
  1094.   LCD1602_DIS_CHAR(2,7,table3[ge1]);//在第2行第7列显示读回数据
  1095.   if(table3[shi1]=='0' & table3[ge1]=='0' | flag_time==0)
  1096.   {
  1097.     GETDS3231_DAT=DS3231_ReadByte(0x01);//读取指定地址的数据分
  1098.     stemp=BCD2HEX(GETDS3231_DAT);
  1099.     shi1=stemp/10;//取转换十位
  1100.     ge1=stemp%10;//取转换个位
  1101.     LCD1602_DIS_CHAR(2,3,table3[shi1]);//在第2行第3列显示读回数据   
  1102.     LCD1602_DIS_CHAR(2,4,table3[ge1]);//在第2行第4列显示读回数据
  1103.   }
  1104.   if(table3[shi1]=='0' & table3[ge1]=='0' | flag_time==0)
  1105.   {
  1106.     GETDS3231_DAT=DS3231_ReadByte(0x02);//读取指定地址的数据小时
  1107.     GETDS3231_DAT&=0x3f;
  1108.     stemp=BCD2HEX(GETDS3231_DAT);
  1109.     if(stemp>OPT1[5] & stemp<OPT1[4])
  1110.     {
  1111.       stemp1=1;
  1112.     }
  1113.     else
  1114.     {
  1115.       stemp1=0;
  1116.     }
  1117.     shi1=stemp/10;//取转换十位
  1118.     ge1=stemp%10;//取转换个位
  1119.     LCD1602_DIS_CHAR(2,0,table3[shi1]);//在第2行第0列显示读回数据   
  1120.     LCD1602_DIS_CHAR(2,1,table3[ge1]);//在第2行第1列显示读回数据
  1121.   }
  1122.   if(table3[shi1]=='0' & table3[ge1]=='0' | flag_time==0)
  1123.   {
  1124.     GETDS3231_DAT=DS3231_ReadByte(0x04);//读取指定地址的数据日
  1125.     GETDS3231_DAT&=0x3f;
  1126.     stemp=BCD2HEX(GETDS3231_DAT);
  1127.     shi1=stemp/10;//取转换十位
  1128.     ge1=stemp%10;//取转换个位
  1129.     LCD1602_DIS_CHAR(1,6,table3[shi1]);//在第2行第0列显示读回数据   
  1130.     LCD1602_DIS_CHAR(1,7,table3[ge1]);//在第2行第1列显示读回数据
  1131.     GETDS3231_DAT=DS3231_ReadByte(0x05);//读取指定地址的数据月
  1132.     GETDS3231_DAT&=0x3f;
  1133.     stemp=BCD2HEX(GETDS3231_DAT);
  1134.     if(stemp>OPT1[7] & stemp<OPT1[6])
  1135.     {
  1136.       stemp2=1;
  1137.     }
  1138.     else
  1139.     {
  1140.       stemp2=0;
  1141.     }
  1142.     shi1=stemp/10;//取转换十位
  1143.     ge1=stemp%10;//取转换个位
  1144.     LCD1602_DIS_CHAR(1,3,table3[shi1]);//在第2行第0列显示读回数据   
  1145.     LCD1602_DIS_CHAR(1,4,table3[ge1]);//在第2行第1列显示读回数据
  1146.     GETDS3231_DAT=DS3231_ReadByte(0x06);//读取指定地址的数据年
  1147.     GETDS3231_DAT&=0x3f;
  1148.     stemp=BCD2HEX(GETDS3231_DAT);
  1149.     shi1=stemp/10;//取转换十位
  1150.     ge1=stemp%10;//取转换个位
  1151.     LCD1602_DIS_CHAR(1,0,table3[shi1]);//在第2行第0列显示读回数据   
  1152.     LCD1602_DIS_CHAR(1,1,table3[ge1]);//在第2行第1列显示读回数据
  1153.     GETDS3231_DAT=DS3231_ReadByte(0x03);//读取指定地址的数据星期
  1154.     stemp=BCD2HEX(GETDS3231_DAT);        
  1155.     ge1=stemp%10;//取转换个位
  1156.     u8 week[4];//星期显示数组
  1157.     switch(ge1)
  1158.     {
  1159.       case 1:
  1160.         week[0]='M';
  1161.         week[1]='o';
  1162.         week[2]='n';
  1163.         week[3]=' ';
  1164.         break;
  1165.       case 2:
  1166.         week[0]='T';
  1167.         week[1]='u';
  1168.         week[2]='e';
  1169.         week[3]='s';
  1170.         break;
  1171.       case 3:
  1172.         week[0]='W';
  1173.         week[1]='e';
  1174.         week[2]='d';
  1175.         week[3]=' ';
  1176.         break;
  1177.       case 4:
  1178.         week[0]='T';
  1179.         week[1]='h';
  1180.         week[2]='u';
  1181.         week[3]='r';
  1182.         break;
  1183.       case 5:
  1184.         week[0]='F';
  1185.         week[1]='r';
  1186.         week[2]='i';
  1187.         week[3]=' ';
  1188.         break;
  1189.       case 6:
  1190.         week[0]='S';
  1191.         week[1]='a';
  1192.         week[2]='t';
  1193.         week[3]=' ';
  1194.         break;
  1195.       case 7:
  1196.         week[0]='S';
  1197.         week[1]='u';
  1198.         week[2]='n';
  1199.         week[3]=' ';
  1200.         break;
  1201.         default: break;
  1202.     }
  1203.     LCD1602_DIS_CHAR(1,10,week[0]);//在第2行第0列显示读回数据   
  1204.     LCD1602_DIS_CHAR(1,11,week[1]);//在第2行第1列显示读回数据
  1205.     LCD1602_DIS_CHAR(1,12,week[2]);//在第2行第1列显示读回数据
  1206.     LCD1602_DIS_CHAR(1,13,week[3]);//在第2行第1列显示读回数据
  1207.     flag_time=1;
  1208.   }
  1209. }
  1210. /****************************************************************/
  1211. //上电读取温度判断工作位标志函数read_18b20_flag(),无形参,无返回值
  1212. /****************************************************************/
  1213. void read_18b20_flag(void)
  1214. {
  1215.   DS18B20_init();       //初始化DS18B20设备
  1216.   delay(15);
  1217.   DS18B20_get_Temperature();//温度取值和处理
  1218.   delay(15);//等待采样转换完成
  1219.   if(Tem_u16>OPT1[3] & Tem_u16<OPT1[2])
  1220.   {
  1221.     cj=1;         
  1222.   }
  1223.   if(Tem_u16>OPT1[1] | Tem_u16==OPT1[1])
  1224.   {
  1225.     cj=2;
  1226.   }
  1227.   if(Tem_u16<OPT1[0] | Tem_u16==OPT1[0])
  1228.   {
  1229.     cj=1;
  1230.   }
  1231. }
  1232. /****************************************************************/
  1233. //读取OPT参数函数OPT_Load(),无形参,无返回值
  1234. /****************************************************************/
  1235. void OPT_Load(void)
  1236. {
  1237.   //读取STM8EEPROM数据
  1238.     OPT[0]=*((u8*)0X4000);//配置低于多少温度风机停机条件
  1239.     OPT[1]=*((u8*)0X4001);//配置大于多少温度风机高速启动条件
  1240.     OPT[2]=*((u8*)0X4002);//配置小于多少温度风机中速启动条件
  1241.     OPT[3]=*((u8*)0X4003);//配置大于多少温度风机中速启动条件
  1242.     OPT[4]=*((u8*)0X4004);//配置小于哪个小时风机允许启动条件
  1243.     OPT[5]=*((u8*)0X4005);//配置大于哪个小时风机允许启动条件
  1244.     OPT[6]=*((u8*)0X4006);//配置小于哪个月份风机允许启动条件
  1245.     OPT[7]=*((u8*)0X4007);//配置大于哪个月份风机允许启动条件
  1246.     OPT1[0]=BCD2HEX(OPT[0]);//配置低于多少温度风机停机条件
  1247.     OPT1[1]=BCD2HEX(OPT[1]);//配置大于多少温度风机高速启动条件
  1248.     OPT1[2]=BCD2HEX(OPT[2]);//配置小于多少温度风机中速启动条件
  1249.     OPT1[3]=BCD2HEX(OPT[3]);//配置大于多少温度风机中速启动条件
  1250.     OPT1[4]=BCD2HEX(OPT[4]);//配置小于哪个小时风机允许启动条件
  1251.     OPT1[5]=BCD2HEX(OPT[5]);//配置大于哪个小时风机允许启动条件
  1252.     OPT1[6]=BCD2HEX(OPT[6]);//配置小于哪个月份风机允许启动条件
  1253.     OPT1[7]=BCD2HEX(OPT[7]);//配置大于哪个月份风机允许启动条件
  1254. }
  1255. /****************************************************************/
  1256. //继电器逻辑控制函数K_OC(),无形参,无返回值
  1257. /****************************************************************/
  1258. void K_OC(void)
  1259. {
  1260.   if(Tem_u16>OPT1[3] & Tem_u16<OPT1[2] & cj==1)         
  1261.   {            
  1262.     cj=2;            
  1263.     K3=0;            
  1264.     delay_ms(500);            
  1265.     K1=1;            
  1266.     delay_ms(500);            
  1267.     K2=1;            
  1268.     LCD1602_DIS_CHAR(1,15,'M');//在第1行第15列显示风机中速运转状态
  1269.   }            
  1270.   if(Tem_u16>OPT1[1] | Tem_u16==OPT1[1] & cj==2)         
  1271.   {            
  1272.     cj=1;            
  1273.     K2=0;            
  1274.     delay_ms(500);               
  1275.     K1=1;            
  1276.     delay_ms(500);               
  1277.     K3=1;            
  1278.     LCD1602_DIS_CHAR(1,15,'H');//在第1行第15列显示风机高速运转状态           
  1279.   }         
  1280.   if(Tem_u16<OPT1[0] | Tem_u16==OPT1[0])         
  1281.   {                     
  1282.     cj=1;            
  1283.     K3=0;            
  1284.     K2=0;            
  1285.     K1=0;            
  1286.     LCD1602_DIS_CHAR(1,15,'S');//在第1行第15列显示风机停止运转状态           
  1287.   }
  1288. }
  1289. /****************************************************************/
  1290. //键盘检测函数key_Testing(),无形参,无返回值
  1291. /****************************************************************/
  1292. void key_Testing(void)
  1293. {  
  1294.   
  1295.   ADC_GET();//启动AD转换获取AD采样数据AD_val
  1296.   AVG_AD_Vtemp();//求6次平均值(去掉2个最低去掉2个最高)
  1297.   delay(50);//延时
  1298.   GETvoltage=(u16)(AD_val*4.92);//4.8828125);//计算对应电压(mV)
  1299.   AD_val=0;//清零ADC转换数据
  1300.   qian=GETvoltage/1000;//取转换电压千位
  1301.   bai=GETvoltage%1000/100;//取转换电压百位
  1302.   if(qian==0)
  1303.   {         
  1304.     if(bai<1){KS=1;KEY_NO='1';}//S1按键电压0判断低于0.1
  1305.     else if(bai<5){KS=1;KEY_NO='2';}//S2按键电压0.31判断0.1至0.5之间
  1306.     else if(bai<8){KS=1;KEY_NO='3';}//S3按键电压0.622判断0.5至0.8之间
  1307.     else {KS=1;KEY_NO='A';}//S4按键电压0.938判断0.8至1.0之间
  1308.         
  1309.   }        
  1310.   else if(qian==1)        
  1311.   {         
  1312.     if(bai<1){KS=1;KEY_NO='A';}//S4按键电压0.938判断1.0至1.1之间         
  1313.     else if(bai<5){KS=1;KEY_NO='4';}//S5按键电压1.243判断1.1至1.5之间         
  1314.     else if(bai<7){KS=1;KEY_NO='5';}//S6按键电压1.554判断1.5至1.7之间         
  1315.     else {KS=1;KEY_NO='6';}//S7按键电压1.863判断1.7至2.0之间        
  1316.   }        
  1317.   else if(qian==2)        
  1318.   {         
  1319.     if(bai<3){KS=1;KEY_NO='B';}//S8按键电压2.185判断2.0至2.3之间         
  1320.     else if(bai<7){KS=1;KEY_NO='7';}//S9按键电压2.495判断2.3至2.7之间         
  1321.     else {KS=1;KEY_NO='8';}//S10按键电压2.814判断2.7至3.0之间        
  1322.   }        
  1323.   else if(qian==3)        
  1324.   {         
  1325.     if(bai<3){KS=1;KEY_NO='9';}//S11按键电压3.133判断3.0至3.2之间         
  1326.     else if(bai<6){KS=1;KEY_NO='C';}//S12按键电压3.428判断3.2至3.6之间         
  1327.     else {KS=1;KEY_NO='E';}//S13按键电压3.734判断3.6至4.0之间         
  1328.   }        
  1329.   else if(qian==4)        
  1330.   {         
  1331.     if(bai<2){KS=1;KEY_NO='0';}//S14按键电压4.057判断4.0至4.2之间         
  1332.     else if(bai<5){KS=1;KEY_NO='K';}//S15按键电压4.375判断4.2至4.5之间         
  1333.     else if(bai<9){KS=1;KEY_NO='D';}//S16按键电压4.691判断4.5至4.8之间         
  1334.     else KS=0;//无按键按下        
  1335.   }        
  1336.   delay(200);//延时等待
  1337.   if(KEY_NO==KEY_NO1)
  1338.   {
  1339.     KS=0;   
  1340.   }
  1341.   if(KS==1)//判断是否有按键按下
  1342.   {
  1343.     if(KEY_NO=='A')//控制屏幕背景灯
  1344.     {
  1345.       K4=!K4;
  1346.     }
  1347.     if(flag_DIS==1)//只有在正常工作界面是这些案件操作功能有效
  1348.     {
  1349.       if(KEY_NO=='B')//时间设置界面
  1350.       {
  1351.         LCD1602_DIS(3);
  1352.       }
  1353.       if(KEY_NO=='C')//温度控制参数设置界面
  1354.       {
  1355.         LCD1602_DIS(2);
  1356.       }
  1357.       if(KEY_NO=='D')//风机允许运行时间参数设置界面
  1358.       {
  1359.         LCD1602_DIS(4);
  1360.       }   
  1361.     }
  1362.     if(flag_DIS==3)//时间设置参数输入
  1363.     {      
  1364.       switch(flag_save)
  1365.       {      
  1366.       case 0://年数据输入
  1367.         if(KEY_NO=='K')
  1368.         {            
  1369.           LCD1602_DIS_CHAR_S(2,1,1);//在设定地址显示光标闪烁            
  1370.           flag_save++;
  1371.           break;         
  1372.         }         
  1373.         mt=KEY_NO;         
  1374.         mt=mt<<4;         
  1375.         if(KEY_NO!='B')         
  1376.         {            
  1377.           LCD1602_DIS_CHAR(2,0,KEY_NO);            
  1378.           LCD1602_DIS_CHAR_S(2,0,1);//在设定地址显示光标闪烁         
  1379.         }         
  1380.         break;
  1381.       case 1:         
  1382.         if(KEY_NO=='K')         
  1383.         {            
  1384.           year=mt+lt;            
  1385.           LCD1602_DIS_CHAR_S(2,2,1);//在设定地址显示光标闪烁            
  1386.           flag_save++;            
  1387.           break;         
  1388.         }         
  1389.         lt=KEY_NO;
  1390.         lt&=0x0f;         
  1391.         if(KEY_NO!='K')         
  1392.         {
  1393.           LCD1602_DIS_CHAR(2,1,KEY_NO);            
  1394.           LCD1602_DIS_CHAR_S(2,1,1);//在设定地址显示光标闪烁         
  1395.         }
  1396.         break;      
  1397.       case 2://月数据输入
  1398.         if(KEY_NO=='K')
  1399.         {            
  1400.           LCD1602_DIS_CHAR_S(2,3,1);//在设定地址显示光标闪烁            
  1401.           flag_save++;
  1402.           break;         
  1403.         }         
  1404.         mt=KEY_NO;         
  1405.         mt=mt<<4;         
  1406.         if(KEY_NO!='K')         
  1407.         {            
  1408.           LCD1602_DIS_CHAR(2,2,KEY_NO);            
  1409.           LCD1602_DIS_CHAR_S(2,2,1);//在设定地址显示光标闪烁         
  1410.         }         
  1411.         break;
  1412.       case 3:         
  1413.         if(KEY_NO=='K')         
  1414.         {            
  1415.           month=mt+lt;            
  1416.           LCD1602_DIS_CHAR_S(2,4,1);//在设定地址显示光标闪烁            
  1417.           flag_save++;            
  1418.           break;         
  1419.         }         
  1420.         lt=KEY_NO;         
  1421.         lt&=0x0f;         
  1422.         if(KEY_NO!='K')         
  1423.         {            
  1424.           LCD1602_DIS_CHAR(2,3,KEY_NO);            
  1425.           LCD1602_DIS_CHAR_S(2,3,1);//在设定地址显示光标闪烁         
  1426.         }
  1427.         break;        
  1428.       case 4://日数据输入
  1429.         if(KEY_NO=='K')
  1430.         {            
  1431.           LCD1602_DIS_CHAR_S(2,5,1);//在设定地址显示光标闪烁            
  1432.           flag_save++;
  1433.           break;         
  1434.         }         
  1435.         mt=KEY_NO;         
  1436.         mt=mt<<4;         
  1437.         if(KEY_NO!='K')         
  1438.         {            
  1439.           LCD1602_DIS_CHAR(2,4,KEY_NO);            
  1440.           LCD1602_DIS_CHAR_S(2,4,1);//在设定地址显示光标闪烁         
  1441.         }         
  1442.         break;
  1443.       case 5:         
  1444.         if(KEY_NO=='K')         
  1445.         {            
  1446.           day=mt+lt;            
  1447.           LCD1602_DIS_CHAR_S(2,7,1);//在设定地址显示光标闪烁            
  1448.           flag_save++;            
  1449.           break;         
  1450.         }         
  1451.         lt=KEY_NO;         
  1452.         lt&=0x0f;         
  1453.         if(KEY_NO!='K')         
  1454.         {            
  1455.           LCD1602_DIS_CHAR(2,5,KEY_NO);            
  1456.           LCD1602_DIS_CHAR_S(2,5,1);//在设定地址显示光标闪烁         
  1457.         }
  1458.         break;      
  1459.       case 6://星期数据输入
  1460.         if(KEY_NO=='K')
  1461.         {      
  1462.           week=mt;  
  1463.           LCD1602_DIS_CHAR_S(2,9,1);//在设定地址显示光标闪烁            
  1464.           flag_save++;
  1465.           break;         
  1466.         }         
  1467.         mt=KEY_NO;         
  1468.         mt&=0x0f;;         
  1469.         if(KEY_NO!='K')         
  1470.         {            
  1471.           LCD1602_DIS_CHAR(2,7,KEY_NO);            
  1472.           LCD1602_DIS_CHAR_S(2,7,1);//在设定地址显示光标闪烁         
  1473.         }         
  1474.         break;              
  1475.       case 7://小时数据输入
  1476.         if(KEY_NO=='K')
  1477.         {            
  1478.           LCD1602_DIS_CHAR_S(2,10,1);//在设定地址显示光标闪烁            
  1479.           flag_save++;
  1480.           break;         
  1481.         }         
  1482.         mt=KEY_NO;         
  1483.         mt=mt<<4;         
  1484.         if(KEY_NO!='K')         
  1485.         {            
  1486.           LCD1602_DIS_CHAR(2,9,KEY_NO);            
  1487.           LCD1602_DIS_CHAR_S(2,9,1);//在设定地址显示光标闪烁         
  1488.         }         
  1489.         break;
  1490.       case 8:         
  1491.         if(KEY_NO=='K')         
  1492.         {            
  1493.           hour=mt+lt;            
  1494.           LCD1602_DIS_CHAR_S(2,11,1);//在设定地址显示光标闪烁            
  1495.           flag_save++;            
  1496.           break;         
  1497.         }         
  1498.         lt=KEY_NO;         
  1499.         lt&=0x0f;         
  1500.         if(KEY_NO!='K')         
  1501.         {            
  1502.           LCD1602_DIS_CHAR(2,10,KEY_NO);            
  1503.           LCD1602_DIS_CHAR_S(2,10,1);//在设定地址显示光标闪烁         
  1504.         }
  1505.         break;         
  1506.       case 9://分数据输入
  1507.         if(KEY_NO=='K')
  1508.         {            
  1509.           LCD1602_DIS_CHAR_S(2,12,1);//在设定地址显示光标闪烁            
  1510.           flag_save++;
  1511.           break;         
  1512.         }         
  1513.         mt=KEY_NO;         
  1514.         mt=mt<<4;         
  1515.         if(KEY_NO!='K')         
  1516.         {            
  1517.           LCD1602_DIS_CHAR(2,11,KEY_NO);            
  1518.           LCD1602_DIS_CHAR_S(2,11,1);//在设定地址显示光标闪烁         
  1519.         }         
  1520.         break;
  1521.       case 10:         
  1522.         if(KEY_NO=='K')         
  1523.         {            
  1524.           branch=mt+lt;            
  1525.           LCD1602_DIS_CHAR_S(2,13,1);//在设定地址显示光标闪烁            
  1526.           flag_save++;            
  1527.           break;         
  1528.         }
  1529.         lt=KEY_NO;         
  1530.         lt&=0x0f;         
  1531.         if(KEY_NO!='K')         
  1532.         {            
  1533.           LCD1602_DIS_CHAR(2,12,KEY_NO);            
  1534.           LCD1602_DIS_CHAR_S(2,12,1);//在设定地址显示光标闪烁         
  1535.         }
  1536.         break;         
  1537.       case 11://秒数据输入
  1538.         if(KEY_NO=='K')
  1539.         {            
  1540.           LCD1602_DIS_CHAR_S(2,14,1);//在设定地址显示光标闪烁            
  1541.           flag_save++;
  1542.           break;         
  1543.         }         
  1544.         mt=KEY_NO;         
  1545.         mt=mt<<4;         
  1546.         if(KEY_NO!='K')         
  1547.         {            
  1548.           LCD1602_DIS_CHAR(2,13,KEY_NO);            
  1549.           LCD1602_DIS_CHAR_S(2,13,1);//在设定地址显示光标闪烁         
  1550.         }         
  1551.         break;
  1552.       case 12:         
  1553.         if(KEY_NO=='K')         
  1554.         {            
  1555.           second=mt+lt;            
  1556.           LCD1602_DIS_CHAR_S(2,15,1);//在设定地址显示光标闪烁
  1557.           DS3231_WriteByte(0x00,second);//秒
  1558.           DS3231_WriteByte(0x01,branch);//分
  1559.           DS3231_WriteByte(0x02,hour);//小时
  1560.    
  1561.           DS3231_WriteByte(0x03,week);//星期
  1562.          
  1563.           DS3231_WriteByte(0x04,day);//天
  1564.           DS3231_WriteByte(0x05,month);//月
  1565.           DS3231_WriteByte(0x06,year);//年
  1566.           KEY_NO='E';//模拟取消按键,进入正常工作界面            
  1567.           break;         
  1568.         }
  1569.         lt=KEY_NO;         
  1570.         lt&=0x0f;         
  1571.         if(KEY_NO!='K')
  1572.         {            
  1573.           LCD1602_DIS_CHAR(2,14,KEY_NO);            
  1574.           LCD1602_DIS_CHAR_S(2,14,1);//在设定地址显示光标闪烁         
  1575.         }
  1576.         break;
  1577.     default:
  1578.       break;
  1579.       }
  1580.       if(KEY_NO=='E')
  1581.       {
  1582.         flag_time=0;//第一次读全日期时间标志位
  1583.         flag_save=0;//参数储存标志位
  1584.         LCD1602_DIS(1);//正常运行界面
  1585.       }
  1586.     }
  1587.     if(flag_DIS==2)//温度参数设置输入
  1588.     {      
  1589.       switch(flag_save)
  1590.       {      
  1591.       case 0://低于多少温度,风机停机
  1592.         if(KEY_NO=='K')
  1593.         {            
  1594.           LCD1602_DIS_CHAR_S(1,5,1);//在设定地址显示光标闪烁            
  1595.           flag_save++;
  1596.           break;         
  1597.         }
  1598.         mt=KEY_NO;
  1599.         mt=mt<<4;         
  1600.         if(KEY_NO!='C')
  1601.         {            
  1602.           LCD1602_DIS_CHAR(1,4,KEY_NO);            
  1603.           LCD1602_DIS_CHAR_S(1,4,1);//在设定地址显示光标闪烁
  1604.         }         
  1605.         break;
  1606.       case 1:         
  1607.         if(KEY_NO=='K')
  1608.         {            
  1609.           OPT[0]=mt+lt;            
  1610.           LCD1602_DIS_CHAR_S(1,12,1);//在设定地址显示光标闪烁            
  1611.           flag_save++;            
  1612.           break;         
  1613.         }         
  1614.         lt=KEY_NO;         
  1615.         lt&=0x0f;         
  1616.         if(KEY_NO!='K')         
  1617.         {            
  1618.           LCD1602_DIS_CHAR(1,5,KEY_NO);            
  1619.           LCD1602_DIS_CHAR_S(1,5,1);//在设定地址显示光标闪烁         
  1620.         }
  1621.         break;
  1622.       case 2://大于多少温度风机高速运行
  1623.         if(KEY_NO=='K')
  1624.         {            
  1625.           LCD1602_DIS_CHAR_S(1,13,1);//在设定地址显示光标闪烁            
  1626.           flag_save++;
  1627.           break;         
  1628.         }         
  1629.         mt=KEY_NO;         
  1630.         mt=mt<<4;         
  1631.         if(KEY_NO!='K')         
  1632.         {            
  1633.           LCD1602_DIS_CHAR(1,12,KEY_NO);            
  1634.           LCD1602_DIS_CHAR_S(1,12,1);//在设定地址显示光标闪烁         
  1635.         }         
  1636.         break;
  1637.       case 3:         
  1638.         if(KEY_NO=='K')         
  1639.         {            
  1640.           OPT[1]=mt+lt;            
  1641.           LCD1602_DIS_CHAR_S(2,2,1);//在设定地址显示光标闪烁            
  1642.           flag_save++;            
  1643.           break;         
  1644.         }         
  1645.         lt=KEY_NO;         
  1646.         lt&=0x0f;         
  1647.         if(KEY_NO!='K')         
  1648.         {            
  1649.           LCD1602_DIS_CHAR(1,13,KEY_NO);            
  1650.           LCD1602_DIS_CHAR_S(1,13,1);//在设定地址显示光标闪烁         
  1651.         }
  1652.         break;        
  1653.       case 4://小于多少温度风机中速运行
  1654.         if(KEY_NO=='K')
  1655.         {            
  1656.           LCD1602_DIS_CHAR_S(2,3,1);//在设定地址显示光标闪烁            
  1657.           flag_save++;
  1658.           break;         
  1659.         }         
  1660.         mt=KEY_NO;         
  1661.         mt=mt<<4;         
  1662.         if(KEY_NO!='K')         
  1663.         {            
  1664.           LCD1602_DIS_CHAR(2,2,KEY_NO);            
  1665.           LCD1602_DIS_CHAR_S(2,2,1);//在设定地址显示光标闪烁         
  1666.         }         
  1667.         break;
  1668.       case 5:         
  1669.         if(KEY_NO=='K')         
  1670.         {            
  1671.           OPT[2]=mt+lt;            
  1672.           LCD1602_DIS_CHAR_S(2,7,1);//在设定地址显示光标闪烁            
  1673.           flag_save++;            
  1674.           break;         
  1675.         }         
  1676.         lt=KEY_NO;         
  1677.         lt&=0x0f;         
  1678.         if(KEY_NO!='K')         
  1679.         {            
  1680.           LCD1602_DIS_CHAR(2,3,KEY_NO);            
  1681.           LCD1602_DIS_CHAR_S(2,3,1);//在设定地址显示光标闪烁         
  1682.         }
  1683.         break;
  1684.       case 6://大于多少温度风机中速运行
  1685.         if(KEY_NO=='K')
  1686.         {            
  1687.           LCD1602_DIS_CHAR_S(2,8,1);//在设定地址显示光标闪烁            
  1688.           flag_save++;
  1689.           break;         
  1690.         }         
  1691.         mt=KEY_NO;         
  1692.         mt=mt<<4;         
  1693.         if(KEY_NO!='K')         
  1694.         {            
  1695.           LCD1602_DIS_CHAR(2,7,KEY_NO);            
  1696.           LCD1602_DIS_CHAR_S(2,7,1);//在设定地址显示光标闪烁         
  1697.         }
  1698.         break;
  1699. ……………………

  1700. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

附件里包含源代码(IAR)和控制器的详细说明书

0.png

全部资料51hei下载地址:
散热风机控制.zip (5.76 MB, 下载次数: 48)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:386877 发表于 2018-8-16 14:11 | 显示全部楼层
本帖最后由 13931582522 于 2018-8-16 14:30 编辑

源码,行行都有注释,采用的寄存器编程
回复

使用道具 举报

ID:387394 发表于 2018-8-17 20:04 | 显示全部楼层
THANKS
回复

使用道具 举报

ID:67041 发表于 2019-12-6 11:23 | 显示全部楼层
不错,感谢分享。本人虽然年纪大点,还是想学习一下STM8
回复

使用道具 举报

ID:71535 发表于 2020-1-9 22:06 | 显示全部楼层

初学的好教材,谢谢分享!!!
回复

使用道具 举报

ID:23844 发表于 2020-1-12 08:46 | 显示全部楼层
这个全带注释的不错,得下载一个学习学习
回复

使用道具 举报

ID:71535 发表于 2020-9-4 19:32 | 显示全部楼层
带注释的寄存器操作易于初学者学习理解,值得初学者学习学习、
回复

使用道具 举报

ID:98396 发表于 2020-9-7 09:14 | 显示全部楼层
/****************************************************************/
//设备初始化时序产生函数DS18B20_reset(),无形参和返回值
/****************************************************************/
void DS18B20_reset(void)
{
  u8 x;//变量x用于取回总线电平状态
  DS18B20_DQ_DDR(1);//改变DQ引脚方向性为输出方式
  DS18B20_DQ=1;//控制器首先应为高电平状态
  delay_u(910);//延时大约800us
  DS18B20_DQ=0;//控制器拉低总线发送复位脉冲
  delay_u(910);//拉低时间大约800us
  DS18B20_DQ=1;//控制器释放总线
  delay_u(30);//DS18B20等待大约30us
  DS18B20_DQ_DDR(0);//改变DQ引脚方向性为输入方式
  delay_u(30);//等待DS18B20应答脉冲大约30us

  x=PA_IDR_IDR3;//取回总线电平状态                        <------ 這裡有問題!
  while(x);//等待应答脉冲出现低电平                           <------


  delay_u(900);//控制器等待至少480us
}

應該改為 :
  do {
  x=PC_IDR_IDR3;//取回总线电平状态
  } while(x);//等待应答脉冲出现低电平  


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表