目录
[4.1 头文件](#4.1 头文件)
[4.2 驱动文件](#4.2 驱动文件)
[4.3 主函数代码](#4.3 主函数代码)
0.心得体会
这套题,刷新了我的认知:
1. 对于led的操作,不要定义单位的led,在io编程下总是会冲突,造成效果不好。然后我尝试了用与或进行位运算,但还是会造成引脚冲突。最后,我又尝试了定义一个led状态的变量,每次我都去改变这个变量,然后再将变量赋给P0端口,有大佬这样写出来了,但我还是失败了。于是,我想到了一个损招:本题只有3个led灯,因此建立了一个数组,将3个led的9种状态直接写出来。
**2.**对于继电器的操作,也不要定义继电器的一个引脚,直接对P0口进行操作。
**3.**主函数的循环中,最好的状态是只出现键值扫描函数、ds1302刷新函数、ds18b20刷新函数。然后外设的刷新采用中断一定时间产生一个标志位,外设读取标志位从而决定是否刷新。
**4.**led、继电器、数码管的刷新可以放进中断程序中,对应刷新时间为:20*50us,20*50us,50*50us。
**5.**对于io编程模式,要注意对锁存器常关闭。同时采用先赋值P0端口,再打开锁存器方式,这样有效防止数据冲突。
**6.**要注意,ds18b20读出来的温度是三位数,因此在进行比较时需要除以10再进行
1.题目如下
2.代码实现的思路
键值扫描
键值扫描通过keyrunning
函数实现。该函数检测外部按键的按下,并根据按键对key13_state
和SMG_flag
变量进行相应的修改。具体实现方式如下:
- 使用
C3
和C4
作为控制列,H3
和H4
作为行读取信号。 - 通过设置
C3
和C4
的电平状态,可以检测到与它们相对应行H3
和H4
的按键是否被按下。 - 按键
S13
用于切换继电器工作状态(key13_state
变量)。 - 按键
S12
用于切换显示模式(SMG_flag
变量)。 - 按键
S17
和S16
分别用于调整时钟模式和设置温度(在SMG_flag
为2和3时具有不同的功能)。
数码管窗口切换
数码管窗口切换是通过修改SMG_flag
变量实现的,该变量影响flash_SMG
函数中数码管显示的内容。
- 当
SMG_flag
为1时,显示温度; - 当
SMG_flag
为2时,显示时间; - 当
SMG_flag
为3时,显示设置的温度。
数码管的动态扫描
数码管的动态扫描通过flash_SMG
函数实现。该函数基于SMG_flag
和flash_count
变量,动态调整数码管显示的内容,实现动态扫描效果。通过在定时器中断服务程序中调用flash_SMG
函数,并且周期性地更改flash_count
的值来实现数码管的动态扫描。
继电器工作时L3闪烁,整点时刻L1灯光亮5秒
- 继电器的控制和LED(包括L3)的状态变化在
relay_ledrunning
函数中实现。 flag_5s
用于判断是否在整点时刻,影响L1的亮灯逻辑。count_100ms
在timer1_service
中断服务程序中翻转,用于实现L3的闪烁效果。- 当继电器工作时,根据温度与设定温度的关系以及
flag_5s
的值,通过调用state_relay
和state_led
函数,控制继电器的开关和L3、L1的亮灯逻辑。
3.变量列表
定义的常量和数组
duanma
和duanma_dot
:定义了数码管的显示码(不含/含小数点)。用于控制数码管显示数字0-9及特殊符号。led_state
:定义了LED灯的状态,对应L1至L3的开关状态。其中1点亮,0熄灭。
功能控制和状态变量
SMG_flag
:数码管显示模式标志,取值1到3,分别代表显示温度、时间和设置温度。key13_state
:切换工作模式,是一个位变量,0和1分别代表温度控制模式,和时间控制模式。ds1302_mode2
:用于控制数码管时间显示模式,是一个位变量,0和1分别代表正常显示"时分"和特殊显示"分秒"。flash_ds1302
和flash_temperature
:这两个位变量用于控制DS1302时间和DS18B20温度的刷新,1表示需要刷新,0表示不需要。set_temperature
:设定的温度值,用于温度控制逻辑,取值范围为10到99(摄氏度)。temperature
:DS18B20测量的实际温度值,用于显示和控制逻辑。
定时器和计数变量
count_50us
:定时器0的计数变量,用于控制50微秒的计时和相应的事件触发。flash_count
:用于数码管动态扫描的计数变量,控制数码管的显示内容和顺序。flag_5s
:一个位变量,用于标识是否在整点时刻亮灯5秒的状态。
4.代码参考
4.1 头文件
onewire.h
cpp
#ifndef __ONEWIRE_H__
#define __ONEWIRE_H__
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
void Delay_OneWire(unsigned int t);
#endif
ds1302.h
cpp
#ifndef __DS1302_H__
#define __DS1302_H__
void Write_Ds1302(unsigned char temp) ;
void Write_Ds1302_Byte( unsigned char address,unsigned char dat ) ;
unsigned char Read_Ds1302_Byte ( unsigned char address );
#endif
4.2 驱动文件
onewire.c
cpp
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <reg52.h>
sbit DQ = P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
ds1302.c
cpp
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
//
#include <reg52.h>
#include <intrins.h>
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
4.3 主函数代码
cpp
#include <reg52.h>
#include <intrins.h>
#include "ds1302.h"
#include "onewire.h"
sbit AUXR = 0x8e;
sbit C3 = P3^5;
sbit C4 = P3^4;
sbit H3 = P3^2;
sbit H4 = P3^3;
unsigned char code duanma[12] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xc1,0xbf};
unsigned char code duanma_dot[10] = { 0x40 , 0x79 , 0x24 , 0x30 , 0x10 , 0x12 , 0x02 , 0x78 , 0x00 , 0x10 };
unsigned char code write_ds1302_addr[7] = { 0x80 , 0x82 , 0x84 , 0x86 , 0x88 , 0x8a , 0x8c };
unsigned char code read_ds1302_addr[7] = { 0x81 , 0x83 , 0x85 , 0x87 , 0x89 , 0x8b , 0x8d };
unsigned char ds1302_time[8] = { 0x45 , 0x59 , 0x7 , 0x11 , 0x04 , 0x04 , 0x24 };
unsigned char code led_state[8] = { 0xff , 0xfb , 0xfd , 0xf9 , 0xfe , 0xfa , 0xfc , 0xf8 }; 对应L1,L2,L3,1点亮,0熄灭
// 000 001 010 011 100 101 110 111
void flash_SMG ();
void keyrunning ();
void relay_ledrunning ();
unsigned char SMG_flag = 1;
bit key13_state = 0;
bit ds1302_mode2 = 0;
void select_HC573 ( unsigned char channal )
{
switch ( channal )
{
case 4:
P2 = ( P2 & 0x1f ) | 0x80;
break;
case 5:
P2 = ( P2 & 0x1f ) | 0xa0;
break;
case 6:
P2 = ( P2 & 0x1f ) | 0xc0;
break;
case 7:
P2 = ( P2 & 0x1f ) | 0xe0;
break;
case 0:
P2 = ( P2 & 0x1f ) | 0x00;
break;
}
}
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{
select_HC573 ( 0 );
P0 = 0x01 << pos_SMG;
select_HC573( 6 );
select_HC573 ( 0 );
P0 = value_SMG;
select_HC573( 7 );
select_HC573 ( 0 );
}
void state_SMG_all ( unsigned char value_SMG_all )
{
select_HC573 ( 0 );
P0 = 0xff;
select_HC573( 6 );
select_HC573 ( 0 );
P0 = value_SMG_all;
select_HC573( 7 );
select_HC573 ( 0 );
}
void state_relay ( unsigned char value_relay )
{
select_HC573 ( 0 );
if ( value_relay == 0 )
{
P0 =0x00;
}
else
{
P0 =0x10;
}
select_HC573 ( 5 );
select_HC573 ( 0 );
}
void state_led ( unsigned char value_led )
{
select_HC573 ( 0 );
P0 = 0xff;
select_HC573 ( 4 );
P0 = value_led;
select_HC573 ( 4 );
select_HC573 ( 0 );
}
void init_sys ()
{
select_HC573 ( 0 );
P0 = 0xff;
select_HC573 ( 4 );
select_HC573 ( 0 );
P0 = 0x00;
select_HC573 ( 5 );
select_HC573 ( 0 );
}
void init_ds1302()
{
unsigned char i;
Write_Ds1302_Byte( 0x8e , 0x00 );
for ( i=0 ; i<8 ; i++ )
{
Write_Ds1302_Byte( write_ds1302_addr[i] , ds1302_time[i] );
}
Write_Ds1302_Byte( 0x8e , 0x80 );
}
bit flash_ds1302 = 0;
void ds1302_flash ()
{
if ( flash_ds1302 == 1 )
{
unsigned char i;
for ( i=0 ; i<8 ; i++ )
{
ds1302_time[i] = Read_Ds1302_Byte ( read_ds1302_addr[i] );
}
flash_ds1302 = 0;
}
}
void Delay700ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 32;//32
j = 236;
k = 16;
do
{
do
{
while (--k);
} while (--j);
keyrunning ();
// relay_ledrunning ();
} while (--i);
}
bit flash_temperature = 0;
unsigned int set_temperature = 23;
unsigned int temperature = 0;
void ds18b20_temperature ()
{
if ( flash_temperature == 1 )
{
unsigned char LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay700ms();
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
temperature = MSB;
temperature = ( temperature << 8 ) | LSB;
temperature = (temperature >> 4)*10 + (LSB & 0x0f)*0.625;
flash_temperature = 0;
}
}
//===================================================================================
void init_timer0 (void) //50微秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x02; //设置定时器模式
TL0 = 0xCE; //设置定时初值
TH0 = 0xCE; //设置定时重载值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1;
ET0 = 1;
}
unsigned char count_50us = 0;
unsigned char flash_count = 0;
void timer0_service () interrupt 1
{
count_50us++;
if ( count_50us % 50 == 0 )
{
if ( SMG_flag == 1 )
{
if ( ++flash_count > 5 )
{
flash_count = 0;
}
}
else if ( SMG_flag == 2 )
{
if ( ++flash_count == 8 )
{
flash_count = 0;
}
}
else if ( SMG_flag == 3 )
{
if ( ++flash_count > 4 )
{
flash_count = 0;
}
}
flash_SMG ();
}
if ( count_50us == 200 )
{
count_50us = 0;
flash_ds1302 = 1;
if ( SMG_flag == 1 )
{
flash_temperature = 1;
}
}
if ( count_50us % 20 == 0 )
{
relay_ledrunning ();
}
}
//=======================================================================
void init_timer1(void) //50毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xB0; //设置定时初值
TH1 = 0x3C; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA = 1;
ET1 = 1;
}
unsigned char count_50ms = 0;
bit count_100ms = 0;
void timer1_service () interrupt 3
{
if ( ++count_50ms % 2 == 0 )
{
count_100ms = ~count_100ms;
}
}
bit flag_5s = 0;
void relay_ledrunning ()
{
if ( ds1302_time[0] >= 0x00 && ds1302_time[0] < 0x06 && ds1302_time[1] == 0x00 )
{
flag_5s = 1;
}
else
{
flag_5s = 0;
}
if ( (key13_state == 0) && (temperature/10 >= set_temperature) )
{
state_relay( 1 );
if ( flag_5s == 0 )
{
if ( count_100ms == 0 )
{
state_led ( led_state[2] );
}
else
{
state_led ( led_state[3] );
}
}
else if ( flag_5s == 1 )
{
if ( count_100ms == 0 )
{
state_led ( led_state[6] );
}
else
{
state_led ( led_state[7] );
}
}
}
else if ( (key13_state == 0) && (temperature/10 < set_temperature) )
{
state_relay( 0 );
if ( flag_5s == 0 )
{
state_led ( led_state[2] );
}
else if ( flag_5s == 1 )
{
state_relay ( 1 );
state_led ( led_state[6] );
}
}
else if ( key13_state == 1 )
{
if ( flag_5s == 0 )
{
state_relay( 0 );
state_led ( led_state[0] );
}
else if ( flag_5s == 1 )
{
state_relay( 1 );
if ( count_100ms == 0 )
{
state_led ( led_state[4] );
}
else
{
state_led ( led_state[5] );
}
}
}
else
{
state_led ( 7 );
state_relay ( 0 );
}
}
void flash_SMG ()
{
state_SMG_all ( 0xff );
if ( SMG_flag == 1 )
{
switch ( flash_count )
{
case 0 :
state_SMG ( 0 , duanma[10] );
break;
case 1 :
state_SMG ( 1 , duanma[SMG_flag] );
break;
case 2 :
state_SMG ( 5 , duanma[temperature/100] );
break;
case 3 :
state_SMG ( 6 , duanma_dot[temperature/10%10] );
break;
case 4 :
state_SMG ( 7 , duanma[temperature%10] );
break;
case 5 :
state_SMG_all ( 0xff );
break;
}
}
else if ( SMG_flag == 2 )
{
switch ( flash_count )
{
case 0 :
state_SMG ( 0 , duanma[10] );
break;
case 1 :
state_SMG ( 1 , duanma[SMG_flag] );
break;
case 2 :
if ( ds1302_mode2 == 1 )
{
state_SMG ( 3 , duanma[ds1302_time[1]/16] );
}
else
{
state_SMG ( 3 , duanma[ds1302_time[2]/16] );
}
break;
case 3 :
if ( ds1302_mode2 == 1 )
{
state_SMG ( 4 , duanma[ds1302_time[1]%16] );
}
else
{
state_SMG ( 4 , duanma[ds1302_time[2]%16] );
}
break;
case 4 :
state_SMG ( 5 , duanma[11] );
break;
case 5 :
if ( ds1302_mode2 == 1 )
{
state_SMG ( 6 , duanma[ds1302_time[0]/16] );
}
else
{
state_SMG ( 6 , duanma[ds1302_time[1]/16] );
}
break;
case 6 :
if ( ds1302_mode2 == 1 )
{
state_SMG ( 7 , duanma[ds1302_time[0]%16] );
}
else
{
state_SMG ( 7 , duanma[ds1302_time[1]%16] );
}
break;
case 7 :
state_SMG_all ( 0xff );
break;
}
}
else if ( SMG_flag == 3 )
{
switch ( flash_count )
{
case 0 :
state_SMG ( 0 , duanma[10] );
break;
case 1 :
state_SMG ( 1 , duanma[SMG_flag] );
break;
case 2 :
state_SMG ( 6 , duanma[set_temperature/10] );
break;
case 3 :
state_SMG ( 7 , duanma[set_temperature%10] );
break;
case 5 :
state_SMG_all ( 0xff );
break;
}
}
}
void Delay2ms() //@12.000MHz
{
unsigned char i, j;
i = 24;
j = 85;
do
{
while (--j);
} while (--i);
}
void keyrunning ()
{
C3 = 0;
C4 = H3 = H4 = 1;
if ( H3 == 0 )
{
Delay2ms();
if ( H3 == 0 )
{
while ( H3 == 0 );//S13
key13_state = ~key13_state;
}
}
else if ( H4 == 0 )
{
Delay2ms();
if ( H4 == 0 )
{
while ( H4 == 0 );//S12
if ( ++SMG_flag == 4 )
{
SMG_flag = 1;
}
}
}
C4 = 0;
C3 = H3 = H4 = 1;
if ( H3 == 0 )
{
Delay2ms();
if ( H3 == 0 )
{
while ( H3 == 0 )//S17
{
if ( SMG_flag == 2 )
{
ds1302_flash();
ds1302_mode2 = 1;
}
}
ds1302_mode2 = 0;
if ( SMG_flag == 3 )
{
if ( --set_temperature == 9 )
{
set_temperature = 10;
}
}
}
}
else if ( H4 == 0 )
{
Delay2ms();
if ( H4 == 0 )
{
while ( H4 == 0 );//S16
if ( SMG_flag == 3 )
{
if ( ++set_temperature == 100 )
{
set_temperature = 99;
}
}
}
}
}
void main ()
{
init_ds1302();
init_timer0();
init_timer1();
init_sys();
while ( 1 )
{
keyrunning ();
ds1302_flash ();
ds18b20_temperature ();
}
}