找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3382|回复: 23
收起左侧

主函数while循环中,触发一次或连续多次蜂鸣器该怎么写..献上我惨不忍睹的单片机代码

  [复制链接]
ID:886945 发表于 2021-3-10 02:55 | 显示全部楼层 |阅读模式
     最近学习中感觉遇到了一个砍..类似于1602显示这类实时驱动的程序按照模块化编程感觉没什么问题了,但是那些触发类型的功能函数感觉很生疏...比如蜂鸣器的触发类型的驱动,然后找开发板那些程序...又都是类似于用延迟函数等蜂鸣器响完成结束了再去执行其他程序....我尝试以定时器时基的方式在主函数的while中实现蜂鸣器控制,但是感觉写的挺乱的样子,应该说写了一点点就不知道如何写了...写不出来了233     蜂鸣器需要在某些条件下响一声或是连续的几声,但是不影响while函数中其他的功能,该如何写
     附上乱写一通后无从下手的代码....有大佬能指导一下吗..     是需要加上一个蜂鸣器总控开关的标志位吗

单片机源程序如下:
  1. void buz_1()    //一声
  2. {
  3.   static uchar time_500ms=0;
  4.   if(buz_timecnt)
  5.     {
  6.       buz_timecnt=0;  //定时器中10ms置1一次
  7.       time_500ms++;
  8.       if(time_500ms>50)
  9.         {
  10.           buz_state(buz_off);   //开蜂鸣器。。有缘蜂鸣器
  11.           time_500ms=0;
  12.            buz_one_finish=1;
  13.           }
  14.     else
  15.      {
  16.       buz_state(buz_on);    //关蜂鸣器
  17.       }
  18.   }
  19. }

  20. void buz_4()    //连续响四声
  21. {
  22.   static uchar num=0;
  23.   if(num<4)   //
  24.   {
  25.       buz_1();
  26.      if(buz_one_finish==1)
  27.      {
  28.         buz_one_finish=0;
  29.         num++;   、、不知道如何写了
  30.      }
  31.    }
  32. }
复制代码




回复

使用道具 举报

ID:89515 发表于 2021-3-10 08:06 来自手机 | 显示全部楼层
只是做提示音的话用有源蜂鸣器很简单的。
回复

使用道具 举报

ID:89515 发表于 2021-3-10 08:44 来自手机 | 显示全部楼层
char t,c;
void(char t1,char c1)
{
   t=t1;//单次=溢出*t1
   c=c1;//单次时次数为0
   beep=1;//开蜂鸣器
}
void time_INT()//定时器溢出值自定
{
   if(t--==0)
   {
       if(c==0)
         beep=0;//关  
       else
         beep=~beep;
   }
}

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:89515 发表于 2021-3-10 08:49 来自手机 | 显示全部楼层
注意定时器的开启与关闭同步
回复

使用道具 举报

ID:654028 发表于 2021-3-10 09:33 | 显示全部楼层
传参不就好了,写那么多函数干嘛
回复

使用道具 举报

ID:213173 发表于 2021-3-10 11:39 | 显示全部楼层
这很简单,给你写个示例,一看就明白。
  1. #include <reg51.H>

  2. sbit Buzzer=P3^7;
  3. sbit key=P3^0;

  4. unsigned char start;

  5. /****1ms延时子程序(12MHz)****/
  6. void delayms(unsigned int k)
  7. {
  8.         unsigned int i,j;
  9.         for(i=k;i>0;i--)
  10.                 for(j=120;j>0;j--);
  11. }
  12. //num最大值与主循环周期密切关联
  13. //此例以主循环周期1ms计算,响铃周期1s
  14. void buz_4()    //1~n次声响
  15. {
  16.         static unsigned int num;
  17.         if(start>0)   //start=0~n
  18.         {
  19.                 num++;       
  20.                 if(num<=500)
  21.                         Buzzer=0;//响
  22.                 if(num>500)
  23.                         Buzzer=1;//停
  24.                 if(num>=1000)
  25.                 {
  26.                         num=0;
  27.                         start--;
  28.                 }
  29.         }
  30.         else //确保意外时能复位
  31.         {
  32.                 Buzzer=1;
  33.                 num=0;
  34.         }
  35. }

  36. void keyscan()       
  37. {
  38.         static unsigned char count=0;        //计数变量                       
  39.         static bit key_sign=0;                        //按键状态标志
  40.         if(!key)                                                //按键按下
  41.         {                       
  42.                 if(++count>=10&&key_sign==0)//计数延时消抖
  43.                 {                       
  44.                         key_sign=1;                                //按键状态标志置1,防止重复响应
  45.                         start=4;                                        //start最大赋值255
  46.                 }
  47.         }
  48.         else                                                         //松手
  49.         {
  50.                 count=0;                                        //计数变量清0
  51.                 key_sign=0;                                        //按键状态标志清0
  52.         }
  53. }
  54. void main()
  55. {
  56.         while(1)
  57.         {
  58.                 keyscan();
  59.                 buz_4();
  60.                 delayms(1);//控制主循环周期,代替其它程序所占时间
  61.         }
  62. }
复制代码
回复

使用道具 举报

ID:827243 发表于 2021-3-10 12:16 | 显示全部楼层
标准程序写法, 中断函数设定标志位,主循环处理标志位。
蜂鸣器处理办法,时钟中断处理各种鸣叫 switch case ,  主循环设置好鸣叫模式就好了。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:669393 发表于 2021-3-10 13:46 | 显示全部楼层
写在外部中断里呗,注意优先级
回复

使用道具 举报

ID:886945 发表于 2021-3-11 01:53 | 显示全部楼层
mengzhixinheng 发表于 2021-3-10 08:44
char t,c;
void(char t1,char c1)
{

谢谢大佬简单明了的代码   笔记做起!
回复

使用道具 举报

ID:886945 发表于 2021-3-11 02:07 | 显示全部楼层
wulin 发表于 2021-3-10 11:39
这很简单,给你写个示例,一看就明白。

...最开始思路确实是往这方向写的.同时响控制具体的开启时间....但是脑子脑子一抽总感觉不对劲,最后越写越乱.脑子一下子绕不过来....  感谢大佬帮我的思路延续.....让我发现错在哪里了
回复

使用道具 举报

ID:886945 发表于 2021-3-11 02:51 | 显示全部楼层
总结参考了上边两个程序,我知道我程序里边少了一个核心的东西了,标志位..第一个buz_1的函数功能基本也无问题,但是少了触发函数的条件,也就是标志位,第二个函数buz_4,在标志位列出来之后,就已经是个没用了的函数了,可以直接删除省事,但是如果真要单独写个4声的函数也是可以写出来了
回复

使用道具 举报

ID:89515 发表于 2021-3-11 18:29 来自手机 | 显示全部楼层
sdarling 发表于 2021-3-11 01:53
谢谢大佬简单明了的代码   笔记做起!

只是这样简单的提示音,担心蜂鸣器过多占用资源的话,肯定要用定时器。8位单片机定时器也是很珍贵的。没必要单独写两个函数对定时器做过多的修饰。写个带参的初始化函数,在需要提示音的地方放个初始化函数就行了,要多少声就初始化多少声,要响多长时间就多长时间。我上面的程序只是思路,有两个错误,如果你发现了自己改了就是。没有就说一下!
回复

使用道具 举报

ID:750420 发表于 2021-3-11 22:24 | 显示全部楼层
使用有源蜂鸣器,根据定时器设置的时间标志位改变蜂鸣器io输出状态即可
回复

使用道具 举报

ID:886945 发表于 2021-3-12 00:34 | 显示全部楼层
mengzhixinheng 发表于 2021-3-11 18:29
只是这样简单的提示音,担心蜂鸣器过多占用资源的话,肯定要用定时器。8位单片机定时器也是很珍贵的。没 ...

这样可以吗.不知道大佬觉得该如何改..我放开发板上,这个程序能是能用,但是不知道IO口什么情况,明明有能力驱动三极管控制正常发声的,一上这个程序在响的时候就只有滋滋滋的声音了...


  1. char t,c;
  2. void(char t1,char c1)   
  3. {
  4.    t=t1;//单次=溢出*t1
  5.    c=c1;//单次时次数为1
  6.    beep=1;//开蜂鸣器
  7. }
  8. void time_INT()//定时器溢出值自定
  9. {
  10. static char cnt=0;
  11.   if(C>0)
  12.     {
  13.         if(++cnt<t)
  14.        {
  15.            beep=1;//开
  16.         }
  17.         else if(cnt<xx) //多次响时,xxx为间隔时间,可调
  18.         {
  19.            beep=0;
  20.          }
  21.         else
  22.         {
  23.            cnt=0;
  24.            C--;
  25.          }       
  26.      }
  27.     else  beep=0; //关
  28. }
复制代码
回复

使用道具 举报

ID:886945 发表于 2021-3-12 00:53 | 显示全部楼层
mengzhixinheng 发表于 2021-3-11 18:29
只是这样简单的提示音,担心蜂鸣器过多占用资源的话,肯定要用定时器。8位单片机定时器也是很珍贵的。没 ...

大佬有更简便的方法吗,刚刚那个用是能用的,声音不对是我其他地方弄错了
回复

使用道具 举报

ID:89515 发表于 2021-3-12 07:32 来自手机 | 显示全部楼层
sdarling 发表于 2021-3-12 00:53
大佬有更简便的方法吗,刚刚那个用是能用的,声音不对是我其他地方弄错了

char t,c;//全局变量
//蜂鸣器初始化
//c1声响次数
//t1设定单次声音的长度
/*
例:蜂鸣器单次响2秒,定时器溢出10ms
t1=200,c1=0
例:蜂鸣器响4次,每次500ms,定时器溢出10
t1=50,c1=4
如果定时器一直开启,溢出时间不能太长,
如果定时器与蜂鸣器同步开启关闭,那就无所谓
但是浪费定时器
*/
void BeepInit(char t1,char c1)//此函数哪里需要就放哪里
{
t=t1;//单次=溢出*t1
c=c1*2;//单次时次数为0
beep=1;//开蜂鸣器
}
void time_INT()//定时器溢出值自定,不同单片机函数写法自己修改
{
//这里你的定时器初值是否需要重载?
if(t--==0)
{
   if(c==0)
   beep=0;//关
   else
       {
   beep=~beep;
         c--;
        }
}
}
注意以上程序是要调用定时器的,你有准确调用定时器吗?

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:886945 发表于 2021-3-15 03:29 来自手机 | 显示全部楼层
mengzhixinheng 发表于 2021-3-12 07:32
char t,c;//全局变量
//蜂鸣器初始化
//c1声响次数

这次看懂了!   谢谢
回复

使用道具 举报

ID:886945 发表于 2021-3-15 03:41 来自手机 | 显示全部楼层
mengzhixinheng 发表于 2021-3-12 07:32
char t,c;//全局变量
//蜂鸣器初始化
//c1声响次数

但是你其中的变量t不是也还是需要重装的吗,所以也还是需要多写一个变量吧?
回复

使用道具 举报

ID:89515 发表于 2021-3-15 18:20 来自手机 | 显示全部楼层
sdarling 发表于 2021-3-15 03:41
但是你其中的变量t不是也还是需要重装的吗,所以也还是需要多写一个变量吧?

t,c根据你的需要初始化赋值,这不叫重载。你需要怎么样的效果就怎样赋值,调用函数填入参数就行啊!!!
回复

使用道具 举报

ID:123289 发表于 2021-3-15 21:52 | 显示全部楼层
教你如何让蜂鸣器叫N声,而不影响其它程序。
1、弄清楚蜂鸣器的特性:假设是长鸣型的,且接在P1.1上,0、1可决定其鸣与不鸣。
不妨用一个标记位来决定P1.1的值,设为B_BELL,=0或1,送入P1.1就可决定鸣叫。(假设0=叫,1=停)
2、弄清楚什么是叫一声:假设叫0.5秒停0.3秒为叫一声。这就需要用两个寄存器来计时,不妨一个叫R_BUZZ用作0.5秒计时,另一个叫R_STOP用作0.3秒计时。
3、弄一个寄存器决定叫几声,设为R_N。
4、即下来就是计时了,用定时器做个中断,设中断时间=10ms。在中断子程序里做一个供蜂鸣器用的标记位,设为:B_BELLTIME,每次中断时将B_BELLTIME置1。
5、写关键的鸣叫程序了:
5.1,在主程序中查B_BELLTIME,=0说明还未中断,什么也不做,结束;=1说明中断了,进行如下处理:
5.2,清B_BELLTIME=0,防止本程序被再次执行(10ms后将由中断服务程序置1)。
5.3,查看R_N=?,=0则表示已经完成了N次鸣叫,什么也不做,结束;<>0,则表示还在鸣叫中,继续下面步骤:
5.4,查看当前正在叫B_BELL=0,还是正在停B_BELL=1?分别处理如下:
5.4.1,当前正在叫B_BELL=0,将R_BUZZ-1,即计时10ms(初始化时,让R_BUZZ=50,即0.5秒),减1后不为0,则结束,即一声还未叫完,让它继续叫着,不必动它。
       如果=0,即已叫满0.5秒了,应该停叫了。这时:复位R_BUZZ=50准备下次计时用,将B_BELL改为1,并送到P1.1,让蜂鸣器停止。
5.4.2,当前正在停B_BELL=1,将R_STOP-1,即计时10ms(初始化时,让R_STOP=30,即0.3秒),减1后不为0,则结束,即一声中的停止期未完,让它继续停着,不必动它。
       如果=0,即已停止0.3秒了,应该叫了。这时:复位R_STOP=30准备下次计时用,将B_BELL改为0,并送到P1.1,让蜂鸣器开始叫。
       5.4.1 与 5.4.2 是分支,两者只做一个。与5.4.1不同的是,5.4.2还要增加做一件重要的事:将R_N-1!!!
以上就大功告成了。

要让蜂鸣器叫8次,就让R_N=8,就行了。叫5声呢,让R_N=5。
如何让蜂鸣器在鸣叫过程中突然停止呢?是不是将R_N改为0就可以了呢?你自己想想吧,就算给你的作业吧。如果做对了,就说明你彻底理解了。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:123289 发表于 2021-3-15 21:54 | 显示全部楼层
其它程序也同样处理,关键是构思处理方案。写程序简单,照着构思写语句就可以了。
回复

使用道具 举报

ID:886945 发表于 2021-3-18 03:39 来自手机 | 显示全部楼层
yzwzfyz 发表于 2021-3-15 21:52
教你如何让蜂鸣器叫N声,而不影响其它程序。
1、弄清楚蜂鸣器的特性:假设是长鸣型的,且接在P1.1上,0、1 ...

主要还是看的资料少,按楼上老哥思路差不多已经自己弄了一个了,之前看的都是那些直接上延迟的操作,想找贴近实际项目的教程很难找
回复

使用道具 举报

ID:275826 发表于 2021-3-18 16:11 | 显示全部楼层
yzwzfyz 发表于 2021-3-15 21:52
教你如何让蜂鸣器叫N声,而不影响其它程序。
1、弄清楚蜂鸣器的特性:假设是长鸣型的,且接在P1.1上,0、1 ...

假如是无源蜂鸣器,怎么写呢?
回复

使用道具 举报

ID:798631 发表于 2021-3-19 09:17 | 显示全部楼层
弄好了之后 再发散一下   自己编写一个  通用函数以后可以用一辈子
    RunTask(  *Task(),uint8 Delay,uint8 Period,uint8 RunTimes)         

*Task() 是任务函数   Period  扫描执行的间隔    Delay初值=Period 然后在时基标志时--  到0时再赋值Period RunTimes是任务次数   任务执行的条件RunTimes大于1
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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