OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5849|回复: 11

求一个stm32 pwm控制蜂鸣器的程序或者有人能帮我解决以下问题

[复制链接]

3

主题

9

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2018-8-12
在线时间
5 小时
发表于 2018-8-16 12:44:09 | 显示全部楼层 |阅读模式
10金钱
我做了一个小车,小车功能有LDC铁丝寻迹,检测硬币报警,LCD1602秒表。  。没加秒表的时候用蜂鸣器报警没问题,后来加了个TIM定时器作秒表,蜂鸣器报警的时候程序经常就卡死了,我的LDC都读不到数据了,
我把蜂鸣器或者秒表去掉程序都不会卡死,不知道是什么问题。
蜂鸣器是无源的 ,用的延时函数,我就想试一试再加一个TIM用PWM驱动蜂鸣器看看能不能解决问题

我已经用了TIM2,3,4了 就剩个5了
求个程序或者求大佬们帮忙分析解决一下问题

最佳答案

查看完整内容[请看2#楼]

完全可以用TIM驱动蜂鸣器.........只是pwm用在蜂鸣器上是用来调蜂鸣器的音调的(简单地说就是可以用pwm和蜂鸣器简单地做一个电子钢琴...)估计是你的延时卡住了,延时是很不好的一个东西,稍微哪里用的不好就要出问题。 用定时器驱动蜂鸣器:你可以设个flag,当你检测到硬币时,flag置1,否则置0; 然后在定时器里判断flag的值,若flag为1则驱动蜂鸣器,若为0则关闭蜂鸣器。定时器周期你可以根据你的板子来确定,要求不高,周期 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2018-8-16 12:44:10 | 显示全部楼层
完全可以用TIM驱动蜂鸣器.........只是pwm用在蜂鸣器上是用来调蜂鸣器的音调的(简单地说就是可以用pwm和蜂鸣器简单地做一个电子钢琴...)估计是你的延时卡住了,延时是很不好的一个东西,稍微哪里用的不好就要出问题。
用定时器驱动蜂鸣器:你可以设个flag,当你检测到硬币时,flag置1,否则置0;
然后在定时器里判断flag的值,若flag为1则驱动蜂鸣器,若为0则关闭蜂鸣器。定时器周期你可以根据你的板子来确定,要求不高,周期不要太长就行。如果你这样子写了程序会比你之前那样写效果好很多
猪猪熊呢?
回复

使用道具 举报

3

主题

9

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2018-8-12
在线时间
5 小时
 楼主| 发表于 2018-8-22 09:10:40 | 显示全部楼层
323232 发表于 2018-8-16 13:49
完全可以用TIM驱动蜂鸣器.........只是pwm用在蜂鸣器上是用来调蜂鸣器的音调的(简单地说就是可以用pwm和蜂 ...

pwm驱动蜂鸣器只能调音调吗 我只是想让他响一下不行吗  这个东西我真不懂,能给我个程序吗?
回复

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2018-8-22 09:46:44 | 显示全部楼层
你的是无源蜂鸣器额...确实 要用pwm驱动,方便上代码吗?你把蜂鸣器的延时去掉试试
猪猪熊呢?
回复

使用道具 举报

3

主题

9

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2018-8-12
在线时间
5 小时
 楼主| 发表于 2018-8-22 10:22:17 | 显示全部楼层
323232 发表于 2018-8-22 09:46
你的是无源蜂鸣器额...确实 要用pwm驱动,方便上代码吗?你把蜂鸣器的延时去掉试试

这个是蜂鸣器驱动程序,其他代码太多 不知道你要看哪个
#include "buzzer.h"
#include "interface.h"

void BUZZER_Init(void){ //蜂鸣器的接口初始化
        GPIO_InitTypeDef  GPIO_InitStructure;        
    GPIO_InitStructure.GPIO_Pin = BUZZER; //选择端口号                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //选择IO接口工作方式      
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置IO接口速度(2/10/50MHz)   
        GPIO_Init(BUZZERPORT, &GPIO_InitStructure);       
       
        GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鸣器接口输出高电平1               
}

void BUZZER_BEEP1(void){ //蜂鸣器响一声
        u16 i;
        for(i=0;i<200;i++){
                GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(0)); //蜂鸣器接口输出0
                Delay_us(500); //延时               
                GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鸣器接口输出高电平1
                Delay_us(500); //延时               
        }
}
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-8-22 10:29:39 | 显示全部楼层
你碰到的是一般初学者(特别是学生)经常会碰到的问题, 就是Delay, Delay不是说不可以用, 就是不能随便用
Delay是等于停止一切工作(中断除外)只在默默的等, 这既是浪费CPU的资源, 又是制造问题
最严重的更是在中断处理时用Delay
把Delay从你的字典删去吧
回复

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2018-8-22 10:32:59 | 显示全部楼层
你的延时是执行一次BUZZER_BEEP1();这个函数就有0.5*2*200=200ms,而你运行其他句子的时候只有几微秒的时间,总的下来只要满足蜂鸣器的条件,你的程序就有99%的时间都在运行蜂鸣器的程序........建议你把你写的这个pwm改成用定时器产生pwm,或者网上查一查引脚输出pwm
猪猪熊呢?
回复

使用道具 举报

3

主题

9

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2018-8-12
在线时间
5 小时
 楼主| 发表于 2018-8-22 12:37:28 | 显示全部楼层
323232 发表于 2018-8-22 10:32
你的延时是执行一次BUZZER_BEEP1();这个函数就有0.5*2*200=200ms,而你运行其他句子的时候只有几微秒的时间 ...

我才发现TIM5的端口和TIM2是重复的,所以我好像不能用PWM 了...其实我最不懂的是为什么在我没有加TIM4作秒表的时候小车是可以正常运行的,蜂鸣器也不会影响的,加了TIM4秒表之后,这两个就冲突了.在我加TIM4秒表之前也已经使用了TIM2 和 TIM3,他俩就不会和蜂鸣器冲突,
这是我TIM4的代码
#include "tim.h"
#include "lcd1602.h"
#include "speedctrol.h"
//定时器时间计算公式Tout = ((重装载值+1)*(预分频系数+1))/时钟频率;
//例如:1秒定时,重装载值=9999,预分频系数=7199

void TIM4_Init(u16 arr,u16 psc){  //TIM4 初始化 arr重装载值 psc预分频系数
    TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStrue;
   
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能TIM4
    TIM4_NVIC_Init (); //开启TIM4中断向量
             
    TIM_TimeBaseInitStrue.TIM_Period=arr; //设置自动重装载值
    TIM_TimeBaseInitStrue.TIM_Prescaler=psc; //预分频系数
    TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up; //计数器向上溢出
    TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1; //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1
    TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStrue); //TIM4初始化设置
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);//使能TIM4中断   
    TIM_Cmd(TIM4,ENABLE); //使能TIM4
}

void TIM4_NVIC_Init (void){ //开启TIM4中断向量
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;       
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x3;        //设置抢占和子优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x3;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}

void TIM4_IRQHandler(void){ //TIM4中断处理函数
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET){        //判断是否是TIM4中断
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
                        second++;
                        distance = (front_left_speed+front_right_speed)/2*second;
                                LCD_Setpos_Dispnum(1,5,second);
                        LCD_Setpos_Dispnum(2,9,distance);

        //此处写入用户自己的处理程序
    }
}
这是我用到蜂鸣器的寻迹函数
void SearchRun(void)
{
                if(ProximityData/10>=2200&ProximityData2/10>=2600&ProximityData/10<=2399&ProximityData2/10<=2690)
        {
                ctrl_comm = COMM_UP;       
        }
       
         if(ProximityData2/10 > 2690&ProximityData2/10 <=3000)//
        {
                ctrl_comm = COMM_RIGHT;
        }
         if(ProximityData/10 > 2399&ProximityData/10<=2550)//
        {
                ctrl_comm = COMM_LEFT;
        }
         if(ProximityData/10 > 2550 | ProximityData2/10>3000)
        {
                BUZZER_BEEP1();
                if(ProximityData/10 > 2550)
                        ctrl_comm = COMM_RIGHT;
                if(ProximityData2/10>3000)
                        ctrl_comm = COMM_LEFT;
        }
               
}
回复

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2018-8-22 13:09:49 | 显示全部楼层
保温杯里泡枸杞 发表于 2018-8-22 12:37
我才发现TIM5的端口和TIM2是重复的,所以我好像不能用PWM 了...其实我最不懂的是为什么在我没有加TIM4作秒 ...

Delay_us(500); //延时   你把程序里的这两个延时先去了试试
猪猪熊呢?
回复

使用道具 举报

2

主题

66

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
204
金钱
204
注册时间
2017-8-20
在线时间
49 小时
发表于 2018-8-22 14:02:50 | 显示全部楼层
我从51 PIC ARM从不用delay()函数,实时的可在中断处理,1ms以上非实时的可用滴答定时器,定义一个用户临时滴答寄存器,用标准滴答寄存器值减用户临时滴答寄存器的值就是知道延时了多长时间,当然在计时时要先将用户临时滴答寄存器=标准滴答寄存器值
回复

使用道具 举报

3

主题

9

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2018-8-12
在线时间
5 小时
 楼主| 发表于 2018-8-22 14:33:50 | 显示全部楼层
323232 发表于 2018-8-22 13:09
Delay_us(500); //延时   你把程序里的这两个延时先去了试试

去了延时程序不会卡住了,就是蜂鸣器叫声有点低  ,不过应该影响不大  ,谢谢你的帮助 我再按楼下大佬说的研究研究
回复

使用道具 举报

9

主题

796

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2038
金钱
2038
注册时间
2017-8-2
在线时间
522 小时
发表于 2018-8-22 14:38:41 | 显示全部楼层
本帖最后由 323232 于 2018-8-22 14:41 编辑
保温杯里泡枸杞 发表于 2018-8-22 14:33
去了延时程序不会卡住了,就是蜂鸣器叫声有点低  ,不过应该影响不大  ,谢谢你的帮助 我再按楼下大佬说的 ...

就是你加了延时。延时时间太长了,运行时间占总周期的比太大,导致程序像是卡住了一样。

你这个蜂鸣器的延时,可以用定时器代替,就像我一开始回复的那样。就能让他正常发声了。网上搜一下定时器驱动无源蜂鸣器吧,其实我没用过无源的,我也不清楚怎么用比较好,应该是用定时器或者引脚pwm驱动比较好一点,以后坚决不要用delay!
猪猪熊呢?
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-11 10:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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