STM32
直播中

张杰

8年用户 1360经验值
私信 关注
[问答]

Systick寄存器理解操作

最近看原子的开发板例程时遇到几个问题,

void delay_us(u32 nus)
{
u32 temp;      
Systick->LOAD=nus*fac_us; //时间加载     
SysTick->VAL=0x00;        //清空计数器
SysTick->CTRL=0x01 ;      //开始倒数   
do
{
temp=SysTick->CTRL;(问题1:从上面红线框的理解,这里对CTRL读不是会把CTRL的第16位给清零掉吗,这样后面do-while循环判断条件!(temp&(1<<16))为真永远都挑不出循环了,怎么理解呢?)                                                                                   
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   (问题2:上面已经使能了CTRL的第0位那么temp&0x01是不是一直为1即为真而这一条件是多余的?直接判断条件可以改为while(!(temp&(1<<16)));?)

SysTick->CTRL=0x00;       //关闭计数器
SysTick->VAL =0X00;       //清空计数器

回帖(3)

黄远飞

2019-5-14 09:13:57
问题1,应该第16位是读取之后,硬件自动再清零,并不是读取的瞬间!所以读取到的temp的第16位为1,那么!(temp&(1<<16))为0.
问题2,可能是怕初始化时没有使能,而后面的!(temp&(1<<16))为真,跳不出while.
举报

潘璐

2019-5-14 09:22:49
谢谢  金色的梦想  的解答.
问题1:金色的回答已经很准确了.但楼主存在理解上的错误.这里读取CTRL的16位用于判断是否完成计数.注意这个第16位,是在计数时间到,才被硬件置1的,所以在没到达之前,一直是0.所以在完成之前,无论你读多少次都没关系了.
当计数时间到之后,该位被硬件置1,则肯定可以被读到一次(也只能被读一次).在读到该位为1之后,!(temp&1<<16)就为0了.从而退出do while循环.
所以,不存在你说的死循环.
问题2:这一步其实是防止CTRL的0位被意外的关闭,从而导致的死循环无法退出的问题.你去掉也是可以的.只要能保证CTRL没有被其他程序意外修改就可以.
举报

蔡表胤

2019-5-14 09:40:04
非常感谢楼上二位的细心解答,已经弄明白了。
对问题1:循环体内对temp赋值即是对CTRL的读,读后CTRL的第16位自动被清零,此清零在重新赋值前对temp的第16位无影响。
对问题2:拜读了原子的博客更清楚了
举报

更多回帖

发帖
×
20
完善资料,
赚取积分