请用STC15系列单片机,设计温度采集系统。要求BS18B20温度传感器,键盘设置当前的日期时间,显示器用LED显示,显示当前采集的温度,保存10个温度点,可用键盘回调查询。代码
时间: 2024-03-26 15:34:05 浏览: 88
好的,我会尽力回答你的问题。首先,我们来了解一下STC15系列单片机和BS18B20温度传感器。
STC15系列单片机是一种常见的8位单片机,它具有高效、低功耗的特点。BS18B20温度传感器是一种数字温度传感器,具有精度高、可靠性好、抗干扰能力强等特点。
下面是我的代码实现:
```c
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DS18B20_DQ P2_7
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
sbit LED = P1 ^ 0;
sbit KEY1 = P3 ^ 1;
sbit KEY2 = P3 ^ 2;
sbit KEY3 = P3 ^ 3;
sbit KEY4 = P3 ^ 4;
char *weekday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
uint16_t ADC_value;
uint8_t flag, save_count, read_count;
uint8_t temperature[10];
uint8_t year, month, day, hour, minute, second, week;
void delay(uint16_t ms)
{
uint16_t i, j;
for (i = ms; i > 0; i--)
for (j = 110; j > 0; j--);
}
void init()
{
TMOD = 0x01; //定时器0模式1
TH0 = 0x3C; //装载初值,定时1ms
TL0 = 0xAF;
EA = 1; //总中断允许
ET0 = 1; //定时器0中断允许
TR0 = 1; //启动定时器0
}
void send_byte(uint8_t dat)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
DS18B20_DQ = 0;
DS18B20_DQ = dat & 0x01;
delay(2);
DS18B20_DQ = 1;
dat >>= 1;
}
}
uint8_t read_byte()
{
uint8_t dat = 0, i;
for (i = 0; i < 8; i++)
{
dat >>= 1;
DS18B20_DQ = 0;
DS18B20_DQ = 1;
if (DS18B20_DQ)
dat |= 0x80;
delay(2);
}
return dat;
}
void start_convert()
{
send_byte(0xCC);
send_byte(0x44);
}
void read_temperature()
{
uint8_t TL, TH;
send_byte(0xCC);
send_byte(0xBE);
TL = read_byte();
TH = read_byte();
if (TH & 0x80) //负温度
{
ADC_value = ((~(TH << 8 | TL)) + 1) * 625 / 100;
}
else //正温度
{
ADC_value = (TH << 8 | TL) * 625 / 100;
}
}
void display_temperature()
{
uint8_t i;
printf("Temperature: %d.%d℃\n", ADC_value / 100, ADC_value % 100);
if (flag == 0)
{
LED = 1;
printf("Saving...\n");
temperature[save_count] = ADC_value / 100;
save_count++;
if (save_count >= 10)
{
flag = 1;
save_count = 0;
}
}
else
{
printf("Reading...\n");
printf("Saved Temperature:\n");
for (i = 0; i < 10; i++)
{
printf("%d.%d℃\n", temperature[i], ADC_value % 100);
}
printf("Press KEY1 to continue...\n");
}
}
void display_time()
{
printf("%04d-%02d-%02d %s %02d:%02d:%02d\n", 2000 + year, month, day, weekday[week], hour, minute, second);
}
void set_time()
{
printf("Setting Time...\n");
printf("Enter Year(00-99):");
scanf("%d", &year);
printf("Enter Month(01-12):");
scanf("%d", &month);
printf("Enter Day(01-31):");
scanf("%d", &day);
printf("Enter Hour(00-23):");
scanf("%d", &hour);
printf("Enter Minute(00-59):");
scanf("%d", &minute);
printf("Enter Second(00-59):");
scanf("%d", &second);
week = ((day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400) % 7);
printf("Time Set Successfully!\n");
}
void main()
{
init();
while (1)
{
start_convert();
read_temperature();
display_temperature();
if (KEY1 == 0)
{
while (!KEY1);
set_time();
display_time();
}
if (KEY2 == 0)
{
while (!KEY2);
flag = 0;
printf("Saving Temperature...\n");
}
if (KEY3 == 0)
{
while (!KEY3);
flag = 1;
printf("Reading Temperature...\n");
}
if (KEY4 == 0)
{
while (!KEY4);
display_time();
}
}
}
void timer0_isr() interrupt 1
{
static uint16_t ms_count = 0;
TH0 = 0x3C;
TL0 = 0xAF;
ms_count++;
if (ms_count >= 1000)
{
ms_count = 0;
second++;
if (second >= 60)
{
second = 0;
minute++;
if (minute >= 60)
{
minute = 0;
hour++;
if (hour >= 24)
{
hour = 0;
day++;
week = ((day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400) % 7);
}
}
}
}
}
```
代码中使用了定时器0来实现1ms的计时,主函数循环不断地采集温度,并通过键盘输入来设置时间、保存温度点、读取温度点和查询当前时间。在采集温度时,先发送启动转换指令,然后读取温度值,最后将温度值保存在数组中。在显示温度时,根据标志位的不同,可以选择保存温度点或读取温度点。在设置时间时,通过键盘输入来设置年、月、日、时、分、秒,并计算出当前星期几。在定时器中断中,每1s更新一次时间。
注意:由于我没有实际硬件进行测试,代码可能存在一些问题,需要根据具体情况进行修改。
阅读全文