完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
上次写完HAL_NVIC_SetPriorityGrouping(),设置分组为2,抢占优先级与响应优先级都是2
HAL_Init还剩下一个HAL_InitTick(TICK_INT_PRIORITY)函数就讲完了,其中,TICK_INT_PRIORITY为Systick时钟默认中断,为0x0F。 如上文抢占有限级和响应优先级都是2来说,那么Systick的中断优先级是最低的 只要任何出现中断优先级高的,就会打断Systick中断,这样怎么保障如何保障其定时准确呢? 首先看了正点原子的开发指南 他的意思是使用内部实现的,不占用外部中断 那么有一个问题了,内部外设和普通外设的中断优先级谁更高一些? 是根据设定的优先级顺序来决定还是根据内核优先原则? 其结论为 Systick虽然作为与CPU紧耦合的内核外设,但其中断优先级并不比普通外设要高,并不因为它是内核外设而特殊,它还是遵循中断优先级高低的规则来响应。 所以如果需要保障计时更准确一些,应该将Systick中断优先级提高,具体我先埋个坑-。- 然后进入函数 __weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) { /* Configure the SysTick to have interrupt in 1ms time basis*/ if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U) { return HAL_ERROR; } /* Configure the SysTick IRQ priority */ if (TickPriority < (1UL << __NVIC_PRIO_BITS)) { HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U); uwTickPrio = TickPriority; } else { return HAL_ERROR; } /* Return function status */ return HAL_OK; } 这一步很巧妙,通过if来判断括号中的1ms时间是否设置完成, 中心思路:系统时钟为16Mhz,然后记16/1000,那么就是1/1000s,也就是1ms 其具体实现如下: 首先第一个if判断语句,HAL_SYSTICK_Config(),该函数如下,首先判断ticks是否超过24位,如果没有的话,就送到SysTick->LOAD中。 STK_ LOAD 寄存器是重置值,当计数为0的时候充值为LOAD值,HAL库将其设置为16000 (0x00003E80) VAL寄存器是Systick时钟当前计数值,将其清零 CTRL是控制寄存器,其由以下组成 16 COUNTFLAG 计数标志位: 当倒计时到0时,输出1 CLKSOURSE时钟源选择 0: AHB/8 1:AHB TICKINT 1:当计数到0会发出计数信号 ENABLE 1:计数 0:关闭使能 默认的这三个都设置为1 __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ } 中间还有一个NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); 该函数设置SysTick_IRQn 优先级为0111,特别注意这个是函数内部设置优先级为0111, __STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) //0x0c 1100 { if ((int32_t)(IRQn) >= 0) { NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);//(1100 << 4 = 1100 0000) } else { SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } 设置好标准时间之后,再设置中断时钟的优先级,入口参数为SysTick_IRQn,0x0F,0 void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t prioritygroup = 0x00U; /* Check the parameters */ assert_param(IS_NVIC_SUB_PRIORITY(SubPriority)); assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority)); prioritygroup = NVIC_GetPriorityGrouping(); NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority)); } assert 函数就不说了,然后再获取当前分组,设置优先级,这个与上面不同的是,上面设置优先级的值是函数内部初始化,NVIC_EncodePriority 将中断分组名,宏定义的优先级与SubPriority 进行编码 __STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) { uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ uint32_t PreemptPriorityBits; uint32_t SubPriorityBits; PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); //get min of this SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); return ( ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) ); } C语法:(>)?A:B如果括号内成立则执行A,不成立执行B 这里两个赋值语句执行的都是B 还是贴一下F4的中断分组 PriorityGroupTmp :当前AIRCR二进制 PreemptPriorityBits :获取当前抢占优先级是几位 SubPriorityBits :获取当前响应优先级是几位 注意当计算减法的时候,都转为十进制进行计算。 最后返回的便是抢占优先级与相应优先级的具体位上的值 最后便进行优先级设置,设置好之后,再把当前优先级送到uwTickPrio中。便完成了HAL_ini |
|
|
|
只有小组成员才能发言,加入小组>>
3310 浏览 9 评论
2991 浏览 16 评论
3492 浏览 1 评论
9057 浏览 16 评论
4086 浏览 18 评论
1175浏览 3评论
603浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
596浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2333浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1894浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 14:09 , Processed in 1.020100 second(s), Total 47, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号