完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近几天搞了下STM32F407 的定时器和超声波模块,遇到很多问题:
1.软件仿真不了;(在system_init函数里出现read no permission) 2.硬件仿真不了;(没办法跑入主函数,时钟不对应等等) 参考正点原子输入捕获实验 成功的改造超声波模块,50hz的更新频率,线性度十分好(亲测),有1-2cm的波动(在接受范围内,还没有加滤波) 调试时遇到很多问题,比如: 1.用示波器观潮ECHO管脚的波形正确,但是如果接上PA1(tiM5_CH2),波形紊乱 解决方法: 换一个通道(TIM_CH1),应该是 刚好PA1 接上了其他外设的元婴,也可能是芯片内部原因; 2.使用硬件仿真,单步时,一直进TIM1中断,原因是清标志的语句没有起作用。但是全速运行时,SR的更新标志有清零(这个问题保留) 这里贴出整个工程的代码。及给出一个文件的形式: 你的回复是我共享的不竭动力:(配置的备注有些有问题,以代码为准) /* ********************************************************************************************************* * Embedded Systems Building Blocks * Complete and Ready-to-Use Modules in C * * ULTRASOUND Module Driver * * (c) Copyright 2014, Fisher * * Filename : ultrasound.c * Programmer : Fisher ********************************************************************************************************* * DESCRIPTION * * 这个文件初始化超声波模块所需的IO口以及定时器等的相关配置 * 提供的接口:ultrasound_init 初始化超声波模块相关配置 * high 超声波测得的距离 * 消耗的IO口:PA1 下拉输入 TIM5_CH2输入捕获IO口 * PA0 下拉输出 超声波触发口 ********************************************************************************************************* */ /********************************************************* 改进: 1.加入数字输入滤波IC2F = 0010 *********************************************************/ /*$PAGE*/ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #include "ultrasound.h" #include "led.h" #include "usart.h" #include "sys.h" #include "delay.h" /* Includes ------------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Global varibles ------------------------------------------------------------*/ /* ** 捕获状态 ** [7]:0,没有成功的捕获;1,成功捕获到一次. ** [6]:0,还没捕获到高电平;1,已经捕获到高电平了. ** [5:0]:捕获高电平后溢出的次数 */ u8 TIM5CH2_CAPTURE_STA = 0; /* 输入捕获状态 */ u32 TIM5CH2_CAPTURE_VAL = 0; /* 输入捕获值 */ double high = 0.0; /* USED Outside varibles Declare----------------------------------------------*/ /*------------------------------------------------------------------------------*/ /* ********************************************************************************************************* * 初始化定时器1 * * 描述: 此函数初始化STM32定时器1 * Tout = ((arr+1) * (psc+1))/ Tclk * 参数: arr 自动重装值。 * psc 时钟预分频数 * 返回值:无 ********************************************************************************************************* */ void TIM1_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* TIM1时钟使能 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); TIM_DeInit(TIM1);// /* ** 自动重装载值,计数器计数到这个值就会触发溢出中断 */ TIM_TimeBaseInitStructure.TIM_Period = arr; TIM_TimeBaseInitStructure.TIM_Prescaler = psc; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //不分频 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);//初始化TIM1 TIM_ARRPreloadConfig(TIM1,ENABLE);//ARR自动装载默认是打开的,可以不设置 /* 允许触发中断 */ TIM_ClearITPendingBit(TIM1, TIM_IT_Update); TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // //初始化NVIC寄存器 NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM1,ENABLE); } /* ********************************************************************************************************* * 定时器1中断服务程序 * * 描述: 此函数提供定时器3的中断服务程序 * 参数: 无 * 返回值:无 ********************************************************************************************************* */ void TIM1_UP_TIM10_IRQHandler(void) { if(TIM_GetITStatus(TIM1, TIM_IT_Update) == SET) /* 溢出中断 */ { /* 中断处理程序 */ PAout(4) = 1; /* 脉冲触发 */ delay_us(200); /* 手册中需要至少给10us的高电平脉冲 */ PAout(4) = 0; //printf("Hello Ketty!!rn"); } TIM_ClearITPendingBit(TIM1, TIM_IT_Update); //清除中断标志位 } //定时器5通道1输入捕获配置 //arr:自动重装值(TIM2,TIM5是32位的!!) //psc:时钟预分频数 void TIM5_Cap_Init(u16 arr,u16 psc) { TIM_ICInitTypeDef TIM5_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); //TIM5时钟使能 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIOA0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA0 GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //PA0复用位定时器5 TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure); //初始化TIM5输入捕获参数 TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 选择输入端 IC1映射到TI1上 TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获 TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频 TIM5_ICInitStructure.TIM_ICFilter = 0x03;//IC1F=0000 配置输入滤波器 不滤波 TIM_ICInit(TIM5, &TIM5_ICInitStructure); TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断 NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =2; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 TIM_Cmd(TIM5,ENABLE ); //使能定时器5 } //捕获状态 //[7]:0,没有成功的捕获;1,成功捕获到一次. //[6]:0,还没捕获到低电平;1,已经捕获到低电平了. //[5:0]:捕获低电平后溢出的次数(对于32位定时器来说,1us计数器加1,溢出时间:4294秒) //定时器5中断服务程序 u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态 u32 TIM5CH1_CAPTURE_VAL; //输入捕获值(TIM2/TIM5是32位) void TIM5_IRQHandler(void) { LED0= ~LED0 ; if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获 { if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)//溢出 { if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了 { if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了 { TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次 TIM5CH1_CAPTURE_VAL=0XFFFFFFFF; }else TIM5CH1_CAPTURE_STA++; } } if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//捕获1发生捕获事件 { if(TIM5CH1_CAPTURE_STA&0X40) //捕获到一个下降沿 { TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽 TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);//获取当前的捕获值. high = TIM5CH1_CAPTURE_STA & 0X3F; //[5:0]:捕获高电平后溢出的次数 high *= 0XFFFFFFFF; /* 溢出时间总和 */ high += TIM5CH1_CAPTURE_VAL; /* 得到总的高电平时间 */ high = high * 170 / 1000000; printf("%lf rn",high); /* 打印总的高点平时间 */ TIM5CH1_CAPTURE_STA = 0; TIM5CH1_CAPTURE_VAL = 0; TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获 }else //还未开始,第一次捕获上升沿 { TIM5CH1_CAPTURE_STA=0; //清空 TIM5CH1_CAPTURE_VAL=0; TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿 TIM_Cmd(TIM5,ENABLE ); //使能定时器5 TIM_SetCounter(TIM5,0); TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获 TIM_Cmd(TIM5,ENABLE ); //使能定时器5 } } } TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位 TIM5->SR = 0; } /* ********************************************************************************************************* * 超声波初始化 * * 描述: 此函数初始化超声波相关的IO口 * 参数: 无 * 返回值:无 ********************************************************************************************************* */ void ultrasound_init(void) { GPIO_InitTypeDef GPIO_InitStructure; //因为系统初始化 SystemInit 函数里面已经初始化 APB1 的时钟为 4 分频,所 //以 APB1 的时钟为 42M, Ft = 84MHZ //根据时钟配置,系统时钟为168MHz,APB2时钟为84MHz。TIM1挂接在APB2上,所以APB2 时钟为84MHz TIM5_Cap_Init(0XFFFF,83); /* 1MHz频率计数 */ TIM1_Init(1999,16799); /*更新频率:考虑余量声速300 , 最高飞行高度: 2m,传输完一次需要0.02s,故配置50hz的更新频率 */ //超声波触发脚 PA0 (检测管脚PA1已在定时器初始化时完成初始化) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTA时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //GPIOA0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出?? GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA1 PAout(4) = 0; TIM5CH2_CAPTURE_STA = 0; /* 输入捕获状态 */ TIM5CH2_CAPTURE_VAL = 0; } /*$PAGE*/ /* ********************************************************************************************************* * 处理超声波测得的距离 * * 描述: 此函数处理超声波测得的距离 * 参数: 无 * 返回值:无 ********************************************************************************************************* */ void deal_high(void) { }
|
|
相关推荐
|
|
不错不错,mark了
|
|
|
|
|
|
1.建议使用示波器观察管脚波形,触发管脚和返回的管脚 2.不建议使用这种方法读取超声波数据:原因:a.中断对系统的影响大,b.有更好的方式,比如串口模式的超声波,或者使用PWM输入捕获的方法;后面两种更可靠 |
|
|
|
|
|
990 浏览 2 评论
STM32CUBEMX(13)--SPI,W25Q128外部Flash移植
2013 浏览 0 评论
OV7670摄像头使用串口发送数据到另一个板子上的lcd,出现花屏
2025 浏览 1 评论
1373 浏览 0 评论
801 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-10-20 16:46 , Processed in 0.805192 second(s), Total 81, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号