STM32库函数的学习5.2——滴答定时器

        以前都是随便用的延时函数都是c语言的延时函数或者TIM定时器,最近几年才用到正点原子的滴答定时器。

        Systick定时器,是一个简单的定时器, Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。 Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。 SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。 Systick中断的优先级也可以设置。这个是寄存器设置函数了。所以这个可以作为设备运行计时函数,目前暂时还没设计到。

        固件库中的Systick相关函数,库函数配置:

        SysTick_CLKSourceConfig()    //Systick时钟源选择

                                                          //位于misc.c函数199行

        SysTick_Config(uint32_t ticks) //初始化systick,时钟为HCLK,并开启中断                                 

                                                         //位于core_cm3.h的1694行       

        Systick中断服务函数:

        void SysTick_Handler(void);

        正点原子的delay延时函数:

       static u8  fac_us=0;                            //us延时倍乘数               
       static u16 fac_ms=0;                            //ms延时倍乘数

        //初始化延迟函数
        //SYSTICK的时钟固定为HCLK时钟的1/8
        //SYSCLK:系统时钟
        void delay_init()
        {
            SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);    //选择外部时钟  HCLK/8
            fac_us=SystemCoreClock/8000000;                //为系统时钟的1/8  
            fac_ms=(u16)fac_us*1000;                    //代表每个ms需要的systick时钟数   
        }

        //延时nus
        //nus为要延时的us数.                                               
        void delay_us(u32 nus)
        {        
            u32 temp;             
            SysTick->LOAD=nus*fac_us;                     //时间加载               
            SysTick->VAL=0x00;                            //清空计数器
            SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;    //开始倒数      
            do
            {
                temp=SysTick->CTRL;
            }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
            SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;    //关闭计数器
            SysTick->VAL =0X00;                           //清空计数器     
        }
        //延时nms
        //注意nms的范围
        //SysTick->LOAD为24位寄存器,所以,最大延时为:
        //nms<=0xffffff*8*1000/SYSCLK
        //SYSCLK单位为Hz,nms单位为ms
        //对72M条件下,nms<=1864 ,
        void delay_ms(u16 nms)
        {                     
            u32 temp;           
            SysTick->LOAD=(u32)nms*fac_ms;                //时间加载(SysTick->LOAD为24bit)
            SysTick->VAL =0x00;                            //清空计数器
            SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;    //开始倒数  
            do
            {
                temp=SysTick->CTRL;
            }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
            SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;    //关闭计数器
            SysTick->VAL =0X00;                           //清空计数器              
        }

        这里正点原子的最大延时是1864毫秒。然后下放的函数则是我设计冰浴机所使用的超过1864毫秒以后得延时函数,毕竟我当时设计还没用上计时器,所以延时都能到1分钟以上。而且延时会耗费单片机系统资源,所以正点原子估计是不建议设置延时函数太大。

        void delay_s(u16 ns)
        {
            u16 ms;
        for(ms=0;ms<ns;ms++)
            {
                delay_ms(1000);//这里是1250才满足1s,1000不够1s;

                                          //  这里我设计时候进行了秒表计时测试出来的, 不过看了正点原子的前几讲视频,我发现我keil里面的晶振选择是12m,但是实际板子使用的是8M的,所以我觉得有可能是这个造成的,因为我离职了,那个项目我就测试不了,所以我这里就直接改成了1000,不过等之后做学习时候,可以再顺便测试一下。

                                        //正点原子的视频说了,如果使用中发现延时不一致,问题一般都是因为不同内核时钟不一样而已。修改ticks值即可。           
            }

        }

        这里用到了do while函数,以前很少用到呢,毕竟我c语言学的也一般。这里就查询了一下,while、do while、break、continue相关的应用。

        while 与 if的区别:while循环是若表达式满足条件可循环重复执行语句,if则是执行一次语句。

        break、continue 是不仅能用于循环中,也能用于选择分支语句中(switch case语句 ,if 嵌套,多分支语句),以前只是知道能用在while、switch case里面,if嵌套跟还真没用过之后可以试试。

        在 do while 循环中先执⾏代码,执⾏完代码以后,再去执⾏“判断表达式”,判断表达式的结果是!=0,则继续循环,执⾏循环语句;判断表达式的结果==0,则循环结束。所以在 do while 语句中循环体是⾄少执⾏⼀次的,这是 do while 循环⽐较特殊的地⽅。这个感觉还是if比较好,毕竟if是先执行判断,再去运行代码,速度快很多,我运行时候多数是选择的if,而不是选择的do while,毕竟if判断以后不会运行后面代码,do while却需要运行再判断,优劣很明显。

       break 的作⽤是⽤于永久的终⽌循环,只要 break 被执⾏,直接就会跳出循环,继续往后执⾏。continue 的作⽤是跳过本次循环 continue 后边的代码,在 for 循环和 while 循环中有所差异的。在while循环中 continue 可以帮助我们跳过某⼀次循环 continue 后边的代码,直接到循环的判断部分,进⾏下⼀次循环的判断,如果循环的调整是在 continue 后边的话,可能会造成死循环。而在for循环中 continue 的作⽤是跳过本次循环中 continue 后的代码,直接去到循环的调整部分。未来当某个条件发⽣的时候,本次循环⽆需再执⾏后续某些操作的时候,就可以使⽤continue 来实现。

        补:延时函数基本上学到这里,之后有计划要研究sim卡跟语音通话。

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

esmember

感谢大家喜欢我遇到的问题分享。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值