找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1126|回复: 0
收起左侧

基于51单片机声音传感器控制灯渐亮源程序 数值如何保持?

[复制链接]
ID:994927 发表于 2021-12-22 16:55 | 显示全部楼层 |阅读模式
想要通过光敏传感器和声音传感器控制led渐亮,如果光小于某个值并且检测到声音的话,让led像呼吸灯一样渐渐亮起来
但是我的代码只能在串口接收到数值,led不能渐渐亮起来,并且渐亮以后,怎么能在下一次获得传感器数值之前保持住呢?

单片机源程序如下:
  1. #include "stc8a.h"                                //头文件
  2. #include "stdio.h"
  3. #include "intrins.h"

  4. typedef unsigned char u8;                        //别名

  5. u8 Tcount, dutyfactor=0, direct;                //一个PWM周期内的:周期计数,占空比,方向

  6. sbit LED = P2^0;                                        //位定义,led灯引脚
  7. unsigned int dat;
  8. char y=0;
  9. float ftemp1,ftemp2;
  10. float miniftemp=2.0;
  11. float ratio=0.1;
  12. float d_value;
  13. float buf1=0.0,buf2=0.0;
  14. char str[10];
  15. int i,t;

  16. void InterruptInit();                                //中断初始化配置的函数声明
  17. void Time0();                                                 //定时器0中断的函数声明
  18. void display( );
  19. void breatheLED();                                        //呼吸灯主程序的函数声明
  20. int dec,inc;

  21. void delay(int b)
  22. {
  23.         while(b--);
  24.         }

  25. void UartInit(void)                //9600bps@11.0592MHz
  26. {
  27.         SCON = 0x50;                //8位数据,可变波特率
  28.         AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
  29.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  30.         TMOD &= 0x0F;                //设定定时器1为16位自动重装方式
  31.         TL1 = 0xE0;                //设定定时初值
  32.         TH1 = 0xFE;                //设定定时初值
  33.         ET1 = 0;                //禁止定时器1中断
  34.         TR1 = 1;                //启动定时器1
  35. }

  36. void Delay1000ms()                //@11.0592MHz
  37. {
  38.         unsigned char i, j, k;

  39.         _nop_();
  40.         i = 8;
  41.         j = 1;
  42.         k = 243;
  43.         do
  44.         {
  45.                 do
  46.                 {
  47.                         while (--k);
  48.                 } while (--j);
  49.         } while (--i);
  50. }




  51. //主函数
  52. void main() {
  53.         //InterruptInit();                                //初始化中断配置
  54.         UartInit();

  55.         //循环实现呼吸灯功能
  56.         //PWM周期:20ms;占空比:0~100;占空比每一份:200us;一次呼吸灯效果(暗->亮->暗):4s
  57.         while(1) {
  58.                  P1M0 = 0x00;                                //设置P1.0为ADC口
  59.      P1M1 = 0x01;

  60.     ADCCFG = 0x2f;                              //设置ADC时钟为系统时钟/2/16/16
  61.     ADC_CONTR = 0x80;                           //使能ADC模块 1000 0000
  62.                 ADC_CONTR |= 0x40;                      //启动AD转换 P1.0        1000 0000 || 0100 0000=1100 0000
  63.                 _nop_();
  64.                 _nop_();
  65.                 while (!(ADC_CONTR & 0x20));            //查询ADC完成标志
  66.                 ADC_CONTR &= ~0x20;                     //清完成标志
  67.                 //ADC_RES(高4位) ADC_RESL(低8位);                           //读取ADC结果
  68.                 dat=ADC_RES*256+ADC_RESL;
  69.                 buf1=ftemp1;//保存上一次的值
  70.                 ftemp1=dat;
  71.                 ftemp1=ftemp1*3.3/4096;//此时环境的暗亮程度
  72. //                printf("The intensity is ");
  73.                 sprintf(str,"%.2f\r\n\0",ftemp1);
  74.                 i=0;
  75.                 while(str[i]!=0)
  76.                 {
  77.                         SBUF=str[i];
  78.                         while(!TI);
  79.                         TI=0;
  80.                         i++;
  81.                 }
  82.                 Delay1000ms();
  83.                
  84.                 ADC_CONTR = 0x81;                           //使能ADC模块 1000 0000
  85.                 ADC_CONTR |= 0x40;                      //启动AD转换 P1.0        1000 0000 || 0100 0000=1100 0000
  86.                 _nop_();
  87.                 _nop_();
  88.                 while (!(ADC_CONTR & 0x20));            //查询ADC完成标志
  89.                 ADC_CONTR &= ~0x20;                     //清完成标志
  90.                 //ADC_RES(高4位) ADC_RESL(低8位);                           //读取ADC结果
  91.                 dat=ADC_RES*256+ADC_RESL;
  92.                 buf2=ftemp2;//保存上一次的值
  93.                 ftemp2=dat;
  94.                 ftemp2=ftemp2*3.3/4096;//此时环境的暗亮程度
  95. //                printf("The noise is ");
  96.                 sprintf(str,"%.2f\r\n\0",ftemp2);
  97.                 i=0;
  98.                 while(str[i]!=0)
  99.                 {
  100.                         SBUF=str[i];
  101.                         while(!TI);
  102.                         TI=0;
  103.                         i++;
  104.                 }
  105.                 Delay1000ms();
  106.                
  107.                
  108.                 if(ftemp1 < miniftemp && ftemp2 > 0.0)
  109.                 {
  110.                         breatheLED();
  111.                 }                        //呼吸灯效果实现
  112.                 else         LED=1;
  113.         }        
  114. }

  115. //中断初始化配置
  116. void InterruptInit() {
  117.         TMOD &= 0xf0;                                        //定时器0设置清除
  118.         TMOD |= 0x02;                                        //定时器0,8位自动重装载
  119.         
  120.         //初值
  121.         TH0 = 0x9C;                                                //100us定时,2^8-11.0592M / 12 * 200us
  122.         TL0 = 0x9C;                                                //自动重装载,低八位等于高八位
  123.         
  124.         ET0 = 1;                                                //打开定时器0中断允许
  125.         EA  = 1;                                                //打开总中断
  126.         
  127.         TR0 = 1;                                                //启动定时器0
  128. }

  129. //定时器0中断
  130. void Time0() interrupt 1 {
  131.         //200us初值重装
  132.         TH0 = 0x9C;                                                               
  133.         TL0 = 0x9C;               
  134.         
  135.         Tcount++;                                                //一个PWM周期内,计数
  136. }

  137. //呼吸灯主程序
  138. void breatheLED( ) {
  139.                 if(Tcount >= 100) {                                //一个PWM周期(4000次*100us)
  140.                         Tcount = 0;                                        //下一个PWM周期内,重新计数
  141.                         
  142.                         
  143.                         //根据占空比值判断方向是否需要改变
  144.                         if(ftemp2 > buf2) {                        //占空比减少到0
  145.                                 direct = 1;                                        //正方向,占空比开始增加
  146.                         } else if(ftemp2 < buf2) {        //占空比增加到100
  147.                                 direct = 0;                                        //负方向,占空比开始减少
  148.                         }
  149.                         
  150.                         //根据方向判断占空比增加或减少
  151.                         if(direct == 1) {                        //正方向,占空比增
  152.                                 d_value=(ftemp2-buf2)/ratio;
  153.                                 inc=floor(d_value);
  154.                                 dutyfactor=dutyfactor+inc;                                //下一个PWM周期,占空比增加1
  155. //                                dutyfactor++;
  156.                         } else if(direct == 0) {        //负方向,占空比减少
  157.                                 d_value=(buf2-ftemp2)/ratio;
  158.                                 dec=floor(d_value);
  159.                                 dutyfactor=dutyfactor-dec;                        //下一个PWM周期,占空比减少1
  160.                                   dutyfactor--;
  161.                         }
  162.                 }
  163.                
  164.                 //占空比:通电时间相对于总时间所占的比例(此程序中:低电平时间相对于PWM周期所占的比例)
  165.                 //一个PWM周期计数100次,占空比相当于低电平的计数周期次数。即:0~占空比:低电平,灯亮;占空比~100:高电平,灯灭
  166.                 //在一个PWM周期内,根据周期计数是否小于占空比,判断LED灯的亮灭
  167.                 if(Tcount < dutyfactor) {                //周期计数值<占空比
  168.                         LED = 0;                                        //当前PWM周期的当前计数周期内灯亮
  169.                 } else {
  170.                         LED = 1;                                        //当前PWM周期的当前计数周期内灯灭
  171.                 }

  172. }
复制代码

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表