蓝桥杯大赛用单片机C51实现本程序1.设定按健S7为出水控制按键,当S7按下后,售水机持绩出水(继电要接通,指示灯L10点亮)。设定按键S6为停水控制按键,当 S6按下后,停止出水(继电器断开,指示灯L10您灭) 2.数码管显单元 通过4位数码管DS1示费率,单为元/升,保2位有效数字, 通过4位数码管DS2显示当前出水总量(出水时,单位为升)和总价(停止时,单 位为元):按下出水按键S7后,清除数码管DS2显示数据,数码管DS2实时显示出水量(保留两位有效数字),在出水状态下,再次按下S7,不会影响出水状态,直到按下停止按键S6 为止:按下停止出水按键 S6 后,数码管DS2 显示总价(保留两位有效数字) 通过 DS18B20 检测环境温度,当温度超过 27C时,Led2 以 0.1S 为间隔闪烁,否则关闭 系统说明 假定水价为 0.5 元/升,出水速度为 100 毫升/秒 一次出水总量达到 99.99L时,继电器自动断开,数码管显示 DS2显示价格
时间: 2024-03-20 16:39:41 浏览: 90
蓝桥杯单片机开发板实现定时器中断进而控制数码管的动态显示
5星 · 资源好评率100%
以下是使用C51单片机实现的自动售水机程序,包括出水和停水控制、数码管显示、温度检测等功能:
```c
#include <reg51.h>
#include <intrins.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
sbit S7 = P1^0; // 出水控制按键
sbit S6 = P1^1; // 停水控制按键
sbit L10 = P1^2; // 指示灯
sbit DQ = P3^7; // DS18B20数据线
uchar code DispTab[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; // 数码管显示表
uchar DispBuf[8]; // 数码管显示缓存
uchar DispIndex = 0; // 数码管显示位置
uchar DispCount = 0; // 数码管显示计数
uint WaterCount = 0; // 出水总量,单位:毫升
uint TotalPrice = 0; // 总价,单位:分
uint WaterRate = 50; // 费率,单位:分/升
uint WaterPrice = 0; // 水的价格,单位:分
uchar Temperature = 0; // 温度,单位:摄氏度
bit WaterFlag = 0; // 出水标志
bit StopFlag = 0; // 停水标志
bit BlinkFlag = 0; // 闪烁标志
void Delay(uint t) // 延时函数
{
uint i, j;
for (i = 0; i < t; i++)
{
for (j = 0; j < 125; j++);
}
}
void InitDS18B20() // 初始化DS18B20
{
uchar i;
DQ = 1;
Delay(1);
DQ = 0;
Delay(500);
DQ = 1;
Delay(60);
i = DQ;
Delay(400);
}
uchar ReadDS18B20() // 读取DS18B20温度
{
uchar i, j;
uchar dat = 0;
for (i = 0; i < 8; i++)
{
DQ = 0;
_nop_();
_nop_();
DQ = 1;
_nop_();
_nop_();
j = DQ;
Delay(5);
dat >>= 1;
if (j) dat |= 0x80;
Delay(50);
}
return dat;
}
void WriteDS18B20(uchar dat) // 写入DS18B20温度
{
uchar i;
for (i = 0; i < 8; i++)
{
DQ = 0;
_nop_();
_nop_();
DQ = dat & 0x01;
Delay(5);
DQ = 1;
_nop_();
_nop_();
dat >>= 1;
}
Delay(50);
}
void DispValue(uint value, uchar dot) // 显示数值
{
uchar i;
for (i = 0; i < 4; i++)
{
DispBuf[DispIndex + i] = DispTab[value % 10];
if (i == dot) DispBuf[DispIndex + i] |= 0x80;
value /= 10;
}
DispIndex += 4;
}
void DispWaterCount() // 显示出水总量
{
DispIndex = 0;
DispValue(WaterCount / 1000, 2);
DispValue(WaterCount % 1000 / 10, 1);
DispBuf[DispIndex] = DispTab[DispBuf[DispIndex] & 0x7f]; // 去掉小数点
}
void DispTotalPrice() // 显示总价
{
DispIndex = 4;
DispValue(TotalPrice / 100, 1);
DispValue(TotalPrice % 100, 2);
}
void DispWaterPrice() // 显示水的价格
{
DispIndex = 4;
DispValue(WaterPrice / 10, 1);
DispValue(WaterPrice % 10, 2);
}
void Display() // 数码管显示
{
if (DispCount == 0)
{
P2 = 0xff;
P0 = DispBuf[DispIndex];
P2 = 0xfe >> DispIndex;
DispIndex++;
if (DispIndex >= 8) DispIndex = 0;
}
DispCount++;
if (DispCount >= 50) DispCount = 0;
}
void WaterControl() interrupt 0 // 出水控制
{
if (!WaterFlag && !StopFlag)
{
L10 = 1;
WaterFlag = 1;
WaterCount = 0;
DispIndex = 4;
DispValue(0, 2);
}
else if (WaterFlag && !StopFlag)
{
WaterCount += 100;
TotalPrice = WaterCount * WaterRate / 100;
if (WaterCount >= 99990) // 出水总量达到99.99L时停水
{
StopFlag = 1;
WaterFlag = 0;
L10 = 0;
DispTotalPrice();
}
else
{
DispWaterCount();
}
}
}
void StopControl() interrupt 1 // 停水控制
{
if (WaterFlag && !StopFlag)
{
StopFlag = 1;
WaterFlag = 0;
L10 = 0;
DispTotalPrice();
}
}
void Timer0() interrupt 1 using 1 // 定时器0中断
{
static uchar count = 0;
TH0 = 0xff;
TL0 = 0x9c;
count++;
if (count >= 20) // 每1秒检测一次温度
{
count = 0;
InitDS18B20();
WriteDS18B20(0xcc);
WriteDS18B20(0x44);
Delay(100);
InitDS18B20();
WriteDS18B20(0xcc);
WriteDS18B20(0xbe);
Temperature = ReadDS18B20();
if (Temperature > 27)
{
BlinkFlag = !BlinkFlag;
if (BlinkFlag)
{
P2 = 0xff;
P0 = 0x00;
}
else
{
P2 = 0xff;
P0 = 0x80;
}
}
else
{
BlinkFlag = 0;
P2 = 0xff;
P0 = 0x00;
}
}
}
void main()
{
TMOD = 0x11; // 定时器0工作在模式1(16位自动重载)下,定时器1工作在模式0(13位定时器)下
TH0 = 0xff;
TL0 = 0x9c;
TH1 = 0x3d;
TL1 = 0x09;
ET0 = 1; // 允许定时器0中断
ET1 = 0; // 禁止定时器1中断
EA = 1; // 允许总中断
TR0 = 1;
TR1 = 1;
DispWaterPrice(); // 显示水的价格
while (1)
{
if (S7 == 0)
{
while (S7 == 0); // 等待按键释放
if (!WaterFlag && !StopFlag)
{
WaterPrice = WaterRate * 100 / 2; // 计算水的价格
DispWaterPrice();
}
WaterFlag = 1;
StopFlag = 0;
L10 = 1;
}
if (S6 == 0)
{
while (S6 == 0); // 等待按键释放
if (WaterFlag && !StopFlag)
{
StopFlag = 1;
WaterFlag = 0;
L10 = 0;
DispTotalPrice();
}
}
Display();
}
}
```
注意:本程序仅供参考,实际实现可能需要根据具体硬件平台和需求进行修改。
阅读全文