前后台系统的应用:改版的多功能记录仪


/**
 * 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 (code * pFn)();        //定义函数指针类型,该指针指向code存储区

void sys_init();

void samplingDS1302();
void samplingPCF8591();
void samplingDS18B20();
void writeAndReadEEPROM();

void keyAction(uint8_t keyCode);

//void printTime();
//void printTemAndHum();
//void printResT();

void dispMode0();
void dispMode1();
void dispMode2();
void LED_init();
void LEDchangeMode();
void LED3toggle();

#endif




/**
 * 项目名称:多功能记录仪
 * 功能概述:能测量实时时间、温度、湿度、物品停留时间;
 *           能从EEPROM存/取测量到的数据;
 *             能通过串口和上位机通信。
 * 工作模式0:自动传输模式(上电默认)
 * 工作模式1:自动记录模式
 * 用户操作:
 * (1)按键S5切换工作模式
 * (2)按键S4切换显示模式
 * (3)当记录仪工作在两种模式下时,只有当用户发送字符"AAASSS"给单片机,
 *      单片机才把数据传送给上位机显示。
 * 
 * 文件名:main.c
 */

#include <stc15f2k60s2.h>
#include <string.h>
#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表示自动记录模式
bit isShading = 0;        //是否被遮光的标志

msg_t message;

uint8_t SerialBuf[7], SerialBufIndex = 0;    //串口数据缓存

uint8_t leds_state = ~0x01;    //上电默认为模式1

void main() {
    sys_init();
    
    while (1) {
        keyDriver();
        
        if (flag200ms) {    //200ms采集一次实时时间
            flag200ms = 0;
            
            samplingDS1302();
        }

        if (flag300ms) {    //300ms采集一次模拟量
            flag300ms = 0;
            
            samplingPCF8591();
        }

        if (flag1s) {    //1s采集一次温度
            flag1s = 0;
            
            samplingDS18B20();
            if (workingMode) {    //如果工作于自动记录模式
                writeAndReadEEPROM();
            }
        }
    }
}

void sys_init() {
    tmr0_init(2);
    DS18B20_start();
    DS1302init();
    Serial_init(1200);    //baudrate=1200
    LED_init();
}

void samplingDS1302() {        //200ms
    sTime_t time;
    static uint8_t preSec;
    
    DS1302_getRealTime(&time);
    if (time.sec != preSec) {    //秒有变化
        message.hour = (time.hour >> 4) * 10 + (time.hour & 0x0F);    //将BCD码解码
        message.minute = (time.minute >> 4) * 10 + (time.minute & 0x0F);
        message.second = (time.sec >> 4) * 10 + (time.sec & 0x0F);
        if (disptrIndex == 0) {
            dispMode0();
        }
        preSec = time.sec;
    }
}

void samplingPCF8591() {    //300ms
    uint8_t chn1Sample, chn3Sample;
    static uint8_t cnt300ms = 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;
        if ((cnt300ms * 3 / 10) != ((cnt300ms - 1) * 3 / 10)) {    //如果秒数有变化则闪烁
            LED3toggle();    //在这里闪烁更及时一些
        }
    } 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;
    }
}

void samplingDS18B20() {    //1s
    int16_t temperature;
    uint8_t tempIntPart, tempDecPart;
    
    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();
    }
    */
}

void writeAndReadEEPROM() {
    static uint8_t EEPROMwritingIndex = 0, EEPROMreadingIndex = 0;
    
    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;
        LEDchangeMode();
        break;
    }
}

void Serial_receive() {
    SerialBuf[SerialBufIndex] = SBUF;
    if (SerialBufIndex == 5) {
        if (strncmp(SerialBuf, "AAASSS", 6) == 0) {
            //%bu用于输出uint8_t(byte unsigned)
            myprintf("{%bu-%bu-%bu}", 
                message.hour, message.minute, message.second);
            myprintf("{%buC--%buH}", 
                message.tempIntPart, message.humidity);
            if (workingMode == 0) {        //如果工作于模式0
                if (isShading)            //如果现在被遮光了
                    myprintf("{--1--}\n");
                else
                    myprintf("{--0--}\n");
            } else {    //否则打印前一次的停留时间
                myprintf("{--%bus}\n", message.resTime);
            }
        }
        SerialBufIndex = 0;
    } else {
        SerialBufIndex++;
    }
}

void Serial_transmit() { }

void dispMode0() {
    static bit flag = 0;

    dspBuf[0] = message.hour / 10;    //已经解码了
    dspBuf[1] = message.hour % 10;
    dspBuf[2] = (flag ? 11 : 10);
    dspBuf[3] = message.minute / 10;
    dspBuf[4] = message.minute % 10;
    dspBuf[5] = (flag ? 11 : 10);
    dspBuf[6] = message.second / 10;
    dspBuf[7] = message.second % 10;

    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 LED_init() {
    P2 = (P2 & 0x1F) | 0x80;
    P0 = leds_state;
    P2 &= 0x1F;
}

void LEDchangeMode() {
    leds_state ^= 0x03;        //将最低两位反转
    
    P2 = (P2 & 0x1F) | 0x80;
    P0 = leds_state;
    P2 &= 0x1F;
}

void LED3toggle() {
    leds_state ^= 0x04;        //将倒数第三位反转
    
    P2 = (P2 & 0x1F) | 0x80;
    P0 = leds_state;
    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;
    }
}

你可能感兴趣的:(前后台系统的应用:改版的多功能记录仪)