当前位置: 首页 > news >正文

摄影工作室网站模板vip解析网站怎么做

摄影工作室网站模板,vip解析网站怎么做,WordPress 要求,网页设计基础考试题目延时函数是很常用的 API 函数#xff0c;在前面的实验中我们使用循环来实现延时函数#xff0c;但是使用循环来实现的延时函数不准确#xff0c;误差会很大。虽然使用到延时函数的地方精度要求都不会很严格( 要求严格的话就使用硬件定时器了 ) #xff0c;但是延时函数肯定…         延时函数是很常用的 API 函数在前面的实验中我们使用循环来实现延时函数但是使用循环来实现的延时函数不准确误差会很大。虽然使用到延时函数的地方精度要求都不会很严格( 要求严格的话就使用硬件定时器了 ) 但是延时函数肯定是越精确越好这样延时函数就可以使用在某些对时序要求严格的场合。本章我们就来学习一下如何使用硬件定时器来实现高精度延时。 1、 高精度延时简介 1.1 GPT 定时器简介 学过 STM32 的同学应该知道在使用 STM32 的时候可以使用 SYSTICK 来实现高精度延时。I.MX6U 没有 SYSTICK 定时器但是 I.MX6U 有其他定时器啊比如第十五章讲解的 EPIT定时器。本章我们使用 I.MX6U 的 GPT 定时器来实现高精度延时顺便学习一下 GPT 定时器 GPT 定时器全称为 General Purpose Timer 。 GPT 定时器是一个 32 位向上定时器 ( 也就是从 0X00000000 开始向上递增计数 ) GPT 定时器也可以跟一个值进行比较当计数器值和这个值相等的话就发生比较事件产生比较中断。GPT 定时器有一个 12 位的分频器可以对 GPT 定时器的时钟源进行分频 GPT 定时器特性如下 ①、一个可选时钟源的 32 位向上计数器。 ②、两个输入捕获通道可以设置触发方式。 ③、三个输出比较通道可以设置输出模式。 ④、可以生成捕获中断、比较中断和溢出中断。 ⑤、计数器可以运行在重新启动(restart)或(自由运行)free-run 模式。 GPT 定时器的可选时钟源如图 20.1.1.1 所示 从图 20.1.1.1 可以看出一共有五个时钟源分别为 ipg_clk_24M 、 GPT_CLK( 外部时钟 ) 、ipg_clk、 ipg_clk_32k 和 ipg_clk_highfreq 。本例程选择 ipg_clk 为 GPT 的时钟源 ipg_clk66MHz 。 GPT 定时器结构如图 20.1.1.2 所示 图 20.1.1.2 中各部分意义如下 ①、此部分为 GPT 定时器的时钟源前面已经说过了本章例程选择 ipg_clk 作为 GPT 定时器时钟源。 ②、此部分为 12 位分频器对时钟源进行分频处理可设置 0~4095分别对应 1~4096 分频。 ③、经过分频的时钟源进入到 GPT 定时器内部 32 位计数器。 ④和⑤、这两部分是 GPT 的两路输入捕获通道本章不讲解 GPT 定时器的输入捕获。 ⑥、此部分为输出比较寄存器一共有三路输出比较因此有三个输出比较寄存器输出比较寄存器是 32 位的。 ⑦、此部分位输出比较中断三路输出比较中断当计数器里面的值和输出比较寄存器里面的比较值相等就会触发输出比较中断。 GPT 定时器有两种工作模式重新启动 (restart) 模式和自由运行 (free-run) 模式这两个工作模式的区别如下 重新启动(restart) 模式 当 GPTx_CR(x1 2) 寄存器的 FRR 位清零的时候 GPT 工作在此 模式。在此模式下当计数值和比较寄存器中的值相等的话计数值就会清零然后重新从 0X00000000 开始向上计数只有比较通道 1 才有此模式向比较通道 1 的比较寄存器写入任何 数据都会复位 GPT 计数器。对于其他两路比较通道通道 2 和 3 当发生比较事件以后不会复位计数器。 自由运行(free-run) 模式 当 GPTx_CR(x1 2) 寄存器的 FRR 位置 1 时候 GPT 工作在此模 式下此模式适用于所有三个比较通道当比较事件发生以后并不会复位计数器而是继续计 数直到计数值为 0XFFFFFFFF 然后重新回滚到 0X00000000 。         接下来看一下 GPT 定时器几个重要的寄存器第一个就是 GPT 的配置寄存器 GPTx_CR 此寄存器的结构如图 20.1.1.3 所示 寄存器 GPTx_CR 我们用到的重要位如下         SWR(bit15)复位 GPT 定时器向此位写 1 就可以复位 GPT 定时器当 GPT 复位完成以后此为会自动清零。         FRR(bit9) 运行模式选择当此位为 0 的时候比较通道 1 工作在重新启动 (restart) 模式。当此位为 1 的时候所有的三个比较通道均工作在自由运行模式 (free-run) 。         CLKSRC(bit8:6) GPT 定时器时钟源选择位为 0 的时候关闭时钟源为 1 的时候选择ipg_clk 作为时钟源为 2 的时候选择 ipg_clk_highfreq 为时钟源为 3 的时候选择外部时钟为时钟源为 4 的时候选择 ipg_clk_32k 为时钟源为 5 的时候选择 ip_clk_24M 为时钟源。本章例程选择 ipg_clk 作为 GPT 定时器的时钟源因此此位设置位 1(0b001) 。         ENMOD(bit1) GPT 使能模式此位为 0 的时候如果关闭 GPT 定时器计数器寄存器保存定时器关闭时候的计数值。此位为 1 的时候如果关闭 GPT 定时器计数器寄存器就会清零。         EN(bit) GPT 使能位为 1 的时候使能 GPT 定时器为 0 的时候关闭 GPT 定时器。 接下来看一下 GPT 定时器的分频寄存器 GPTx_PR 此寄存器结构如图 20.1.1.4 所示 寄存器 GPTx_PR 我们用到的重要位就一个 PRESCALER(bit11:0) 这就是 12 位分频值可设置 0~4095 分别对应 1~4096 分频。 接下来看一下 GPT 定时器的状态寄存器 GPTx_SR 此寄存器结构如图 20.1.1.5 所示 寄存器 GPTx_SR 重要的位如下 ROV(bit5) 回滚标志位当计数值从 0XFFFFFFFF 回滚到 0X00000000 的时候此位置 1 。 IF2~IF1(bit4:3) 输入捕获标志位当输入捕获事件发生以后此位置 1 一共有两路输入捕 获通道。如果使用输入捕获中断的话需要在中断处理函数中清除此位。 OF3~OF1(bit2:0)输出比较中断标志位当输出比较事件发生以后此位置 1 一共有三路 输出比较通道。如果使用输出比较中断的话需要在中断处理函数中清除此位。接着看一下 GPT 定时器的计数寄存器 GPTx_CNT 这个寄存器保存着 GPT 定时器的当前计数值。最后看一下 GPT 定时器的输出比较寄存器 GPTx_OCR 每个输出比较通道对应一个输出比较寄存器因此一个 GPT 定时器有三个 OCR 寄存器它们的作都是相同的。以输出比较通道 1 为例其输出比较寄存器为 GPTx_OCR1 这是一个 32 位寄存器用于存放 32 位的比较值。当计数器值和寄存器 GPTx_OCR1 中的值相等就会产生比较事件如果使能了比较中断的话就会触发相应的中断。 关于 GPT 的寄存器就介绍到这里关于这些寄存器详细的描述请参考《 I.MX6ULL 参考手册》第 1432 页的 30.6 小节。 1.2 定时器实现高精度延时原理 高精度延时函数的实现肯定是要借助硬件定时器前面说了本章实验使用 GPT 定时器来实现高精度延时。如果设置 GPT 定时器的时钟源为 ipg_clk66MHz 设置 66 分频那么进入 GPT定时器的最终时钟频率就是 66/661MHz 周期为 1us 。 GPT 的计数器每计一个数就表示“过去”了 1us 。如果计 10 个数就表示“过去”了 10us 。通过读取寄存器 GPTx_CNT 中的值就知道计了个数比如现在要延时100us 那么进入延时函数以后纪录下寄存器 GPTx_CNT 中的值为 200 当 GPTx_CNT 中的值为 300 的时候就表示 100us 过去了也就是延时结束。 GPTx_CNT 是个 32 位寄存器如果时钟为 1MHz 的话 GPTx_CNT 最多可以实现 0XFFFFFFFFus4294967295us ≈4294s ≈ 72min 。也就是说 72 分钟以后 GPTx_CNT 寄存器就会回滚到 0X00000000 也就是溢 出所以需要在延时函数中要处理溢出的情况。关于定时器实现高精度延时的原理就讲解到这 里原理还是很简单的高精度延时的实现步骤如下 1、设置 GPT1 定时器 首先设置 GPT1_CR 寄存器的 SWR(bit15) 位来复位寄存器 GPT1 。复位完成以后设置寄存器 GPT1_CR 寄存器的 CLKSRC(bit8:6) 位选择 GPT1 的时钟源为 ipg_clk 。设置定时器 GPT1 的工作模式 2、设置 GPT1 的分频值 设置寄存器 GPT1_PR 寄存器的 PRESCALAR(bit111:0) 位设置分频值。 3、设置 GPT1 的比较值 如果要使用 GPT1 的输出比较中断那么 GPT1 的输出比较寄存器 GPT1_OCR1 的值可以 根据所需的中断时间来设置。本章例程不使用比较输出中断所以将 GPT1_OCR1 设置为最大 值即0XFFFFFFFF 。         4、使能 GPT1 定时器         设置好 GPT1 定时器以后就可以使能了设置 GPT1_CR 的 EN(bit0) 位为 1 来使能 GPT1 定 时器。         5、编写延时函数         GPT1定时器已经开始运行了可以根据前面介绍的高精度延时函数原理来编写延时函数 针对 us 和 ms 延时分别编写两个延时函数。 2、 硬件原理分析 本试验用到的资源如下 ①、一个 LED 灯 LED0 。 ②、定时器 GPT1 。 本实验通过高精度延时函数来控制 LED0 的闪烁可以通过示波器来观察 LED0 的控制 IO 输出波形通过波形的频率或者周期来判断延时函数精度是否正常。 3、 实验程序编写 本章实验在上一章例程的基础上完成更改工程名字为“ delay ”直接修改 bsp_delay.c 和 bsp_delay.h 这两个文件将 bsp_delay.h 文件改为如下所示内容 #ifndef __BSP_DELAY_H #define __BSP_DELAY_H #include imx6ul.h/* 函数声明 */ void delay_init(void); void delayus(unsigned int usdelay); void delayms(unsigned int msdelay); void delay(volatile unsigned int n); void gpt1_irqhandler(void);#endif bsp_delay.h 文件就是一些函数声明很简单。在文件 bsp_delay.c 中输入如下内容 #include bsp_delay.h/** description : 延时有关硬件初始化,主要是GPT定时器GPT定时器时钟源选择ipg_clk66Mhz* param : 无* return : 无*/ void delay_init(void) {GPT1-CR 0; /* 清零bit0也为0即停止GPT */GPT1-CR 1 15; /* bit15置1进入软复位 */while((GPT1-CR 15) 0x01); /*等待复位完成 *//** GPT的CR寄存器,GPT通用设置* bit22:20 000 输出比较1的输出功能关闭也就是对应的引脚没反应* bit9: 0 Restart模式,当CNT等于OCR1的时候就产生中断* bit8:6 001 GPT时钟源选择ipg_clk66Mhz* bit*/GPT1-CR (16);/** GPT的PR寄存器GPT的分频设置* bit11:0 设置分频值设置为0表示1分频* 以此类推最大可以设置为0XFFF也就是最大4096分频*/GPT1-PR 65; /* 设置为65即66分频因此GPT1时钟为66M/(651)1MHz *//** GPT的OCR1寄存器GPT的输出比较1比较计数值* GPT的时钟为1Mz那么计数器每计一个值就是就是1us。* 为了实现较大的计数我们将比较值设置为最大的0XFFFFFFFF,* 这样一次计满就是0XFFFFFFFFus 4294967296us 4295s 71.5min* 也就是说一次计满最多71.5分钟存在溢出*/GPT1-OCR[0] 0XFFFFFFFF;GPT1-CR | 10; //使能GPT1/* 一下屏蔽的代码是GPT定时器中断代码* 如果想学习GPT定时器的话可以参考一下代码。*/ #if 0/** GPT的PR寄存器GPT的分频设置* bit11:0 设置分频值设置为0表示1分频* 以此类推最大可以设置为0XFFF也就是最大4096分频*/GPT1-PR 65; //设置为1即65166分频因此GPT1时钟为66M/661MHz/** GPT的OCR1寄存器GPT的输出比较1比较计数值* 当GPT的计数值等于OCR1里面值时候输出比较1就会发生中断* 这里定时500ms产生中断因此就应该为1000000/2500000;*/GPT1-OCR[0] 500000;/** GPT的IR寄存器使能通道1的比较中断* bit0 0 使能输出比较中断*/GPT1-IR | 1 0;/** 使能GIC里面相应的中断并且注册中断处理函数*/GIC_EnableIRQ(GPT1_IRQn); //使能GIC中对应的中断system_register_irqhandler(GPT1_IRQn, (system_irq_handler_t)gpt1_irqhandler, NULL); //注册中断服务函数 #endif}#if 0 /* 中断处理函数 */ void gpt1_irqhandler(void) { static unsigned char state 0;state !state;/** GPT的SR寄存器状态寄存器* bit2 1 输出比较1发生中断*/if(GPT1-SR (10)) {led_switch(LED2, state);}GPT1-SR | 10; /* 清除中断标志位 */ } #endif/** description : 微秒(us)级延时* param - value : 需要延时的us数,最大延时0XFFFFFFFFus* return : 无*/ void delayus(unsigned int usdelay) {unsigned long oldcnt,newcnt;unsigned long tcntvalue 0; /* 走过的总时间 */oldcnt GPT1-CNT;while(1){newcnt GPT1-CNT;if(newcnt ! oldcnt){if(newcnt oldcnt) /* GPT是向上计数器,并且没有溢出 */tcntvalue newcnt - oldcnt;else /* 发生溢出 */tcntvalue 0XFFFFFFFF-oldcnt newcnt;oldcnt newcnt;if(tcntvalue usdelay)/* 延时时间到了 */break; /* 跳出 */}} }/** description : 毫秒(ms)级延时* param - msdelay : 需要延时的ms数* return : 无*/ void delayms(unsigned int msdelay) {int i 0;for(i0; imsdelay; i){delayus(1000);} }/** description : 短时间延时函数* param - n : 要延时循环次数(空操作循环次数模式延时)* return : 无*/ void delay_short(volatile unsigned int n) {while(n--){} }/** description : 延时函数,在396Mhz的主频下* 延时时间大约为1ms* param - n : 要延时的ms数* return : 无*/ void delay(volatile unsigned int n) {while(n--){delay_short(0x7ff);} } 文件 bsp_delay.c 中一共有 5 个函数分别为 delay_init 、 delayus 、 delayms 、 delay_short 和 delay 。除了 delay_short 和 delay 以外其他三个都是新增加的。函数 delay_init 是延时初始化函数主要用于初始化 GPT1 定时器设置其时钟源、分频值和输出比较寄存器值。第 43 到 68 行被屏蔽掉的程序是 GPT1 的中断初始化代码如果要使用 GPT1 的中断功能的话可以参考此部分代码。第 73 到 89 行被屏蔽掉的程序是 GPT1 的中断处理函数 gpt1_irqhandler 同样的 如果需要使用 GPT1 中断功能的话可以参考此部分代码。 函数 delayus 和 delayms 就是 us 级和 ms 级的高精度延时函数函数 delayus 就是按照我们 在 20.1.2 小节讲解的高精度延时原理编写的 delayus 函数处理 GPT1 计数器溢出的情况。函数delayus 只有一个参数 usdelay 这个参数就是要延时的 us 数。 delayms 函数很简单就是对 delayus(1000)的多次叠加此函数也只有一个参数 msdelay 也就是要延时的 ms 数。 最后修改 main.c 文件内容如下 #include bsp_clk.h #include bsp_delay.h #include bsp_led.h #include bsp_beep.h #include bsp_key.h #include bsp_int.h #include bsp_keyfilter.h/** description : main函数* param : 无* return : 无*/ int main(void) {unsigned char state OFF;int_init(); /* 初始化中断(一定要最先调用) */imx6u_clkinit(); /* 初始化系统时钟 */delay_init(); /* 初始化延时 */clk_enable(); /* 使能所有的时钟 */led_init(); /* 初始化led */beep_init(); /* 初始化beep */while(1) { state !state;led_switch(LED0, state);delayms(500);}return 0; }main.c 函数很简单在第 20 行调用 delay_init 函数进行延时初始化最后在 while 循环中 周期性的点亮和熄灭 LED0 调用函数 delayms 来实现延时。 4、 编写 Makefile 和链接脚本 因为本章例程并没有新建任何文件所以只需要修改 Makefile 中的 TARGET 为 delay 即 可链接脚本保持不变。 5、编译下载 使用 Make 命令编译代码编译成功以后使用软件 imxdownload2 将编译完成的 bsp.bin 文件生成可执行的img文件命令如下 make ./imxdownload2 delay.bin 如果  imxdownload2无权限可用以下命令添加权限 chmod 777 imxdownload2 利用Win32DiskImager软件将load.img执行文件写入SD卡SD卡插入开发板上即可正常运行。如果代码运行正常的话 LED0 会以以 500ms 为周期不断的亮、灭闪烁。可以通过肉眼观察 LED 亮灭的时间是否为 500ms。 但是肉眼观察肯定不准确既然本章号称高精度延时实验那么就得经得住专业仪器的测试。我们 率就应该是 1/0.0000425000Hz25KHz 。使用示波器测试 LED0 对应的 IO 频率结果如图 20.4.2.1 所示 从图 20.4.2.1 可以看出 LED0 对应的 IO 波形频率为 22.3KHz 周期是 44.9us 那么 main 函数中 while 循环执行一次的时间就是 44.9/222.45us 大于我们设置的 20us 看起来好像是延 时不准确。但是我们要知道这 22.45us 是 main 函数里面 while 循环总执行时间也就是下面代 码的总执行时间 while(1) { state !state; led_switch(LED0, state); delayus(20); } 在上面代码中不止有 delayus(20) 延时函数还有控制 LED 灯亮灭的函数这些代码的执行也需要时间的即使是 delayus 函数其内部也是要消耗一些时间的。假如我们将 while 循环里面的代码改为如下形式 while(1) { GPIO1-DR ~(13);delayus(20); GPIO1-DR | (13);delayus(20); } 上述代码我们通过直接操作寄存器的方式来控制 IO 输出高低电平理论上 while 循环执行时间会更小并且 while 循环里面使用了两个 delayus(20) 因此执行一次 while 循环的理论时间应该是 40us 和上面做的实验一样。重新使用示波器测量一下结果如图 20.4.2.2 所示 从图 20.4.2.2 可以看出此时 while 循环执行一次的时间是 41.8us 那么一次 delayus(20) 的时间就是 41.8/220.9us 很接近我们的 20us 理论值。但是还是因为有其他程序开销存在在加上示波器测量误差所以不可能测量出绝对的 20us 。但是其已经非常接近了基本可以证明我们的高精度延时函数是成功的、可以用的。 例程 【免费】Linux学习笔记17-高精度延时实验例程资源-CSDN文库
http://www.tj-hxxt.cn/news/139757.html

相关文章:

  • 网站开发用什么字体网页站点是什么意思
  • 做一级域名网站多少钱外贸网络推广专员
  • h5网站开发企业标准化体系建设流程
  • 东台建设网站wordpress 后台忘了
  • 网站建设与管理教学视频西安网站品牌建设
  • 网站被人做跳转恺英网络公司最新消息
  • 网页制作与网站建设宝典扫描版pdf百万网站建设报价
  • 常州微信网站建设咨询东莞网站建站推广
  • 长沙免费建站模板专业柳州网站建设哪家便宜
  • 干净简约的网站怎么做网站支付
  • 电子商务网站建设特点网上商城网站建设报价
  • ps网站导航条素材seo怎么做网站优秀案例
  • 做自媒体都有什么网站下载黑龙江建设网官网网站
  • 国内免费推广网站如何做网站改版
  • wordpress阿里云云存储绵阳做网站优化
  • 盘锦做网站选哪家已有备案号新增网站备案要关闭原先的站点吗
  • 烟台网站排名优化一级造价工程师报名时间
  • 漳浦县城乡规划建设局官方网站松原市建设局网站投诉中心
  • 电子商务网站与建设课件开发一个app需要什么条件
  • 网站内容编写方法企业为什么做网站素材
  • 襄樊市网站建设公司安徽手机网站建设
  • 网站的二级目录怎么做招聘简历模板
  • 广东省住房城乡建设厅网站爱站网工具包
  • 危险网站提示wordpress 获取当前文章栏目链接
  • apple私人免费网站怎么下载深圳网络推广培训中心
  • 如何把网站放到域名上台州建设质量监督网站
  • 高校精神文明建设网站做网站会员功能
  • 北京建网站公司飞沐wordpress dropship
  • php网站投票源码网站集约化建设标准
  • 皮具网站建设服装网站外包加工网会员