main.h
/**
* 51单片机项目:多功能记录仪
* 文件名:main.h
*/
#ifndef _MAIN_H
#define _MAIN_H
typedef struct msg {
uint8_t hour; //时
uint8_t minute; //分
uint8_t second; //秒
uint8_t tempIntPart; //温度
uint8_t humidity; //湿度
uint8_t resTime; //物品停留时间
} msg_t;
typedef void (* pFn)(); //定义函数指针类型
void keyAction(uint8_t keyCode);
void Serial_receive();
void dispMode0();
void dispMode1();
void dispMode2();
void LEDupdate();
void LED3toggle();
#endif
main.c
/**
* 51单片机项目:多功能记录仪
* 工作模式0:自动传输模式(上电默认)
* 工作模式1:自动记录模式
* 用户操作:
* (1)按键S5切换工作模式
* (2)按键S4切换显示模式
* (3)当记录仪工作在两种模式下时,只有当用户发送字符"AAASSS"给单片机,
* 单片机才把数据传送给上位机显示。
*
* 文件名:main.c
*/
#include
#include
#include "stdint.h"
#include "timer.h"
#include "digitalTube.h"
#include "independentKey.h"
#include "Serial.h"
#include "I2C.h"
#include "EEPROM.h"
#include "PCF8591.h"
#include "OneWire.h"
#include "DS18B20.h"
#include "DS1302.h"
#include "main.h"
sbit LED_1 = P0^0;
sbit LED_2 = P0^1;
sbit LED_3 = P0^2;
volatile bit flag200ms = 0, flag300ms = 0, flag1s = 0;
pFn code disptr[3] = { dispMode0, dispMode1, dispMode2 };
uint8_t disptrIndex = 0;
bit workingMode = 0; //为0表示自动传输模式;为1表示自动记录模式
msg_t message;
uint8_t SerialBuf[7], SerialBufIndex = 0;
void main() {
sTime_t time;
uint8_t preSec;
int16_t temperature;
uint8_t tempIntPart, tempDecPart;
uint8_t chn1Sample, chn3Sample, cnt300ms = 0;
uint8_t EEPROMwritingIndex = 0, EEPROMreadingIndex = 0;
bit isShading = 0;
tmr0_init(2);
DS18B20_start();
DS1302init();
Serial_init(1200); //baudrate=1200
LEDupdate();
while (1) {
keyDriver();
if (flag200ms) { //200ms采集一次实时时间
flag200ms = 0;
DS1302_getRealTime(&time);
if (time.sec != preSec) { //秒有变化
message.hour = time.hour;
message.minute = time.minute;
message.second = time.sec;
if (disptrIndex == 0) {
dispMode0();
}
preSec = time.sec;
}
}
if (flag300ms) { //300ms采集一次模拟量
flag300ms = 0;
chn1Sample = PCF8591_getADCvalue(1); //通道1的采样值
chn3Sample = PCF8591_getADCvalue(3); //通道3的采样值
message.humidity = (uint8_t)((uint16_t)chn3Sample * 99 / 255);
if (chn1Sample < 128) { //如果遮光
cnt300ms++;
isShading = 1;
} else { //没有遮光
if (isShading) { //如果之前遮光(上升沿)
message.resTime = cnt300ms * 3 / 10;
cnt300ms = 0; //本次遮挡完毕,重置计时次数
}
isShading = 0;
}
if (disptrIndex == 1) { //如果显示模式是1,则更新湿度显示
dspBuf[5] = message.humidity / 10;
dspBuf[6] = message.humidity % 10;
} else if (disptrIndex == 2) { //如果显示模式是2,则更新物品停留时间显示
dspBuf[6] = message.resTime / 10;
dspBuf[7] = message.resTime % 10;
}
}
if (flag1s) { //1s采集一次温度
flag1s = 0;
DS18B20_getTemperature(&temperature);
DS18B20_start(); //!!!重新启动
tempIntPart = getIntPart(temperature);
tempDecPart = getDecPart(temperature);
if (tempDecPart >= 5) //四舍五入
tempIntPart++;
message.tempIntPart = tempIntPart;
if (disptrIndex == 1) { //如果是显示模式1,则更新温度显示
dspBuf[0] = message.tempIntPart / 10;
dspBuf[1] = message.tempIntPart % 10;
}
if (isShading) { //如果被遮光,则LED3一秒钟闪烁一次
LED3toggle();
}
if (workingMode) { //如果工作于自动记录模式
EEPROMwrite((uint8_t *)&message, EEPROMwritingIndex, sizeof (msg_t));
EEPROMwritingIndex += sizeof (msg_t); //这个EEPROM一共是256字节的存储空间
EEPROMread((uint8_t *)&message, EEPROMreadingIndex, sizeof (msg_t)); //写入后再读出
EEPROMreadingIndex += sizeof (msg_t);
}
}
}
}
void keyAction(uint8_t keyCode) {
switch (keyCode) {
case 4:
if (disptrIndex == 2) {
disptrIndex = 0;
} else {
disptrIndex++;
}
disptr[disptrIndex]();
break;
case 5:
workingMode = ~workingMode;
LEDupdate();
break;
}
}
void Serial_receive() {
//uint8_t hour, minute, second;
uint8_t hshi, hge, mshi, mge, sshi, sge;
uint8_t temshi, temge, humshi, humge;
uint8_t restshi, restge;
SerialBuf[SerialBufIndex] = SBUF;
if (SerialBufIndex == 5) {
if (strncmp(SerialBuf, "AAASSS", 6) == 0) {
//hour = (message.hour >> 4) * 10 + (message.hour & 0x0F); // 将BCD码解码
//minute = (message.minute >> 4) * 10 + (message.minute & 0x0F);
//second = (message.second >> 4) * 10 + (message.second & 0x0F);
//myprintf("{%hhu-%hhu-%hhu}", hour, minute, second);
hshi = message.hour >> 4;
hge = message.hour & 0x0F;
mshi = message.minute >> 4;
mge = message.minute & 0x0F;
sshi = message.second >> 4;
sge = message.second & 0x0F;
temshi = message.tempIntPart / 10;
temge = message.tempIntPart % 10;
humshi = message.humidity / 10;
humge = message.humidity % 10;
restshi = message.resTime / 10;
restge = message.resTime % 10;
myprintf("{%c%c-%c%c-%c%c}",
hshi+'0', hge+'0', mshi+'0', mge+'0', sshi+'0', sge+'0');
//myprintf("{%hhuC--%hhuH}", message.tempIntPart, message.humidity);
myprintf("{%c%cC--%c%cH}",
temshi+'0', temge+'0', humshi+'0', humge+'0');
if (workingMode == 0) {
if (message.resTime)
myprintf("{--1--}n");
else
myprintf("{--0--}n");
} else {
//myprintf("{--%hhus}n", message.resTime);
myprintf("{--%c%cs}n", restshi+'0', restge+'0'); //注意要加'0'
}
}
SerialBufIndex = 0;
} else {
SerialBufIndex++;
}
}
void Serial_transmit() { }
void dispMode0() {
static bit flag = 0;
dspBuf[0] = message.hour >> 4;
dspBuf[1] = message.hour & 0x0F;
dspBuf[2] = (flag ? 11 : 10);
dspBuf[3] = message.minute >> 4;
dspBuf[4] = message.minute & 0x0F;
dspBuf[5] = (flag ? 11 : 10);
dspBuf[6] = message.second >> 4;
dspBuf[7] = message.second & 0x0F;
flag = ~flag;
}
void dispMode1() {
dspBuf[0] = message.tempIntPart / 10;
dspBuf[1] = message.tempIntPart % 10;
dspBuf[2] = 12; //C
dspBuf[3] = 11; //-
dspBuf[4] = 11; //-
dspBuf[5] = message.humidity / 10;
dspBuf[6] = message.humidity % 10;
dspBuf[7] = 13; //H
}
void dispMode2() {
dspBuf[0] = 11;
dspBuf[1] = 10;
dspBuf[2] = 10;
dspBuf[3] = 0;
dspBuf[4] = 0;
dspBuf[5] = 0;
dspBuf[6] = message.resTime / 10;
dspBuf[7] = message.resTime % 10;
}
void LEDupdate() {
uint8_t tmp = 0xFF; //初始化为都不显示
P2 = (P2 & 0x1F) | 0x80;
tmp = P0; //获取对应于LED组件时P0的状态
P2 &= 0x1F;
tmp |= 0xF8; //高5位都不显示,置1(0有效)
tmp &= 0xFC; //最低2位清0
if (workingMode == 0) {
tmp |= 0x02; //最低2位写10
} else {
tmp |= 0x01; //最低2位写01
}
P2 = (P2 & 0x1F) | 0x80;
P0 = tmp;
P2 &= 0x1F;
}
/*
void LEDupdate() {
P2 = (P2 & 0x1F) | 0x80;
P0 |= 0xFC; //高位置1,使其无效
P2 &= 0x1F;
P2 = (P2 & 0x1F) | 0x80;
P0 ^= 0x03;
P2 &= 0x1F;
}
*/
void LED3toggle() {
P2 = (P2 & 0x1F) | 0x80;
P0 ^= 0x04; //这里运行的现象有问题,不知道是什么原因
//P0 ^= 0xFB;
//LED_3 = ~LED_3;
P2 &= 0x1F;
}
void tmr0ISR() interrupt 1 {
static uint16_t cnt = 0;
TL0 = tmr0LowByte;
TH0 = tmr0HighByte;
cnt++;
digitalTubeScan();
if (cnt & 0x01)
keyScan();
if (cnt % 100 == 0) {
flag200ms = 1;
}
if (cnt % 150 == 0) {
flag300ms = 1;
}
if (cnt == 500) {
cnt = 0;
flag1s = 1;
}
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』