仿真图:
芯片/模块的特点:
ADC0832特点:
8位分辨率:ADC0832可以将模拟输入信号转换为8位数字输出。这意味着它可以将模拟信号划分为256个不同的离散电平,提供相对较低的分辨率。
双通道输入:ADC0832具有两个模拟输入通道,使其能够同时转换两个模拟信号。这对于需要同时测量多个信号的应用非常有用。
内部参考电压源:ADC0832提供了一个内部的参考电压源,它可以用作模拟输入信号的参考电压。这样可以简化外部电路设计,并提供更稳定和准确的参考电压。
串行输出:ADC0832通过串行接口(SPI或I2C)输出转换结果。这种串行输出形式使其与微控制器或其他数字设备的通信变得更加简单和方便。
低功耗:ADC0832具有较低的功耗特性,适合在低功耗应用中使用。
可编程时钟频率:ADC0832的转换速度可以通过控制输入时钟频率进行编程。这使得可以根据应用的需求调整转换速度,并平衡转换精度和速度。
内部自校准:ADC0832具有内部自校准电路,可以降低转换误差,并提供更准确的转换结果。
DS1302特点:
高精度时间计数:DS1302能够提供高精度的实时时钟计数,可以记录年、月、日、星期、小时、分钟和秒等时间信息。它内部集成了晶体振荡器,提供稳定的时钟信号。
低功耗设计:DS1302采用低功耗设计,可以在低功耗模式下运行,有效延长电池寿命。即使在停电情况下,它也能保持时间数据,并通过外部连接电池继续提供计时功能。
串行接口:DS1302通过串行实时时钟接口(SPI)进行通信和控制。使用少数几个引脚,可以与主控器件进行数据交换和时钟同步。
容易集成:DS1302集成了时钟计数和RAM存储器功能,并具有简单的接口和命令,容易与各种微控制器和单片机集成。它不需要复杂的控制信号,可以通过简单的读写命令进行操作。
可编程控制功能:DS1302具有可编程的控制功能,可以设置闹钟、写保护等特殊功能。它还支持多种时间格式的选择,例如24小时制或12小时制。
温度补偿:DS1302内置温度补偿功能,可以校正温度对时钟频率的影响,提高时钟计数的准确性。
高稳定性和抗震动能力:DS1302具有高稳定性和抗震动能力,适用于各种工业和消费类应用场景。
主程序:
#define _MAIN_C
#include <reg52.h>
#include <stdio.h>
#include "main.h"
#include "delay.h"
#include "eeprom52.h"
#include "tlc0832.h"
#include "ds1302.h"
#include "lcd1602.h"
#include "date.h"
// 管脚声明
sbit IR_SCAN = P1^6;
sbit KEY_SUB = P3^6;
sbit KEY_ADD = P3^4;
sbit KEY_MODE = P3^5;
sbit KEY_SET = P3^3;
sbit LED_PWM = P2^1;
sbit BUZZER = P2^0;
extern unsigned char timeBufBcd[8];
extern unsigned char timeBufDec[8];
unsigned char dispRow0[] = " / / ";
unsigned char dispRow1[] = " : : ";
unsigned char g_setLocation = 0;
unsigned long highT0RH;
unsigned long highT0RL;
unsigned long lowT0RH;
unsigned long lowT0RL;
unsigned char g_PWMdutyCycle = 50;
unsigned char isNew;
unsigned long minuteBuf;
bit g_setTimeFlag = 0;
bit g_OffFlag = 0;
bit g_dispOn = 0;
bit g_getADData = 0;
void DispTime(); //显示时间
void Init_Timer0(); //定时器0初始化
void Init_Timer1(); //定时器1初始化
void KeyPress(); //按键处理
void SetTime(); //设定时间
void SetPWM(unsigned int freq, unsigned char dutyCycle); //PWM设定
void DispLED(); //显示模式和光照等级
CreatByte mode;
// 主函数
main()
{
unsigned long PWMfreq = 100;
unsigned long adData = 0;
unsigned long adDataBuf = 0;
static unsigned char getADDataCnt = 0;
// 初始化
//Init_EEPROM();
DS1302_Init();
// if (!isNew)
// {
// DS1302_ReadTime();
// }
// else
// {
// DS1302_WriteTime();
// }
LCD_Init();
LCD_CLear();
SetPWM(PWMfreq, g_PWMdutyCycle);
Init_Timer0();
Init_Timer1();
DispTime();
DispLED();
while (1)
{
SetPWM(PWMfreq, g_PWMdutyCycle); //设置PWM频率和占空比
if (g_dispOn)
{
DispTime(); //显示时间
DispLED(); //显示模式和灯光等级
g_dispOn = 0;
}
if (g_setTimeFlag)
{
SetTime(); //设置时间
}
else
{
DS1302_ReadTime(); //读取时间
}
if (g_isAutoOff) //自动开关模式
{
if (g_OffFlag == 1)
{
LED_PWM = 1;
TR0 = 0; //关闭定时器0计数
}
else
{
TR0 = 1; //开启定时器0计数
}
if (IR_SCAN == 0) //有人时一直给最新的秒时间
{
minuteBuf = timeBufDec[6];
}
else //没人时,1分钟后关闭台灯
{
if (minuteBuf == 0)
{
if (timeBufDec[6] == 59)
{
g_OffFlag = 1;
}
}
else
{
if (minuteBuf == timeBufDec[6] + 1)
{
g_OffFlag = 1;
}
}
}
}
if (g_isAutoAjust == 1 && g_getADData == 1) //自动调整灯光亮度模式
{
adData = ReadADC(AIN0_GND);
adData = 100 * adData / 255; //读取灯光亮度
if (getADDataCnt < 5) //累加5次
{
adDataBuf = adDataBuf + adData;
getADDataCnt++;
}
else //求平均
{
adDataBuf = adDataBuf / getADDataCnt;
if (adDataBuf >= 95)
{
adDataBuf = 95;
}
else if (adDataBuf <= 5)
{
adDataBuf = 5;
}
g_PWMdutyCycle = adDataBuf;
adDataBuf = 0;
getADDataCnt = 0;
}
g_getADData = 0;
}
KeyPress(); //按键处理
}
}
void DispTime()
{
dispRow0[0] = timeBufDec[1] / 10 +'0'; //年
dispRow0[1] = timeBufDec[1] % 10 +'0';
dispRow0[3] = timeBufDec[2] / 10 +'0'; //月
dispRow0[4] = timeBufDec[2] % 10 +'0';
dispRow0[6] = timeBufDec[3] / 10 +'0'; //日
dispRow0[7] = timeBufDec[3] % 10 +'0';
dispRow1[0] = timeBufDec[4] / 10 +'0'; //时
dispRow1[1] = timeBufDec[4] % 10 +'0';
dispRow1[3] = timeBufDec[5] / 10 +'0'; //分
dispRow1[4] = timeBufDec[5] % 10 +'0';
dispRow1[6] = timeBufDec[6] / 10 +'0'; //秒
dispRow1[7] = timeBufDec[6] % 10 +'0';
LCD_WriteStr(0, 0, dispRow0); //显示日期
LCD_WriteStr(0, 1, dispRow1); //显示时间
switch (timeBufDec[7]) //显示星期
{
case 1: LCD_WriteStr(10, 0, " Sun."); break;
case 2: LCD_WriteStr(10, 0, " Mon."); break;
case 3: LCD_WriteStr(10, 0, " Tue."); break;
case 4: LCD_WriteStr(10, 0, " Wed."); break;
case 5: LCD_WriteStr(10, 0, "Thur."); break;
case 6: LCD_WriteStr(10, 0, " Fri."); break;
case 7: LCD_WriteStr(10, 0, " Sat."); break;
default: LCD_WriteStr(10, 0, " Sun."); break;
}
}
void SetTime()
{
TR1 = 0;
LCD_WriteCommand(0x0F, 0);
// LCD_WriteCommand(0x0C, 0);
switch (g_setLocation)
{
case 1: LCD_WriteCommand(0x80 + 1, 0); break;
case 2: LCD_WriteCommand(0x80 + 4, 0); break;
case 3: LCD_WriteCommand(0x80 + 7, 0); break;
case 4: LCD_WriteCommand(0x80 + 0x40 + 1, 0); break;
case 5: LCD_WriteCommand(0x80 + 0x40 + 4, 0); break;
case 6: LCD_WriteCommand(0x80 + 0x40 + 7, 0); break;
case 7: LCD_WriteCommand(0x80 + 14, 0); break;
case 8:
{
LCD_WriteCommand(0x0C, 0);
DS1302_WriteTime();
g_setLocation = 0;
g_setTimeFlag = 0;
break;
}
default: ;
}
TR1 = 1;
}
void DispLED()
{
if (g_isAutoOff)
{
LCD_WriteChar(10, 1, 'A'); //自动开关模式
}
else
{
LCD_WriteChar(10, 1, 'M'); //手动开关模式
}
if (g_isAutoAjust)
{
LCD_WriteChar(12, 1, 'A'); //自动调节亮度模式
}
else
{
LCD_WriteChar(12, 1, 'M'); //手动调节亮度模式
}
LCD_WriteChar(14, 1, g_PWMdutyCycle / 5 / 10 + '0');
LCD_WriteChar(15, 1, g_PWMdutyCycle / 5 % 10 + '0');
}
void SetPWM(unsigned int freq, unsigned char dutyCycle)
{
unsigned long totalCnt;
unsigned long highCnt;
unsigned long lowCnt;
totalCnt = 11059200 / freq / 12; // (1/freq) / (12/11059200);
highCnt = totalCnt * dutyCycle / 100;
lowCnt = totalCnt - highCnt;
highCnt = 65536 - highCnt;
lowCnt = 65536 - lowCnt;
highT0RH = highCnt / 256;
highT0RL = highCnt % 256;
lowT0RH = lowCnt / 256;
lowT0RL = lowCnt % 256;
}
void KeyPress()
{
static unsigned int keyCnt;
if (!KEY_SET) //设置键按下
{
DelayMs(10);
if (!KEY_SET)
{
if (!g_setTimeFlag)
{
g_setTimeFlag = 1;
}
g_setLocation++;
BUZZER = 0;
DelayMs(10);
BUZZER = 1;
}
while (!KEY_SET);
}
if (!KEY_ADD) //加键按下
{
DelayMs(180);
if (!KEY_ADD)
{
if (!g_setTimeFlag)
{
if (g_isAutoAjust == 1)
{
g_isAutoAjust = 0;
}
g_PWMdutyCycle = g_PWMdutyCycle + 5;
if (g_PWMdutyCycle >= 95)
{
g_PWMdutyCycle = 95;
}
//Write_EEPROM();
}
else
{
switch (g_setLocation)
{
case 1:
{
timeBufDec[1]++;
if (timeBufDec[1] >= 100)
{
timeBufDec[1] = 0;
}
break;
}
case 2:
{
timeBufDec[2]++;
if (timeBufDec[2] >= 13)
{
timeBufDec[2] = 1;
}
break;
}
case 3:
{
timeBufDec[3]++;
if (timeBufDec[3] >= YDay(timeBufDec[1], timeBufDec[2]) + 1)
{
timeBufDec[3] = 1;
}
break;
}
case 4:
{
timeBufDec[4]++;
if (timeBufDec[4] >= 24)
{
timeBufDec[4] = 0;
}
break;
}
case 5:
{
timeBufDec[5]++;
if (timeBufDec[5] >= 60)
{
timeBufDec[5] = 0;
}
break;
}
case 6:
{
timeBufDec[6]++;
if (timeBufDec[6] >= 60)
{
timeBufDec[6] = 0;
}
break;
}
case 7:
{
timeBufDec[7]++;
if (timeBufDec[7] > 7)
{
timeBufDec[7] = 1;
}
break;
}
default:;
}
}
BUZZER = 0;
DelayMs(10);
BUZZER = 1;
}
//while (!KEY_ADD);
}
if (!KEY_SUB) //减键按下
{
DelayMs(180);
if (!KEY_SUB)
{
if (!g_setTimeFlag)
{
if (g_isAutoAjust == 1)
{
g_isAutoAjust = 0;
}
g_PWMdutyCycle = g_PWMdutyCycle - 5;
if (g_PWMdutyCycle <= 5)
{
g_PWMdutyCycle = 5;
}
//Write_EEPROM();
}
else
{
switch (g_setLocation)
{
case 1:
{
if (timeBufDec[1] == 0)
{
timeBufDec[1] = 100;
}
timeBufDec[1]--;
break;
}
case 2:
{
timeBufDec[2]--;
if (timeBufDec[2] < 1)
{
timeBufDec[2] = 12;
}
break;
}
case 3:
{
timeBufDec[3]--;
if (timeBufDec[3] < 1)
{
timeBufDec[3] = YDay(timeBufDec[1], timeBufDec[2]);
}
break;
}
case 4:
{
if (timeBufDec[4] == 0)
{
timeBufDec[4] = 24;
}
timeBufDec[4]--;
break;
}
case 5:
{
if (timeBufDec[5] == 0)
{
timeBufDec[5] = 60;
}
timeBufDec[5]--;
break;
}
case 6:
{
if (timeBufDec[6] == 0)
{
timeBufDec[6] = 60;
}
timeBufDec[6]--;
break;
}
case 7:
{
timeBufDec[7]--;
if (timeBufDec[7] < 1)
{
timeBufDec[7] = 7;
}
break;
}
default:;
}
}
BUZZER = 0;
DelayMs(10);
BUZZER = 1;
}
//while (!KEY_SUB);
}
if (!KEY_MODE) //模式键按下
{
DelayMs(20);
while (!KEY_MODE)
{
DelayMs(20);
keyCnt++;
if (keyCnt >= 50)
{
break;
}
}
if (keyCnt >= 50)
{
if (TR0 == 1) // 长按关灯
{
g_isAutoOff = 0;
LED_PWM = 1;
TR0 = 0;
}
else //长按开灯
{
g_isAutoOff = 0;
LED_PWM = 0;
TR0 = 1;
}
}
else
{
if (g_setTimeFlag)
{
DS1302_WriteTime();
g_setLocation = 0;
g_setTimeFlag = 0;
}
else
{
g_mode++;
g_mode &= 0x03; //满4清零
//Write_EEPROM();
}
LCD_WriteCommand(0x0C, 0);
BUZZER = 0;
DelayMs(10);
BUZZER = 1;
}
keyCnt = 0;
while (!KEY_MODE);
}
}
void Init_Timer0() //定时器0初始化
{
TMOD &= 0xF0;
TMOD |= 0x01; //定时器0模式设定,16位定时器
TH0 = highT0RH;
TL0 = highT0RL; //计数值设定
TR0 = 0; //关闭定时器0计数
ET0 = 1; //打开定时器0中断开关
EA = 1; //打开总中断
}
void Init_Timer1()
{
TMOD &= 0x0F;
TMOD |= 0x10;//定时器0模式设定,16位定时器
TH1 = (65536 - 18432) / 256;
TL1 = (65536 - 18432) % 256;//计数值设定 20ms
PT1 = 1; //高优先级
TR1 = 1;//打开定时器1计数
ET1 = 1;//打开定时器1中断开关
EA = 1;//打开总中断
}
void Timer0_Interrupt() interrupt 1
{
// static unsigned int cnt = 0;
if (LED_PWM == 1) //灯光关闭时
{
TH0 = highT0RH;
TL0 = highT0RL;//设定打开时间
LED_PWM = 0; //灯光打开
// cnt++;
// if (cnt >= 100)
// {
// LED_STATUS = ~LED_STATUS;
// cnt = 0;
// }
}
else //灯光打开时
{
TH0 = lowT0RH;
TL0 = lowT0RL; //设定关闭时间
LED_PWM = 1; //灯光关闭
}
}
void Timer1_Interrupt() interrupt 3
{
static unsigned char j = 0;
static unsigned char n = 0;
static unsigned char oneSecond1 = 0;
TL1 = 0x00; //设置定时初始值
TH1 = 0xB8; //设置定时初始值 0.02s
j++;
if (j % 10 == 0) //200ms刷新一次液晶
{
g_dispOn = 1;
}
else if(j % 25 == 0) //500ms采集一次数据
{
j = 0;
g_getADData = 1;
}
if (IR_SCAN == 0) //有人时开始计时,2秒钟仍然有人则开灯
{
n++;
}
if (n >= 50)
{
n = 0;
oneSecond1++;
if (oneSecond1 >= 2)
{
oneSecond1 = 0;
g_OffFlag = 0;
}
}
}
设计文件: