欢迎大家来到IT世界,在知识的湖畔探索吧!
欢迎大家来到IT世界,在知识的湖畔探索吧!
来源:百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版)
作者:韦东山
本文字数:1353,阅读时长:3分钟
在后续我们对讲解多个传感器,这几个传感器对时序的要求都比较高,比如温湿度传感器DH11,查看芯片手册时序,至少就需要微秒级的延时函数。
延时函数的方式一般有两种:
- ①:使用for循环,利用示波器等工具测得精确值;
- ②:使用定时器,通过不断检测定时器的计数值获得精确时间;
使用for循环的方式,可能会因为硬件的差异,导致延时函数不准,因此这里我们使用定时器的方式。
打开之前的timers.c文件,修改timer_init函数的配置。
PCLK仍然等于,将prescaler value改为4,divider value设置为2,
这样,每减1, 对应0.2us;每减5, 对应1us;从50000减到0,对应10ms。
修改对应的寄存器:
TCFG0 = 4; /* Prescaler 0 = 4, 用于timer0,1 */ TCFG1 &= ~0xf; /* MUX0 : 1/2 */ /* 设置TIMER0的初值 */ TCNTB0 = 50000; /* 10Ms中断一次 */
欢迎大家来到IT世界,在知识的湖畔探索吧!
我们先写一个us延时的函数,然后ms延时就调用us即可。
因此,us延时函数里,尽量少调用函数。
假如现在要延时nus,我们先将n*5,得到nus对应的“计数时钟数”。
然后如果传入“计数时钟周期”如果大于0,则一直计算过去了多少个“计数时钟数”,与传入的“计数时钟数”相减,直到为零,退出循环,也就实现了延时nus。
怎样计算过去了多少个“计算周期”呢?
自然是当前的值,减去一开始进入函数的值。
但还有一种情况是定时器里的计数记到0时,会自动变成5000,计数计数,这时候,计算方式就变成了pre+(5000-cur):
欢迎大家来到IT世界,在知识的湖畔探索吧!/* 尽量少调用函数 */ void udelay(int n) { int cnt = n * 5; /* u us 对应n*5个计数值 */ int pre = TCNTO0; int cur; int delta; while (cnt > 0) { cur = TCNTO0; if (cur <= pre) delta = pre - cur; else delta = pre + (50000 - cur); cnt = cnt - delta; pre = cur; } }然后是ms延时函数:
void mdelay(int m) { udelay(m*1000); }
我们可以写一个测试函数,简单的测试下是否可用,测试函数隔1分钟进行打印一下。
如果us不准的话,放大至s,会有比较大的偏差,这样可以进行粗略的检测,精确检测可以使用示波器等工具。
欢迎大家来到IT世界,在知识的湖畔探索吧!void hrtimer_test(void) { int cnt = 0; while (1) { printf("delay one min: "); mdelay(60000); /* 延时1分钟 */ printf("%d\n\r", ++cnt); } }
前面延时里的计算还是比较耗费时间的,因此,我们尽量提高CPU的运行时钟,并且 将尽可能的启动icache、dcache和mmu。
此外,如果延时过程中,发生了中断,如果中断比较耗时的话,就会导致延时可能出现不准确,所以,我们可以延时之前关中断, 延时之后开中断;
课后作业:
- a. 禁止icache, 禁止mmu, 修改lds, 测试延时函数是否还准确;
- b. 测试延时之前关中断, 延时之后开中断;
「新品首发」STM32MP157开发板火爆预售!首批仅300套
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/94969.html