×
单片机 > 单片机程序设计 > 详情

51单片机项目:多功能记录仪

发布时间:2020-06-08 发布时间:
|

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;

}




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机CO2检测显示程序解析