功能介绍:
0.本系统采用STC89C52作为单片机
1.LCD1602液晶实时显示当前的雨刷状态/雨滴信息/车速/工作模式
2.自动模式下,雨刷可根据当前检测的雨滴状态和车速自动切换档位
3.手动模式下,可通过按键人工调节雨刷的档位,且有LED指示
4.手动模式下,具有自动推荐档位功能,当档位与检测雨滴值推荐档位不一致时,蜂鸣器报警,且对应档位LED闪烁。(该功能可选择开启或关闭)
5.按键可设定雨滴档位阈值
6.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:

PCB:

主程序:
#include "main.h"
/*******************变量定义*********************/
enum _MODE_DF_ dispMode;
bit modeFlag = AUTO; //模式标记
uchar setIndex = 0;
bit dispFlag = 0;
bit buzzerFlag1 = OFF;
char dis[16];
uchar waterValue = 0; //雨滴值检测
float speed = 0; //车速单位km/h
uchar THRH = 0; //定时器值
uchar THRL = 0; //定时器值
uchar ctrlLevel = 0; //雨刷档位
uchar nowCtrlLevel = 0; //当前雨刷档位
bit startFlag = 0; //点火熄火标志
bit motorSwitch = OFF; //电机开关
uchar motorSpeed = 8; //电机速度等级
bit YSSwitch = OFF; //雨刷开关
bit switchFlag2 = 0; //最佳档位提示标志
bit refreshFlag = 0;
unsigned long pulseCnt = 0;
/********************************************************
函数名称:void mian()
函数作用:主函数
参数说明:
********************************************************/
void main()
{
modeFlag = MANUAL;
MOTOR = 0;
MOTOR_N = 0; //电机关闭
Timer0_Init(); //初始化定时器0
Timer1_Init(); //初始化定时器1
EXT0_Init();
LCD_Init(); //初始化液晶
DelayMs(200); //延时有助于稳定
LCD_DispStr(4, 0, "Welcome!");
while (1) //死循环
{
if (startFlag == 1)
{
if (refreshFlag == 1) //刷新速度
{
speed = 3.6 * DIAMETER * 2 * 3.14 * (float)pulseCnt / 1000; //单位km/h
pulseCnt = 0;
EX0 = 1;
refreshFlag = 0;
}
if (dispFlag == 1)
{
dispFlag = 0;
if (dispMode == NORMAL) //正常显示模式
{
DispNormal();
if (AUTO_PIN == 1)
{
modeFlag = AUTO;
}
else
{
modeFlag = MANUAL;
}
if (modeFlag == AUTO) //自动模式
{
if (waterValue < waterLevel1) //第一段,低于最小阈值
{
YSSwitch = OFF; //雨刷关闭
ctrlLevel = 0;
}
else if (waterValue >= waterLevel1 && waterValue < waterLevel2) //第二段
{
YSSwitch = ON;
if (speed < 30)
{
ctrlLevel = 1;
}
else if (speed >= 30 && speed < 80)
{
ctrlLevel = 2;
}
else if (speed >= 80)
{
ctrlLevel = 3;
}
}
else if (waterValue >= waterLevel2 && waterValue < waterLevel3) //第三段
{
YSSwitch = ON;
if (speed >= 0 && speed < 80)
{
ctrlLevel = 2;
}
else if (speed >= 80)
{
ctrlLevel = 3;
}
}
else if (waterValue >= waterLevel3) //第四段
{
YSSwitch = ON;
ctrlLevel = 3;
}
nowCtrlLevel = ctrlLevel;
BUZZER = OFF;
}
else //手动模式
{
if (switchFlag2 == 1) //最佳档位提示开关开启
{
if (waterValue < waterLevel1) //第一段,低于最小阈值
{
ctrlLevel = 0;
}
else if (waterValue >= waterLevel1 && waterValue < waterLevel2) //第二段
{
if (speed < 30)
{
ctrlLevel = 1;
}
else if (speed >= 30 && speed < 80)
{
ctrlLevel = 2;
}
else if (speed >= 80)
{
ctrlLevel = 3;
}
}
else if (waterValue >= waterLevel2 && waterValue < waterLevel3) //第三段
{
if (speed >= 0 && speed < 80)
{
ctrlLevel = 2;
}
else if (speed >= 80)
{
ctrlLevel = 3;
}
}
else if (waterValue >= waterLevel3) //第四段
{
ctrlLevel = 3;
}
if (nowCtrlLevel != ctrlLevel && ctrlLevel != 0) //如果当前档位不等于
{
if (ctrlLevel == 1)
{
LED_LEVEL1 = ON;
}
else if (ctrlLevel == 2)
{
LED_LEVEL2 = ON;
}
else if (ctrlLevel == 3)
{
LED_LEVEL3 = ON;
}
BUZZER = ~BUZZER;
DelayMs(200);
}
else
{
BUZZER = OFF;
}
}
else
{
BUZZER = OFF;
}
}
if (nowCtrlLevel == 0)
{
LED_LEVEL1 = OFF;
LED_LEVEL2 = OFF;
LED_LEVEL3 = OFF;
}
else if (nowCtrlLevel == 1)
{
LED_LEVEL1 = ON;
LED_LEVEL2 = OFF;
LED_LEVEL3 = OFF;
THRH = 0xFA;
THRL = 0x9A; // 1.5ms
}
else if (nowCtrlLevel == 2)
{
LED_LEVEL1 = OFF;
LED_LEVEL2 = ON;
LED_LEVEL3 = OFF;
THRH = 0xFB;
THRL = 0xAE; // 1.2ms
}
else if (nowCtrlLevel == 3)
{
LED_LEVEL1 = OFF;
LED_LEVEL2 = OFF;
LED_LEVEL3 = ON;
THRH = 0xFC;
THRL = 0x66; // 1ms
}
}
}
}
KeyProcess();
}
}
/************************* 正常显示模式 *************************/
void DispNormal(void)
{
/************************* 雨滴检测 *************************/
waterValue = 100 - 100 * (ReadADC(AIN0_GND)) / 255; //读取雨滴信息
sprintf(dis, "W:%2d%% Level:%2d", (int)waterValue, (int)nowCtrlLevel);
LCD_DispStr(0, 0, dis);
/************************* 车辆速度显示 *************************/
sprintf(dis, "S:%5.1fkm/h ", speed);
LCD_DispStr(0, 1, dis);
/************************* 工作模式显示 *************************/
if (modeFlag == AUTO)
{
LCD_DispStr(12, 1, "Md:A");
}
else
{
LCD_DispStr(12, 1, "Md:M");
}
}
/************************* 雨量阈值设置显示 *************************/
void DispSetWater(unsigned char setIndex)
{
LCD_DispStr(0, 0, " L1 L2 L3 ");
sprintf(dis, " %2d%% %2d%% %2d%%", waterLevel1, waterLevel2, waterLevel3);
LCD_DispStr(0, 1, dis);
switch (setIndex)
{
case 1: LCD_SetCursor(3, 1, 1); break;
case 2: LCD_SetCursor(8, 1, 1); break;
case 3: LCD_SetCursor(13, 1, 1); break;
default:;
}
}
void EXT0_Init()
{
IT0 = 1; //下降沿触发
EX0 = 1; //使能外部中断0
EA = 1; //打开总中断
}
void EXT0_Interrupt() interrupt 0
{
pulseCnt++;
}
/************************* 定时器0初始化 *************************/
void Timer0_Init(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH0 = (65536 - 9216) / 256; //重新赋值 10ms
TL0 = (65536 - 9216) % 256;
EA = 1; //总中断打开
ET0 = 1; //定时器中断打开
TR0 = 1; //定时器开关打开
}
/************************* 定时器0中断 *************************/
void Timer0_Interrupt(void) interrupt 1
{
static unsigned int time10ms = 0;
TH0 = (65536 - 9216) / 256; //重新赋值 10ms
TL0 = (65536 - 9216) % 256;
time10ms++;
if (time10ms % 50 == 0)
{
dispFlag = 1; //显示标志
}
if (time10ms > 100)
{
time10ms = 0;
EX0 = 0;
refreshFlag = 1; //刷新速度标志
}
}
/************************* 定时器1初始化 *************************/
void Timer1_Init(void)
{
TMOD &= 0x0F; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TMOD |= 0x10; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
THRH = 0xFA;
THRL = 0x9A; // 1.5ms
TH1 = THRH; //重新赋值
TL1 = THRL;
EA = 1; //总中断打开
ET1 = 1; //定时器中断打开
TR1 = 1; //定时器开关打开
PT1 = 1;
}
/************************* 定时器1中断 *************************/
void Timer1_Interrupt(void) interrupt 3
{
static uchar motorDir = 1;
static uint motorCnt = 0;
static unsigned char IN1Count = 0;
TH1 = THRH; //重新赋值
TL1 = THRL;
if (YSSwitch == ON)
{
if (motorDir == 1)
{
motorCnt++;
BYJ48 = ((BYJ48 & 0xF0) | REV[motorCnt % 8]); //取数据
ULN_DQ3 = BIT3;
ULN_DQ2 = BIT2;
ULN_DQ1 = BIT1;
ULN_DQ0 = BIT0;
if (motorCnt >= MAXCNT)
{
motorDir = 0; //转换方向
}
}
if (motorDir == 0)
{
motorCnt--;
BYJ48 = ((BYJ48 & 0xF0) | REV[motorCnt % 8]); //取数据
ULN_DQ3 = BIT3;
ULN_DQ2 = BIT2;
ULN_DQ1 = BIT1;
ULN_DQ0 = BIT0;
if (motorCnt <= MINCNT)
{
motorDir = 1; //转换方向
}
}
}
else
{
if (motorDir == 1)
{
if (motorCnt > 0)
{
motorCnt++;
}
BYJ48 = ((BYJ48 & 0xF0) | REV[motorCnt % 8]); //取数据
ULN_DQ3 = BIT3;
ULN_DQ2 = BIT2;
ULN_DQ1 = BIT1;
ULN_DQ0 = BIT0;
if (motorCnt >= MAXCNT)
{
motorDir = 0; //转换方向
}
}
if (motorDir == 0)
{
if (motorCnt >= MINCNT)
{
motorCnt--; //回到最初的位置
}
else
{
motorDir = 1;
}
BYJ48 = ((BYJ48 & 0xF0) | REV[motorCnt % 8]); //取数据
ULN_DQ3 = BIT3;
ULN_DQ2 = BIT2;
ULN_DQ1 = BIT1;
ULN_DQ0 = BIT0;
}
}
if (motorSwitch == ON) //控制直流电机
{
IN1Count++;
if (IN1Count < motorSpeed) //占空比调节
{
MOTOR = 1; //启动
}
else if ((IN1Count >= motorSpeed) && (IN1Count <= 11)) //关闭时间段
{
MOTOR = 0;
}
else
{
IN1Count = 0; //一个周期结束
}
}
else
{
MOTOR = 0;
}
}

1555




被折叠的 条评论
为什么被折叠?



