硬件设计
该硬件设计是基于51单片机为MCU,ADC采用ADC0804,电机驱动芯片是L298,显示部分采用的是4位数码管。
ADC0804芯片的简介:
- 工作电压:+5V,即VCC=+5V。
- 模拟转换电压范围:0~+5V,即0≤Vin≤+5V。
- 分辨率:8位,即分辨率为1/28=1/256,转换值介于0~255之间。
- 转换时间:100us(fCK=640KHz时)。
- 转换误差:±1LSB。
- 参考电压:2.5V,即Vref/2=2.5V。
L298N简介:
- 类型 : 全桥
- 输入类型 : 非反相
- 输出数 :4
- 电流-输出/通道 :2A
- 电流-峰值输出 :3A
- 电源电压 :4.5 V ~ 46 V
- 工作温度 :-25°C ~ 130°C
仿真图如下:
手动模式
自动模式下设置光强的上下限
程序设计
/*********51单片机智能窗帘设计*********/
/*************JJ电子直营店*************/
/***************原创设计***************/
#include <REGX52.H> //头文件
#define uchar unsigned char
#define uint unsigned int
#define CS P3_0 //ADC0804 CS端口
#define RD P3_1 //ADC0804 RD端口
#define WR P3_2 //ADC0804 WR端口
#define g_kz P2_5 //数码管个位控制
#define s_kz P2_4 //数码管十位控制
#define b_kz P2_3 //数码管百位控制
#define q_kz P2_2 //码管千位控制
#define SMG_XS P0 //数码管显示端口
#define AD_data P1 //ADC0804输出端口
#define Up P2_1 //上限限位开关端口
#define Down P2_0 //下限限位开关端口
#define Key1 P3_3 //手动/自动切换 按键
#define Key2 P3_4 //定时/光控功能切换 按键
#define Key3 P3_5 //设置 按键
#define Key4 P3_6 //加 按键 (手动模式:打开窗帘 定时模式:定时打开窗帘)
#define Key5 P3_7 //减 按键 (手动模式:关闭窗帘 定时模式:定时关闭窗帘)
#define IA P2_7 //直流电机控制端口
#define IB P2_6 //直流电机控制端口
int adval; //ADC 输出变量
int j; //定义循环变量 i j
uchar flag=0; //显示标志位(0:正常显示 1:上限光照度设置(调时) 2:下限光照度设置(调分)
bit flag_gd=0; //光控/定时标志位(0:当前光照度 1:定时时间 )
bit ms=0; //模式(0:手动模式 1:自动模式)
bit move=0; //定时时间到标志位(0:时间未到 1:时间到)
bit OFF_ON=0; //电机正反转标志位,表示窗帘打开或关闭(0:窗帘关闭 1:窗帘打开)
bit Time_OFF_ON=0;//定时时间到执行窗帘打开或关闭(0:定时关闭窗帘 1:定时打开窗帘)
char hour=12,min=0;sec=0; //定义时间 “时 分 秒”变量 上电默认12.00.00
char num=0; //时间基数
uint H_GM=240; //定义上限光敏度设置变量,上电默认200
uint L_GM=100; //定义下限光敏度设置变量,上电默认100
uchar t=1; //数码管动态扫描延时参数
uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
//数码管显示数组 0 1 2 3 4 5 6 7 8 9
void delay(uint time) //延时函数
{
uint x,y; //定义临时变量 x y
for(x=time;x>0;x--)
for(y=110;y>0;y--); //空操作
}
void Time_init() //定时器初始化
{
EA=1;
TMOD=0x11;
/*定时器0初始化(产生PWM控制电机转速)*/
TH0=0xf8; //定时2ms
TL0=0xcc;
ET0=1; //使能T0中断
TR0=0; //先不启动定时器0
/*定时器1初始化(产生50ms定时时间)*/
TH1=0x4c; //50ms
TL1=0x00;
ET1=1;
TR1=0; //先不启动定时器1
}
void Key_cl()
{
static bit keybuf1=1; //Key1值暂存,临时保存按键扫描值
static bit backup1=1; //Key1值备份,保存前一次的扫描值
static bit keybuf2=1; //Key2值暂存,临时保存按键扫描值
static bit backup2=1; //Key2值备份,保存前一次的扫描值
static bit keybuf3=1; //Key3值暂存,临时保存按键扫描值
static bit backup3=1; //Key3值备份,保存前一次的扫描值
static bit keybuf4=1; //Key4值暂存,临时保存按键扫描值
static bit backup4=1; //Key4值备份,保存前一次的扫描值
static bit keybuf5=1; //Key5值暂存,临时保存按键扫描值
static bit backup5=1; //Key5值备份,保存前一次的扫描值
keybuf1=Key1; //把Key1当前值扫描值暂存
if(keybuf1!=backup1) //Key1当前值与前次值不相等,说明Key1按键有动作
{
delay(1); //延时去抖
if(keybuf1==Key1) //判断Key1扫描值有没有发生变化,即按键抖动
{
if(backup1==1) //Key1按键按下有效
{
move=0; //重置时间标志位为0(时间未到)
TR0=0; //关闭定时器0
ms=~ms; // 模式取反
q_kz=1;b_kz=1;s_kz=1;g_kz=1;//关闭数码管显示
IA=0;IB=0; //窗帘停止
}
backup1=keybuf1; //更新备份Key1当前值,以备进行下次比较
}
}
if(ms==0) //手动模式下
{
if(Key4==0) //当打开窗帘按键 按下
{
delay(10); //延时去抖
if(Key4==0) //再判断按键是否按下
{
move=0; //重置时间标志位为0(时间未到)
OFF_ON=1; //窗帘打开
TR0=1; //开启定时器0
SMG_XS=table[1]; //数码管显示"1"
q_kz=1;b_kz=1;s_kz=1;g_kz=0; //个位显示
while(Key4==0); //等待按键松开
TR0=0; //关闭定时器0
IA=0;IB=0; //窗帘停止
q_kz=1;b_kz=1;s_kz=1;g_kz=1; //关闭数码管
}
}
if(Key5==0) //当关闭窗帘按键 按下
{
delay(10); //延时去抖
if(Key5==0) //再判断按键是否按下
{
move=0; //重置时间标志位为0(时间未到)
OFF_ON=0; //窗帘关闭
TR0=1; //开启定时器0
SMG_XS=table[0]; //数码管显示"0"
q_kz=1;b_kz=1;s_kz=1;g_kz=0; //个位显示
while(Key5==0); //等待按键松开
TR0=0; //关闭定时器0
IA=0;IB=0; //窗帘停止
q_kz=1;b_kz=1;s_kz=1;g_kz=1; //关闭数码管
}
}
}
else //自动模式下
{
keybuf2=Key2; //把Key2当前值扫描值暂存
if(keybuf2!=backup2) //Key2当前值与前次值不相等,说明Key2按键有动作
{
delay(1); //延时去抖
if(keybuf2==Key2) //判断Key2扫描值有没有发生变化,即按键抖动
{
if(backup2==1) //Key2按键按下有效
{
move=0; //重置时间标志位为0(时间未到)
flag_gd=~flag_gd; //光控/定时标志位取反(0:当前光照度 1:定时时间 )
}
backup2=keybuf2; //更新备份Key2当前值,以备进行下次比较
}
}
keybuf3=Key3; //把Key3当前值扫描值暂存
if(keybuf3!=backup3)//Key3当前值与前次值不相等,说明Key3按键有动作
{
delay(1); //延时去抖
if(keybuf3==Key3) //判断Key3扫描值有没有发生变化,即按键抖动
{
if(backup3==1) //Key3按键按下有效
{
move=0; //重置时间标志位为0(时间未到)
TR0=0; //关闭定时器0
flag++;
if(flag==3) {flag=0;} //让flag保持在0-2之间
}
backup3=keybuf3;//更新备份Key3当前值,以备进行下次比较
}
}
if(flag==1) //允许上限光照度设置(调时)
{
keybuf4=Key4; //把Key4当前值扫描值暂存
if(keybuf4!=backup4)//Key4当前值与前次值不相等,说明Key4按键有动作
{
delay(1); //延时去抖
if(keybuf4==Key4) //判断Key4扫描值有没有发生变化,即按键抖动
{
if(backup4==1) //Key4按键按下有效
{
if(flag_gd==0) //光照度设置允许
{
H_GM++; //设置上限光敏度加1
if(H_GM==256) {H_GM=0;} //让光敏度在0-255之间
}
else //否则 调时允许
{
hour++; //时加1
if(hour==24) {hour=0;} //hour保持在0-23之间
}
}
backup4=keybuf4;//更新备份Key4当前值,以备进行下次比较
}
}
keybuf5=Key5; //把Key5当前值扫描值暂存
if(keybuf5!=backup5)//Key5当前值与前次值不相等,说明Key5按键有动作
{
delay(1); //延时去抖
if(keybuf5==Key5) //判断Key5扫描值有没有发生变化,即按键抖动
{
if(backup5==1) //Key5按键按下有效
{
if(flag_gd==0) //光照度设置允许
{
H_GM--; //设置上限光敏度减1
if(H_GM==-1) {H_GM=255;} //让光敏度在0-255之间
}
else //否则 调时允许
{
hour--; //时减1
if(hour==-1) {hour=23;} //hour保持在0-23之间
}
}
backup5=keybuf5;//更新备份Key5当前值,以备进行下次比较
}
}
}
if(flag==2) //下限光照度设置(调分)
{
keybuf4=Key4; //把Key4当前值扫描值暂存
if(keybuf4!=backup4)//Key4当前值与前次值不相等,说明Key4按键有动作
{
delay(1); //延时去抖
if(keybuf4==Key4) //判断Key4扫描值有没有发生变化,即按键抖动
{
if(backup4==1) //Key4按键按下有效
{
if(flag_gd==0) //光照度设置允许
{
L_GM++; //设置下限光敏度加1
if(L_GM==256) {L_GM=0;} //让光敏度在0-255之间
}
else //否则 调分允许
{
min++; //分加1
if(min==60) {min=0;} //min保持在0-59之间
}
}
backup4=keybuf4;//更新备份Key4当前值,以备进行下次比较
}
}
keybuf5=Key5; //把Key5当前值扫描值暂存
if(keybuf5!=backup5)//Key5当前值与前次值不相等,说明Key5按键有动作
{
delay(1); //延时去抖
if(keybuf5==Key5) //判断Key5扫描值有没有发生变化,即按键抖动
{
if(backup5==1) //Key5按键按下有效
{
if(flag_gd==0) //光照度设置允许
{
L_GM--; //设置下限光敏度减1
if(L_GM==-1) {L_GM=255;} //让光敏度在0-255之间
}
else //否则 调分允许
{
min--; //分减1
if(min==-1) {min=59;} //min保持在0-59之间
}
}
backup5=keybuf5;//更新备份Key5当前值,以备进行下次比较
}
}
}
if(flag_gd==1&&flag==0) //在正常显示倒计时的情况下
{
keybuf4=Key4; //把Key4当前值扫描值暂存
if(keybuf4!=backup4)//Key4当前值与前次值不相等,说明Key4按键有动作
{
delay(1); //延时去抖
if(keybuf4==Key4) //判断Key4扫描值有没有发生变化,即按键抖动
{
if(backup4==1) //Key4按键按下有效
{
Time_OFF_ON=1; //定时开启窗帘
}
backup4=keybuf4;//更新备份Key4当前值,以备进行下次比较
}
}
keybuf5=Key5; //把Key5当前值扫描值暂存
if(keybuf5!=backup5)//Key5当前值与前次值不相等,说明Key5按键有动作
{
delay(1); //延时去抖
if(keybuf5==Key5) //判断Key5扫描值有没有发生变化,即按键抖动
{
if(backup5==1) //Key5按键按下有效
{
Time_OFF_ON=0; //定时关闭窗帘
}
backup5=keybuf5;//更新备份Key5当前值,以备进行下次比较
}
}
}
}
}
附:http://www.jh-tec.cn/archives/7119
版权声明:本文为CSDN博主「weixin_46018688」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46018688/article/details/122305422
硬件设计
该硬件设计是基于51单片机为MCU,ADC采用ADC0804,电机驱动芯片是L298,显示部分采用的是4位数码管。
ADC0804芯片的简介:
- 工作电压:+5V,即VCC=+5V。
- 模拟转换电压范围:0~+5V,即0≤Vin≤+5V。
- 分辨率:8位,即分辨率为1/28=1/256,转换值介于0~255之间。
- 转换时间:100us(fCK=640KHz时)。
- 转换误差:±1LSB。
- 参考电压:2.5V,即Vref/2=2.5V。
L298N简介:
- 类型 : 全桥
- 输入类型 : 非反相
- 输出数 :4
- 电流-输出/通道 :2A
- 电流-峰值输出 :3A
- 电源电压 :4.5 V ~ 46 V
- 工作温度 :-25°C ~ 130°C
仿真图如下:
手动模式
自动模式下设置光强的上下限
程序设计
/*********51单片机智能窗帘设计*********/
/*************JJ电子直营店*************/
/***************原创设计***************/
#include <REGX52.H> //头文件
#define uchar unsigned char
#define uint unsigned int
#define CS P3_0 //ADC0804 CS端口
#define RD P3_1 //ADC0804 RD端口
#define WR P3_2 //ADC0804 WR端口
#define g_kz P2_5 //数码管个位控制
#define s_kz P2_4 //数码管十位控制
#define b_kz P2_3 //数码管百位控制
#define q_kz P2_2 //码管千位控制
#define SMG_XS P0 //数码管显示端口
#define AD_data P1 //ADC0804输出端口
#define Up P2_1 //上限限位开关端口
#define Down P2_0 //下限限位开关端口
#define Key1 P3_3 //手动/自动切换 按键
#define Key2 P3_4 //定时/光控功能切换 按键
#define Key3 P3_5 //设置 按键
#define Key4 P3_6 //加 按键 (手动模式:打开窗帘 定时模式:定时打开窗帘)
#define Key5 P3_7 //减 按键 (手动模式:关闭窗帘 定时模式:定时关闭窗帘)
#define IA P2_7 //直流电机控制端口
#define IB P2_6 //直流电机控制端口
int adval; //ADC 输出变量
int j; //定义循环变量 i j
uchar flag=0; //显示标志位(0:正常显示 1:上限光照度设置(调时) 2:下限光照度设置(调分)
bit flag_gd=0; //光控/定时标志位(0:当前光照度 1:定时时间 )
bit ms=0; //模式(0:手动模式 1:自动模式)
bit move=0; //定时时间到标志位(0:时间未到 1:时间到)
bit OFF_ON=0; //电机正反转标志位,表示窗帘打开或关闭(0:窗帘关闭 1:窗帘打开)
bit Time_OFF_ON=0;//定时时间到执行窗帘打开或关闭(0:定时关闭窗帘 1:定时打开窗帘)
char hour=12,min=0;sec=0; //定义时间 “时 分 秒”变量 上电默认12.00.00
char num=0; //时间基数
uint H_GM=240; //定义上限光敏度设置变量,上电默认200
uint L_GM=100; //定义下限光敏度设置变量,上电默认100
uchar t=1; //数码管动态扫描延时参数
uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
//数码管显示数组 0 1 2 3 4 5 6 7 8 9
void delay(uint time) //延时函数
{
uint x,y; //定义临时变量 x y
for(x=time;x>0;x--)
for(y=110;y>0;y--); //空操作
}
void Time_init() //定时器初始化
{
EA=1;
TMOD=0x11;
/*定时器0初始化(产生PWM控制电机转速)*/
TH0=0xf8; //定时2ms
TL0=0xcc;
ET0=1; //使能T0中断
TR0=0; //先不启动定时器0
/*定时器1初始化(产生50ms定时时间)*/
TH1=0x4c; //50ms
TL1=0x00;
ET1=1;
TR1=0; //先不启动定时器1
}
void Key_cl()
{
static bit keybuf1=1; //Key1值暂存,临时保存按键扫描值
static bit backup1=1; //Key1值备份,保存前一次的扫描值
static bit keybuf2=1; //Key2值暂存,临时保存按键扫描值
static bit backup2=1; //Key2值备份,保存前一次的扫描值
static bit keybuf3=1; //Key3值暂存,临时保存按键扫描值
static bit backup3=1; //Key3值备份,保存前一次的扫描值
static bit keybuf4=1; //Key4值暂存,临时保存按键扫描值
static bit backup4=1; //Key4值备份,保存前一次的扫描值
static bit keybuf5=1; //Key5值暂存,临时保存按键扫描值
static bit backup5=1; //Key5值备份,保存前一次的扫描值
keybuf1=Key1; //把Key1当前值扫描值暂存
if(keybuf1!=backup1) //Key1当前值与前次值不相等,说明Key1按键有动作
{
delay(1); //延时去抖
if(keybuf1==Key1) //判断Key1扫描值有没有发生变化,即按键抖动
{
if(backup1==1) //Key1按键按下有效
{
move=0; //重置时间标志位为0(时间未到)
TR0=0; //关闭定时器0
ms=~ms; // 模式取反
q_kz=1;b_kz=1;s_kz=1;g_kz=1;//关闭数码管显示
IA=0;IB=0; //窗帘停止
}
backup1=keybuf1; //更新备份Key1当前值,以备进行下次比较
}
}
if(ms==0) //手动模式下
{
if(Key4==0) //当打开窗帘按键 按下
{
delay(10); //延时去抖
if(Key4==0) //再判断按键是否按下
{
move=0; //重置时间标志位为0(时间未到)
OFF_ON=1; //窗帘打开
TR0=1; //开启定时器0
SMG_XS=table[1]; //数码管显示"1"
q_kz=1;b_kz=1;s_kz=1;g_kz=0; //个位显示
while(Key4==0); //等待按键松开
TR0=0; //关闭定时器0
IA=0;IB=0; //窗帘停止
q_kz=1;b_kz=1;s_kz=1;g_kz=1; //关闭数码管
}
}
if(Key5==0) //当关闭窗帘按键 按下
{
delay(10); //延时去抖
if(Key5==0) //再判断按键是否按下
{
move=0; //重置时间标志位为0(时间未到)
OFF_ON=0; //窗帘关闭
TR0=1; //开启定时器0
SMG_XS=table[0]; //数码管显示"0"
q_kz=1;b_kz=1;s_kz=1;g_kz=0; //个位显示
while(Key5==0); //等待按键松开
TR0=0; //关闭定时器0
IA=0;IB=0; //窗帘停止
q_kz=1;b_kz=1;s_kz=1;g_kz=1; //关闭数码管
}
}
}
else //自动模式下
{
keybuf2=Key2; //把Key2当前值扫描值暂存
if(keybuf2!=backup2) //Key2当前值与前次值不相等,说明Key2按键有动作
{
delay(1); //延时去抖
if(keybuf2==Key2) //判断Key2扫描值有没有发生变化,即按键抖动
{
if(backup2==1) //Key2按键按下有效
{
move=0; //重置时间标志位为0(时间未到)
flag_gd=~flag_gd; //光控/定时标志位取反(0:当前光照度 1:定时时间 )
}
backup2=keybuf2; //更新备份Key2当前值,以备进行下次比较
}
}
keybuf3=Key3; //把Key3当前值扫描值暂存
if(keybuf3!=backup3)//Key3当前值与前次值不相等,说明Key3按键有动作
{
delay(1); //延时去抖
if(keybuf3==Key3) //判断Key3扫描值有没有发生变化,即按键抖动
{
if(backup3==1) //Key3按键按下有效
{
move=0; //重置时间标志位为0(时间未到)
TR0=0; //关闭定时器0
flag++;
if(flag==3) {flag=0;} //让flag保持在0-2之间
}
backup3=keybuf3;//更新备份Key3当前值,以备进行下次比较
}
}
if(flag==1) //允许上限光照度设置(调时)
{
keybuf4=Key4; //把Key4当前值扫描值暂存
if(keybuf4!=backup4)//Key4当前值与前次值不相等,说明Key4按键有动作
{
delay(1); //延时去抖
if(keybuf4==Key4) //判断Key4扫描值有没有发生变化,即按键抖动
{
if(backup4==1) //Key4按键按下有效
{
if(flag_gd==0) //光照度设置允许
{
H_GM++; //设置上限光敏度加1
if(H_GM==256) {H_GM=0;} //让光敏度在0-255之间
}
else //否则 调时允许
{
hour++; //时加1
if(hour==24) {hour=0;} //hour保持在0-23之间
}
}
backup4=keybuf4;//更新备份Key4当前值,以备进行下次比较
}
}
keybuf5=Key5; //把Key5当前值扫描值暂存
if(keybuf5!=backup5)//Key5当前值与前次值不相等,说明Key5按键有动作
{
delay(1); //延时去抖
if(keybuf5==Key5) //判断Key5扫描值有没有发生变化,即按键抖动
{
if(backup5==1) //Key5按键按下有效
{
if(flag_gd==0) //光照度设置允许
{
H_GM--; //设置上限光敏度减1
if(H_GM==-1) {H_GM=255;} //让光敏度在0-255之间
}
else //否则 调时允许
{
hour--; //时减1
if(hour==-1) {hour=23;} //hour保持在0-23之间
}
}
backup5=keybuf5;//更新备份Key5当前值,以备进行下次比较
}
}
}
if(flag==2) //下限光照度设置(调分)
{
keybuf4=Key4; //把Key4当前值扫描值暂存
if(keybuf4!=backup4)//Key4当前值与前次值不相等,说明Key4按键有动作
{
delay(1); //延时去抖
if(keybuf4==Key4) //判断Key4扫描值有没有发生变化,即按键抖动
{
if(backup4==1) //Key4按键按下有效
{
if(flag_gd==0) //光照度设置允许
{
L_GM++; //设置下限光敏度加1
if(L_GM==256) {L_GM=0;} //让光敏度在0-255之间
}
else //否则 调分允许
{
min++; //分加1
if(min==60) {min=0;} //min保持在0-59之间
}
}
backup4=keybuf4;//更新备份Key4当前值,以备进行下次比较
}
}
keybuf5=Key5; //把Key5当前值扫描值暂存
if(keybuf5!=backup5)//Key5当前值与前次值不相等,说明Key5按键有动作
{
delay(1); //延时去抖
if(keybuf5==Key5) //判断Key5扫描值有没有发生变化,即按键抖动
{
if(backup5==1) //Key5按键按下有效
{
if(flag_gd==0) //光照度设置允许
{
L_GM--; //设置下限光敏度减1
if(L_GM==-1) {L_GM=255;} //让光敏度在0-255之间
}
else //否则 调分允许
{
min--; //分减1
if(min==-1) {min=59;} //min保持在0-59之间
}
}
backup5=keybuf5;//更新备份Key5当前值,以备进行下次比较
}
}
}
if(flag_gd==1&&flag==0) //在正常显示倒计时的情况下
{
keybuf4=Key4; //把Key4当前值扫描值暂存
if(keybuf4!=backup4)//Key4当前值与前次值不相等,说明Key4按键有动作
{
delay(1); //延时去抖
if(keybuf4==Key4) //判断Key4扫描值有没有发生变化,即按键抖动
{
if(backup4==1) //Key4按键按下有效
{
Time_OFF_ON=1; //定时开启窗帘
}
backup4=keybuf4;//更新备份Key4当前值,以备进行下次比较
}
}
keybuf5=Key5; //把Key5当前值扫描值暂存
if(keybuf5!=backup5)//Key5当前值与前次值不相等,说明Key5按键有动作
{
delay(1); //延时去抖
if(keybuf5==Key5) //判断Key5扫描值有没有发生变化,即按键抖动
{
if(backup5==1) //Key5按键按下有效
{
Time_OFF_ON=0; //定时关闭窗帘
}
backup5=keybuf5;//更新备份Key5当前值,以备进行下次比较
}
}
}
}
}
附:http://www.jh-tec.cn/archives/7119
版权声明:本文为CSDN博主「weixin_46018688」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46018688/article/details/122305422
暂无评论