本帖最后由 wulin 于 2019-11-1 20:56 编辑
原来的程序有缺陷,这是优化过的程序。如果再把按键程优化为短按加/减,长按连加/减更好。- //头函数
- #include <reg52.h>
- //宏定义
- #define uint unsigned int
- #define uchar unsigned char
- //uchar pdata tt[51]; //定义空数组用于AD0832取平均值
- uchar data tt[51];
- uchar scale,rsd_sec; //定义占空比比例,热释电计时秒变量
- uchar sec;
- bit flag_auto=0,flag_rsd=0;//位定义自动切换,热释电动作标志
- //uint lum; //ad0832读出值
- uchar m;
- uchar n;
- //管脚声明
- sbit LED = P2^5; //灯光控制输出
- sbit rsd = P1^5; //热释电
- sbit qiehuan=P3^7; //手动/自动切换
- sbit add=P3^6; //增加
- sbit dec=P3^5; //减小
- sbit CS=P1^3; //CS定义脚,连接ADC0832CS脚
- sbit SCL=P1^0; //SCL定义脚,连接ADC0832SCL脚
- sbit DO=P1^1; //DO定义脚,连接ADC0832DO脚
- /*****************延时函数:大约1ms************************/
- /*
- void delay(uchar i)
- {
- uchar j,k;
- for(j=i;j>0;j--)
- for(k=125;k>0;k--);
- }*/
- /***********读数模转换数据********************************************************/
- //请先了解ADC0832模数转换的串行协议,再来读本函数,主要是对应时序图来理解,
- //本函数是模拟0832的串行协议进行的
- uchar ad0832read(bit SGL,bit ODD)
- {
- uchar i=0,value=0,value1=0;
- SCL=0;
- DO=1;
- CS=0; //开始
- SCL=1; //第一个上升沿
- SCL=0;
- DO=SGL;
- SCL=1; //第二个上升沿
- SCL=0;
- DO=ODD;
- SCL=1; //第三个上升沿
- SCL=0; //第三个下降沿
- DO=1;
- for(i=0;i<8;i++)
- {
- SCL=1;
- SCL=0; //开始从第四个下降沿接收数据
- value<<=1;
- if(DO)
- value++;
- }
- for(i=0;i<8;i++)
- { //接收校验数据
- value1>>=1;
- if(DO)
- value1+=0x80;
- SCL=1;
- SCL=0;
- }
- CS=1;
- SCL=1;
- if(value==value1) //与校验数据比较,正确就返回数据,否则返回0
- return value;
- return 0;
- }
- /*****************按键函数*****************/
- void work()
- {
- static bit key_sign1=0,key_sign2=0,key_sign3=0; //按键自锁标志
- static uchar count1=0,count2=0,count3=0; //计数变量
- uint lum_mean,lum_all;
- uchar b,c;
- if(qiehuan==0) //自动切换按键按下
- {
- if(++count1==100&&key_sign1==0) //再次判断按键按下
- {
- key_sign1=1;
- flag_auto=~flag_auto; //自动模式标志位取反
- if(flag_auto==1) //当切换到手动模式时 首先将LED发光比例设置在50%
- scale=20;
- }
- }
- else //按键释放
- {
- key_sign1=0;
- count1=0;
- }
- if(flag_auto==1)
- {
- if(add==0) //加键按下
- {
- if(++count2==100&&key_sign2==0)
- {
- key_sign2=1;
- if(scale<41)//灯光比例++
- scale++;
- }
- }
- else //按键释放
- {
- key_sign2=0;
- count2=0;
- }
- if(dec==0) //减键按下时
- {
- if(++count3==100&&key_sign3==0)
- {
- key_sign3=1;
- if(scale>1)//灯光比例--
- scale--;
- }
- }
- else //按键释放
- {
- key_sign3=0;
- count3=0;
- }
- }
- else
- {
- if(flag_rsd==1) //有人在范围内时
- {
- for(b=0;b<49;b++) //将空数组tt[]内数值整体左移一位
- {
- tt[b]=tt[b+1]; //将后一数值放到前一位置
- }
- tt[49] = ad0832read(1,0);//将读出的ad数值放入tt[49]
- for(c=0;c<50;c++) //将tt[]内数值相加
- {
- lum_all=lum_all+tt[c];
- }
- lum_mean=lum_all/50; //将总数/50取出平均值
- lum_all=0; //将总数清零
- if(lum_mean<=30) scale=1;//判断取出平均值大小 小于30 发光强度0%
- else if(lum_mean>=150) scale=41;//大于150 发光强度100%
- else scale=((lum_mean-30)/3)+1;//其他值时将其计算得到发光强度 (计算目的是为了得到一个1-41之间的数值 控制灯光变化)
- }
- else
- {
- scale=1; //没有人在范围内时 将灯光亮度调至0%
- }
- }
- }
- /*********定时器初始化函数**********/
- void init()
- {
- TMOD=0x12; //T1方式1,T0方式2
- TH1=0x3c;
- TL1=0xb0; //T1赋初值50ms
- TH0=0xce; //8位自动重载
- TL0=0xce; //T0赋初值50us
- ET0=1;
- ET1=1; //打开中断允许开关
- EA=1; //中断总开关
- TR0=1;
- TR1=1; //定时器定时开关
- }
- /****************主函数**********************/
- void main()
- {
- init(); //调用初始化函数
- while(1) //循环
- {
- work(); //调用函数
- }
- }
- /******************定时器T0服务函数:脉冲发生函数*******************/
- void time0() interrupt 1
- {
- // TH0=0xff;
- // TL0=0xe7; //重新赋初值
- n++; //每50us n++
- if(n<scale) //n<设置比例时,打开灯
- {
- LED=0;
- }
- else if(n>=scale)//n大于等于设置比例时 关闭灯
- {
- LED=1;
- }
- if(n>=40) //n==40 :50us*40=2ms 500HZ
- {
- n=0; //n=0
- }
- }
- /********************定时器T0服务函数:计时和闪烁控制********************/
- void time1() interrupt 3
- {
- TH1=0x3c;
- TL1=0xb0; //重新赋初值
- if(rsd==1)
- {
- flag_rsd=1;
- rsd_sec=0;
- m=0;
- }
- else
- {
- m++; //50ms m++
- if(m==20) //到达1s时
- {
- m=0; //m=0
- rsd_sec++; //热释电计时秒++
- if(rsd_sec>=20) //热释电计时秒小于等于20 并且 热释电有信号时
- {
- flag_rsd=0; //标志位置0 停止ad0832转换 关闭灯光
- rsd_sec=0; //热释电计时秒清零
- }
- }
- }
- }
复制代码
|