OpenEdv-开源电子网

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

delay_ms()函数不准的问题,求解

[复制链接]

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1666
金钱
1666
注册时间
2016-4-29
在线时间
266 小时
发表于 2016-7-10 00:18:39 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 d1z1y2 于 2016-7-14 23:07 编辑

跑马灯,LED0能闪,但是闪的速度明显偏慢,可能是哪方面的问题?


问题解决了,答案在15楼
QQ截图20160709230922.jpg

最佳答案

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

不仔细看,可能还是看不出来是哪里有问题。。。。原来是贴片晶振的封装画错了,应该是图中1、2脚位是GND,3、4脚位是晶振引脚,现在想起来,可能是不知道什么时候改封装的时候,把封装改错了。真是后悔,更郁闷的是,我还把公司打样的10片板子画错了,唉。。。现在赶紧去买直插的晶振来试试,不知道能不能行。。。。。这就是不严谨的后果。。。。,
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1666
金钱
1666
注册时间
2016-4-29
在线时间
266 小时
 楼主| 发表于 2016-7-10 00:18:40 | 显示全部楼层
不仔细看,可能还是看不出来是哪里有问题。。。。原来是贴片晶振的封装画错了,应该是图中1、2脚位是GND,3、4脚位是晶振引脚,现在想起来,可能是不知道什么时候改封装的时候,把封装改错了。真是后悔,更郁闷的是,我还把公司打样的10片板子画错了,唉。。。现在赶紧去买直插的晶振来试试,不知道能不能行。。。。。这就是不严谨的后果。。。。,
回复

使用道具 举报

7

主题

185

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2729
金钱
2729
注册时间
2015-12-27
在线时间
469 小时
发表于 2016-7-10 09:01:53 | 显示全部楼层
ms延时的参数是u16类型的。函数原型为:void delay_ms(u16 nms);
回复

使用道具 举报

3

主题

548

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1383
金钱
1383
注册时间
2015-2-3
在线时间
197 小时
发表于 2016-7-10 09:14:20 | 显示全部楼层
原子的早期版本delay_ms()函数有一个最大延时时间(因为systick是24位定时器),大概是几百ms。超出则需要多次调用。
回复

使用道具 举报

13

主题

186

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
441
金钱
441
注册时间
2016-6-30
在线时间
97 小时
发表于 2016-7-10 10:15:30 | 显示全部楼层
用滴答定时器吧!这个肯定不准
回复

使用道具 举报

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1666
金钱
1666
注册时间
2016-4-29
在线时间
266 小时
 楼主| 发表于 2016-7-10 20:42:30 | 显示全部楼层
yyx112358 发表于 2016-7-10 09:14
原子的早期版本delay_ms()函数有一个最大延时时间(因为systick是24位定时器),大概是几百ms。超出则需要 ...

delay_ms(1000),没有超过规定值啊
回复

使用道具 举报

14

主题

96

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
412
金钱
412
注册时间
2013-6-23
在线时间
59 小时
发表于 2016-7-10 22:16:28 | 显示全部楼层
这个速度明显偏慢的问题太常见了,是外部晶振的问题,外部晶振没有起振,MCU就使用HSI,而HSI频率低,所以速度明显偏慢
回复

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1835
金钱
1835
注册时间
2014-6-27
在线时间
981 小时
发表于 2016-7-11 08:56:28 | 显示全部楼层
有2个函数你可以试试,时间测试过是很准的,如果要延时时间准的,用定时器是必要的,刚好有滴答定时器,就用那厮了,打开滴答定时器就行,不用老是开关定时器。
void delay_us(u32 x)//这里可以延时大概4294/Fck秒
{
        u32 new_load,old_load,cmp_load=0,tickers;
        tickers=x*Fclk;//Fclk为滴答定时器跑的频率,比如1M,x*1,或者8M,x*8。
        old_load=SysTick->VAL;
        while(1)
        {
            new_load=SysTick->VAL;
            if(new_load!=old_load)
            {        
                if(new_load<old_load)
                    cmp_load+=old_load-new_load;
                else
                    cmp_load+=SysTick->LOAD+old_load-new_load;        
                old_load=new_load;
                if(cmp_load>=tickers)break;
            }  
        }
}

void delay_ms(u16 x)//可以延时65535秒
{
   while(x--)delay_us(1000);
}
回复

使用道具 举报

30

主题

1170

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1993
金钱
1993
注册时间
2016-2-16
在线时间
527 小时
发表于 2016-7-11 12:07:26 | 显示全部楼层
你硬件调试看看,看RCC_CFGR寄存器,看看是不是使用的外部晶振,可能是外部晶振出问题,自动切换到HSI引起的
回复

使用道具 举报

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1666
金钱
1666
注册时间
2016-4-29
在线时间
266 小时
 楼主| 发表于 2016-7-12 00:34:48 | 显示全部楼层
憨厚诚实大叔 发表于 2016-7-11 12:07
你硬件调试看看,看RCC_CFGR寄存器,看看是不是使用的外部晶振,可能是外部晶振出问题,自动切换到HSI引起 ...

if(RCC->CFGR & 0x00000008) LED0 = 0;//时钟
if(RCC->CFGR & 0x00000004) LED1 = 0;//时钟

00:HSI作为系统时钟
01:HSE
10LL

LED0、LED1都不亮,是否表明用的是内部时钟?
回复

使用道具 举报

30

主题

1170

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1993
金钱
1993
注册时间
2016-2-16
在线时间
527 小时
发表于 2016-7-12 09:25:16 | 显示全部楼层
本帖最后由 憨厚诚实大叔 于 2016-7-12 09:38 编辑

你用的不是keil么,keil可以直接看各种寄存器,而没必要这样读数
回复

使用道具 举报

30

主题

1170

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1993
金钱
1993
注册时间
2016-2-16
在线时间
527 小时
发表于 2016-7-12 09:28:15 | 显示全部楼层
虽然你这样弄如果程序没错,的确是用的HSI时钟,不过你还是直接看看寄存器看看吧,百度就有了,keil如何直接看寄存器数据
回复

使用道具 举报

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2016-7-12 13:48:59 | 显示全部楼层
我教你 最科学的办法,如果有示波器的话。

任意IO口 设置为输出    假如  PB1=0; delay_ms(1000); PB1=1;delay_ms(1000);

看波形的周期就知道了。  非常准。
自己选择的路,成家前走完。
回复

使用道具 举报

3

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
95
金钱
95
注册时间
2016-7-9
在线时间
15 小时
发表于 2016-7-12 14:07:26 | 显示全部楼层
aiyeba 发表于 2016-7-12 13:48
我教你 最科学的办法,如果有示波器的话。

任意IO口 设置为输出    假如  PB1=0; delay_ms(1000); PB1= ...

示波器怎么接?
回复

使用道具 举报

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2016-7-12 15:36:32 | 显示全部楼层

   示波器红色线是输入  黑色是地    红色线接IO就可以了,黑色线接单片机上的一个地就可以了。  然后查看波形
自己选择的路,成家前走完。
回复

使用道具 举报

24

主题

695

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1666
金钱
1666
注册时间
2016-4-29
在线时间
266 小时
 楼主| 发表于 2016-7-14 22:48:51 | 显示全部楼层
本帖最后由 d1z1y2 于 2016-7-14 23:00 编辑

给这个贴子结贴,延时不准的原因找到了,虽然没验证,但是可以确定是外部时钟没启振。现在把整个过程写出来,给大家一个参考。先是找问题的原因,怀疑外部时钟没启振,于是读RCC->CFGR,确实没启振。然后又自定义时钟配置函数
void RCC_Configuration(void)
{
    ErrorStatus HSEStartUpStatus;//定义枚举型变量 HSEStartUpStatus
       
        RCC_DeInit();                //重置系统时钟设置
    RCC_HSEConfig(RCC_HSE_ON);   //打开外部晶振 HSE     
        HSEStartUpStatus = RCC_WaitForHSEStartUp();        //等待外部晶振稳定
    //判断HSE是否起振成功
        if(HSEStartUpStatus == SUCCESS)   
    {
        RCC_HCLKConfig(RCC_SYSCLK_Div1);    //选择 HCLK(AHB)   时钟源 //HCLK = SYSCLK
        RCC_PCLK2Config(RCC_HCLK_Div1);     //选择 PCLK2(APB2) 时钟源 //PCLK2 = HCLK(AHB)/1
        RCC_PCLK1Config(RCC_HCLK_Div2);     //选择 PCLK2(APB1) 时钟源 //PCLK1 = HCLK(AHB)/2
        //FLASH_SetLatency(FLASH_Latency2);   //设置 FLASH 延时周期为2
                //FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能 FLASH 预取缓存
                        
              //注:AHB主要负责外部存储器时钟。
              //APB2负责AD,I/O,高级TIM,串口1。
              //APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM。

        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);//PLLCLK = 8MHz * 9 = 72MHz
        RCC_PLLCmd(ENABLE);                                 //使能PLL
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL输出稳定

        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);          //选择 SYSCLK 时钟源为 PLL
        while(RCC_GetSYSCLKSource() != 0x08);               //等待 PLL 成为 SYSCLK 时钟源
               
                f = 0;
        }
        else  //外部晶振起动失败
        {
                f = 1;
        }

}


变量 f 是等于1的,说明外部晶振启动失败。
但是,找了好久原因,也不知道为什么晶振不启振,换晶振,换电容,换成20P,又换成15P,都不行。后来回想起前几天碰到的CH340G电脑识别不出来的问题,当时也是换了晶振和电容,都不行,后来换了一个直插的12M电容就好了,当时以为是晶振不匹配,没有仔细想。
现在想起来怀疑是电路有问题,结果发现,如图:


QQ截图20160714215920.jpg
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-15 08:20

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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