用几个按键表示手动的调光,其中一个按键代表检测到人体。
一个adc转化模块:
以下为全图
代码如下,不是很好用,建议看看就好
#include<reg51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define p1 P1
#define p0 P0
#define p2 P2
#define p3 P3
#define f1(a) (65536-a)/256
#define f2(a) (65536-a)%256
sbit s4=p0^3;
sbit s5=p0^4;
sbit sdo=p1^0;
sbit cs=p1^1;
sbit sclk=p1^2;
sbit pwm1=p1^3;
uchar Auto=0;//控制时候自动;
uchar color=0;//控制颜色
uchar temp=0;//控制亮度
static uint cnt=0;
static bit keyflag=1;//标志位
static uchar keydata=0;//保存按键值
uchar adcresult=0;//记录adc的亮度结果,将adc的函数放置在定时器之中,进行实时记录;
static uint times=0;
void delay10ms();
void delay18us(void);
void delay();
void key_read_data(void);
void keyscan(void);
uchar adc(void);
uchar pwm(void);
void main(void)
{
//打开两个中断
//进行全局初始化
TMOD=0x11;//打开T1 T0,并且全部使用方式1,为16位定时器
TH0=(65536-500)/256;//b=125,125us=0.125ms,最大1khz
TL0=(65536-500)%256;
TH1=(65536-500)/256;//
TL1=(65536-500)%256;
EA=1;
ET0=1;//EA=1;总中断允许ET1=1;ET0=1;定时器中断允许;
ET1=1;
PT1=0;
PT0=1;
//ET0=1;
TR0=1;//制造pwm波形不一定要在这里就开启;
TR1=1;
cs=1;//停止adc采样
sclk=0;
sdo=1;
while(1){
delay10ms();
while(s5==0){
if(Auto==0){p2=0xf0;}
if(Auto==1)
{
switch(color)//灯色优先
{
case 0://黄白
case 1:
p2=0;
break;
case 2:
p2=0x0f;
//白
break;
case 3:
p2=0xf0;
//黄
break;
}
}
keyscan();
}
delay();
p2=0x11;
delay10ms();
p2=0x44;
delay10ms();
p2=0x88;
delay10ms();
p2=0xaa;
delay10ms();
p2=0xcc;
delay10ms();
p2=0xff;
//EA=0;
}
}
void delay10ms(void)//eliminate jitter(抖动)
{
uchar i,j;
for(i=0;i<10;i++)
for(j=0;j<10;j++)
;
}
void delay18us(void)//延时18us
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
void delay()
{
uchar i,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
//void init()//初始化{}
uchar adc(void)//得到adc数据
{
//取得adc的值并返回给pwm;
uchar i,t;
cs=0;
delay18us();
for(i=0;i<8;i++)
{
if(sdo==1)
{
t=t|0x01;
}
if(i<7)
{
t=t<<1;
}
sclk=1;
_nop_();_nop_();_nop_();_nop_();
sclk=0;
_nop_();_nop_();
}
cs=1;
//temp的值从0-256,0x00-0xff,,天然对应8个二极管,
//256分为4个段,0<= x<64(25%),64<=x<128(50%),128<=x<192(75%),192<=x<256(100%)
return t;//temp是一个二进制值,也可以直接看作是一个十六进制值
}
void key_read_data()//采集数据
{
p0=0xff;//检测低四位
_nop_();
_nop_();
_nop_();
_nop_();
keydata=p0^0x0f;//如果p0是1110,1111
//异或后会得到0001,相当于和0x0f与运算后再取反;
//如果没有按键按下,那么1111全部取值后就是0;
}
void keyscan()//重复扫描键盘;
{
key_read_data();
if(keyflag==1&&keydata>0x08)
{
if(cnt>5)
{
switch(keydata)
{
case 0x01://1110
Auto=0;//自动
break;
case 0x02://1101
Auto=0;//自动
break;
case 0x03://1100
Auto=0;//自动
break;
case 0x04://1011
Auto=0;//自动
break;
case 0x05://1010
Auto=0;//自动
break;
case 0x06://1001
Auto=0;//自动
break;
case 0x07://1000
Auto=0;//自动
break;
//以上为自动
//以下为手动
case 0x08://0111,//只有给出手动的指令
case 0x0e://0001
Auto=1;//手动
break;
case 0x09://0110
Auto=1;//手动
color++;
if(color>3)color=0;
break;
case 0x0a://0101,
Auto=1;//手动
if(temp==0);
else if(temp>0)temp--;//越接近0,亮度越高
break;
case 0x0b://0100
Auto=1;//手动
color++;
if(color>3)color=0;
if(temp>0)temp--;//越接近0,亮度越高
break;
case 0x0c://0011 同时加减亮度,则取0;
Auto=1;//手动
temp++;
if(temp>3)temp=3;
break;
case 0x0d://0010
Auto=1;//手动
color++;
if(color>3)color=0;
temp++;
if(temp>3)temp=3;
break;
case 0x0f://0000
Auto=1;//手动
color++;
if(color>3)color=0;
break;
}
keyflag=0;//禁止再次进入处理
cnt=0;
}
}
else if(0<keydata&&keydata<=0x08)
{
keyflag=1;
cnt=0;//技术清零,主要针对按键抖动情况
}
else if(keydata==0)
{
Auto=0;
keyflag=1;
cnt=0;//技术清零,主要针对按键抖动情况
}
}
//
uchar pwm(void)//返回调节占空比数字n,代表调节了
{
uint n;
uchar i;
i=adc();
//TH0=(65536/256-1000/256);//得到固定周期,
//TL0=(65536%256-1000%256);//总周期为0.1ms,100us,
//应该分为4个等级
if(i<0x40)
{
n=0;
}
else if(i<0x80)
{
n=1;
}
else if(i<0xc0)
{
n=2;
}
else//0xff
{
n=3;
}
//输入adc获得的数据,判断pwm所属于的层次,基础分为四个量级,
//0-25%,25-50,50-75,75-100,共四个光强强度对应对应的脉冲宽度;
return n;//返回等级
}
void timer0() interrupt 1//定时器T0
{
//IP决定优先级别
//IE决定是否允许中断,及中断的形式
//TCON寄存器,包括了溢出标志
//TMOD选择定时器和计数器;
TH0=(65536-500)/256;//b=500,500us=0.5ms,最大1khz
TL0=(65536-500)%256;
cnt++;
// keyscan();
times++;//times越大,频率越高;
adcresult=pwm();
if(Auto==0)//自动
{
temp=adcresult;//把手动的亮度结果反馈进入其中
}
if(times==10) //2.5 毫秒的时钟周期
{
times=0; //使 tt=0,开始新的 PWM 周期
pwm1=0; //使 LED 灯亮
}
if(temp==times) //按照当前占空比切换输出为高电平
pwm1=1; //使 LED 灯灭
}