【linux-IMX6ULL-定时器-GPT-串口配置流程-思路】

目录

  • 1. 定时器配置流程
    • 1.1 EPIT定时器简介
    • 1.2 定时器1(epit1)的配置流程
    • 1.3 配置代码(寄存器版本)
    • 1.4 定时器-配合按键消抖
      • 1.4.1 实现原理
      • 1.4.2 代码实现(寄存器版)
  • 2. GPT定时器实现高精度延时
    • 2.1 延时原理分析
    • 2.2 代码实现
  • 3. UART串口配置流程
    • 3.1 UART串口通信基本概念;
      • 3.1.1 基本术语
      • 3.1.2 接线方式
      • 3.1.3 UART通信协议
    • 3.2 配置流程
    • 3.3 程序实现(寄存器版)

个人学习记录,下面这些都属于外设的基本配置,一般就是跟寄存器打交道,而配置思路也是大同小异

1. 定时器配置流程

1.1 EPIT定时器简介

  EPIT 的全称是:Enhanced Periodic Interrupt Timer,直译过来就是增强的周期中断定时器,定时器顾名思义就是记时的,对于其他的单片机例如是STM32而言,定时器具备输入捕获和配置PWM输出的功能,但是对于IMX6ULL的EPIT而言就一个定时的功能,比较简单。
  具体的功能可产靠数据手册的秒描述,这里简述几个重要的点:

  • 时钟源可选的 32 位向下计数器
  • 12 位的分频值
  • 当计数值和比较值相等的时候产生中断

1.2 定时器1(epit1)的配置流程

在这里插入图片描述

  1. 初始化定时器:设计定时器相应的寄存器配置,例如时钟源、分频系数、计数重装值、计数初值等:
  2. 使能定时器:这个对于很多外设都是如此,如歌配置好了初始化基本都要进行使能进行工作;
  3. 使能GIC中断服务控制器:开启中断
  4. 对中断服务函数进行注册:中断注册函数的内容可以具体里哦阿姐在IMX6ULL的中断服务系统;
  5. 编写中断服务函数的内容:这个的注意事项就是完成中断任务后要进行中断标志位的清除;

1.3 配置代码(寄存器版本)

/*初始化EPIT定时器函数*/
void epit1_init(unsigned int frac,unsigned int lodvalue)
{if(frac>4095){frac =4095;}/*配置控制寄存器CR*/EPIT1->CR =0;/*清零*/EPIT1->CR = (1<<1)|(1<<2)|(1<<3)|(frac<<4)|(1<<24);EPIT1->LR = lodvalue;/*加载寄存器的值,相当于到计数值*/EPIT1->CMPR = 0;/*计数器从lodvalue计数到0的话就触发中断*//*初始化中断,使能中中断*/GIC_EnableIRQ(EPIT1_IRQn);system_register_irqhandler(EPIT1_IRQn,epit1_irqhandler,NULL);/*中断ID,中断服务函数,给中断服务函数传递的参数*//*打开EPIT定时器*/EPIT1->CR |=(1<<0);
}
/*中断服务函数的编写*/void  epit1_irqhandler(unsigned int gicciar,void *param){static unsigned  char state = 0;state = !state;if(EPIT1->SR&(1<<0))//判断最后一位是不是0,如果为真表示中断发生{led_switch(LED0,state);/*反转LED0灯*/}/*清除标志位*/EPIT1->SR=1;/*写清零,中断标志位*/}

1.4 定时器-配合按键消抖

  对于按键的输入检测,我们之前常用的就是延时消抖,比如延时10ms,然后再次进行确定,但是这样做对于整个程序的效率有很大的影响,这10ms系统只是单纯的在进行无意义的等待,而且延时也不能放在中断中,因为因为中断服务函数最基本的要求就是快进快出!在实际开发中这是要避免发生的;我们可以考虑使用一个定时器和按键输入中断触发来实现按键的消抖;

1.4.1 实现原理

  本质而言还是延时的思想,不过我们把延时这一做法用定时器来实现(当然不是在定时器中进行延时):具体的思路就是定时器在计时的过程中,CPU是可以干其他的工作的,因此定一个10ms的定时器,每当按键触发中断时,定时器就开启,这样等定时器计数到10ms后就会开启定时器的中断,然后我们在定时器的中断中确定按键是否按下,这样就实现了CPU无意义的消耗;示意图如下:它的精髓是按键在前期会有抖动,但是每次抖动都会进入中断把定时器初始化进行重启,因此进行10ms的定时是完全足够的;而定时器在计时的过程中CPU可以处理其他的事情
在这里插入图片描述

1.4.2 代码实现(寄存器版)

  其中定时器的配置流程和上述是一致的,其中按键中断的配置流程可以参考上篇中断配置流程思路,对于中断的配置是底层比较难写,但是对于上层而言只是调用库函数,因此是比较好些的,只要掌握其配置的流程思路就可以的;具体代码如下:无论那种配置都要进行使能和初始化这是每个外设都基本要进行的操作;

/*初始化按键中断*/
void keyfilter_init(void)
{gpio_pin_config_t key_config;IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);key_config.direction=kGPIO_DigitalInput;key_config.interruptMode=kGPIO_IntFallingEdge;  //注意这里错误//错误设置成低电平触发:导致按键按下去频繁进入中断//key_config.interruptMode=kGPIO_IntLowLevelkey_config.outputLogic = 1;gpio_init(GPIO1,18,&key_config);GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);system_register_irqhandler(GPIO1_Combined_16_31_IRQn,gpio1_io16_31_irqhandlder,NULL);gpio_enable_int(GPIO1,18);/*初始化定时器*/filtertimer_init(66000000/100);
}
/*初始化EPI1定时器*/
void filtertimer_init(unsigned int value)
{EPIT1->CR = 0;/*先清零*/EPIT1->CR = (1<<1)|(1<<2)|(1<<3)|(1<<24);/*不分频*/EPIT1->LR = value;/*加载寄存器的值,相当于到计数值*/EPIT1->CMPR = 0;/*计数器从lodvalue计数到0的话就触发中断*//*初始化中断,使能中中断*/GIC_EnableIRQ(EPIT1_IRQn);system_register_irqhandler(EPIT1_IRQn,filtertimer_irqhandler,NULL);/*中断ID,中断服务函数,给中断服务函数传递的参数*/
}
/*关闭EPIT1定时器*/
void filtertimer_stop(void)
{EPIT1->CR &= ~(1<<0);
}
/*重启EPIT1定时器*/
void filtertimer_restart(unsigned int value)
{EPIT1->CR &= ~(1<<0);//先关闭EPIT1->LR = value;   //装载值EPIT1->CR |= (1<<0);//再打开
}
/*注册EPIT1定时器中断处理函数*/
void filtertimer_irqhandler(unsigned int gicciar,void *param)
{static unsigned char state = 0;if(EPIT1->SR & (1<<0)){/*关闭定时器*/filtertimer_stop();if(gpio_pinread(GPIO1,18)==0){state = ! state;beep_switch(state);}}EPIT1->SR |= 1<<0;        /*写1清除中断标志位*/}
/*按键中断服务函数*/
void gpio1_io16_31_irqhandlder(unsigned int gicciar,void *param)
{/*开启定时器*/filtertimer_restart(66000000/100);/*打开EPIT定时器*//*清除中断标志位*/gpio_clearintflags(GPIO1,18);}

2. GPT定时器实现高精度延时

  对于IMX6ULL而言:GPTGPT 定时器全称为 General Purpose Timer,GPT是一个32位的向上计数器,是通用的定时器,同时具备一个12位的分频器(不是只能进行12分频);他的基本特性如下所示:

  1. 一个可选时钟源的 32 位向上计数器。
  2. 两个输入捕获通道,可以设置触发方式。
  3. 三个输出比较通道,可以设置输出模式。
  4. 可以生成捕获中断、比较中断和溢出中断。
  5. 计数器可以运行在重新启动(restart)或(自由运行)free-run 模式。但是一般就是用作重装载模式

2.1 延时原理分析

  本质上还是利用定时器计数的原理,只不过这里的计时是进行增量计时法。例如对于GPT定时器而言,其时钟源是66MHz的,对齐进行66分频后就是1Mhz,也就是计数器寄存器CNT计数一次,时间就过去了1us,因此我们可以可以让中国CNT计数器一直进行计数,每次进入到延时函数就把这次的CNT记录下来例如此时是100,然后我们要延时200,那么我们要做的就是等到CNT==300时我们再出延时函数,这样就实现了延时的效果,但是可能会出现溢出的情况,因此我们要再延时函数中对溢出情况i进行处理,具体的实现如下:注意,在进入延时函数前定时器就是一直再走,因此进入延时函数时定时器也在走,并且运行延时的每行代码定时器都走,因此这里的计时是增量计时法

2.2 代码实现

在这里插入图片描述

3. UART串口配置流程

3.1 UART串口通信基本概念;

3.1.1 基本术语

  1. 串行:就是数据一位一位的顺序传递;
  2. 异步通信:比如A和B通信,那么异步通信就是两边都要设置时钟且保持一致,如果保持不一致就可能会发生数据传输失败;
  3. 同步通信:顾名思义就是通信设备A和B是共用一条时钟线路,保持同步;
  4. 半双工:可以这样理解,工作一半,也就是发送数据和接受数据只能一时进行一个,也就是同一时间只能发数据或者收数据;
  5. 全双工:这个与半双工是相反的,即同一时间发送和接收数据是通一时间进行的;
  • 我们明白上面的概念后,就可以对串口通信UART进行一个定义:串口通信就是串行异步全双工的通信方式
  1. UART和USART的区别:USART指比UART多了一条时钟线,因此可以进行同步通信;但是相对而言,还是串口通信用的范围广泛一些;

3.1.2 接线方式

  一般而言就是四根线进行通信:但是最少可以三根线首先通信,如果是三根线的话只能其中一个设备只能收数据或者只能发数据;注意RX是与TX接线的,因为一个设备发送送数据,另外一个设备肯定是接受数据的;

3.1.3 UART通信协议

  任何通信都要进行约定好了才能通信,因此通信协议就是通信双方进行的一个约定,这个约定一般有起始位(低电平),数据为,奇偶校验位,停止位(高脉冲),示意图如下:一般对于串口通信而言是先发送低位后发送高位,也就是低位在前,高位在后;如下图:

  小知识点,如何进行奇偶校验:可以利用异或的功能,具体描述如下: 我们使用异或来判断一个二进制数中1的数量是奇数还是偶数异或具有交换律,所以判断101001中的1是奇数还是偶数,只用看:1 ^0 ^ 1 ^ 0 ^ 0 ^ 1的最终结果是1还是0,因为其具有交换律,所以 1 ^0 ^ 1 ^ 0 ^ 0 ^ 1=1 ^ 1 ^ 1 ^ 0 ^ 0 ^ 0 =1 ^ 1 ^ 1 = 1 ^ 0 = 1;因此结果是0就是偶数个,结果为1就是奇数个;

3.2 配置流程

  对于UART而言,其也是一个外设,因此对于外设UASRT的配置一般大体思路如下:注意再接受和发送数据时要进行检测是否空闲或者是否有数据可以接收
在这里插入图片描述

3.3 程序实现(寄存器版)

  

/*初始化UART1,波特率为115200 */
void uart_init(void)
{/*初始化IO*/uart_io_init();/*初始化串口UART1*/uart_disable(UART1);uart_softreset(UART1);/*配置UART1*/UART1->UCR1=0;/*配置UART1的数据位、奇偶校验位、停止位等*/UART1->UCR2 = 0;UART1->UCR2 |= (1<<1)|(1<<2)|(1<<5)|(1<<14);  /*发送和接收使能*/UART1->UCR3 |= (1<<2);/*bit2必须为1*//*设置波特率为:115200 */UART1->UFCR &= ~(7<<7); /*对RFDIV位域清零*/UART1->UFCR |= (5<<7);  /*1分频,uart_clock=80MHz*/UART1->UBIR=71;  //大坑,注意这里的UBIR,UBMR输入顺序不能变UART1->UBMR=3124;/*使能串口 */uart_enable(UART1);
}/*关闭串口UART1*/
void uart_disable(UART_Type *base)
{base->UCR1 &= ~(1<<0);/*关闭指定的串口*/
}/*关闭串口UART1*/
void uart_enable(UART_Type *base)
{base->UCR1 |= (1<<0);
}/* 复位UART,软复位*/
void uart_softreset(UART_Type *base)
{base->UCR2 &= ~(1<<0);while( (base->UCR2 & 0x1)==0);
}/*UART1的IO初始化*/void uart_io_init(void){IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX,0);  /*将引脚UART1_TX配置UART1_TX模式*/IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX,0);  /*将引脚UART1_RX配置UART1_RX模式*/IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX,0x10B0);/*配置UART1_TX电气属性*/IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX,0x10B0);/*配置UART1_RX电气属性*/}/*通过UART1发送一个字符*/
void uart_putc(unsigned char c)
{while(((UART1->USR2>>3)& 0x01)==0);/*等于0说明数据一直在发送中*/UART1->UTXD=c;
}/*通过UART1接收一个数据*/
unsigned char uart_getc(void)
{while(((UART1->USR2)& 0x01)==0);/*等待有数据可以读取*/return UART1->URXD;
}/* 通过串口发送一串字符*/
void uart_puts(char *str)
{char *p =str;while(*p!='\0'){uart_putc(*p++);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/836100.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序按钮去除边框线

通常我们去掉按钮边框直接设置 border:0 但是在小程序中无效&#xff0c;设置outline:none也没用&#xff0c;当然可能你会说加权重&#xff1b;试过了无效 实际上该样式是在伪元素::after内&#xff0c;主要你检查css 还看不到有这个关系&#xff0c;鹅厂就是坑多 类样式::…

半小时搞懂STM32面经知识点——IIC

1.IIC 1.1什么是IIC&#xff1f; 同步半双工通信协议&#xff0c;适用于小数据和短距离传输。 1.2 IIC需要几条线&#xff1f; IIC总共有2条通信总线&#xff08;SDA,SCL&#xff09;&#xff0c;SCL为时钟同步线&#xff0c;用于主机和从机间数据同步操作&#xff1b;SDA为…

【密评】 | 商用密码应用安全性评估从业人员考核题库(9/58)

Hill密码是重要古典密码之一&#xff0c;其加密的核心思想的是&#xff08;&#xff09;。 A.线性变换 B.非线性变换 C.循环移位 D.移位 著名的Kerckhoff原则是指&#xff08;&#xff09;。 A.系统的保密性不但依赖于对加密体制或算法的保密&#xff0c;而且依赖于密钥 B.系统…

【计算机网络】数据链路层的功能

数据链路层的基本功能&#xff1a; 封装成帧透明传输差错检测 数据链路层使用的信道主要有两种 点对点信道——PPP协议广播信道——CSMA/CD协议(有线局域网)、CSMA/CA协议(无线局域网) 数据链路层所处的地位 从图中可以看出&#xff0c;数据从主机H1送到主机H2需要在路径中…

论文笔记模版

1. 摘要 1.1 背景 1.2 挑战 1.3 提出新方法 1.4 贡献 2. 引言 2.1 背景&#xff08;引出问题&#xff09; ①介绍大背景&#xff1a; ② 应用场景&#xff1a; ③ 介绍主题&#xff1a; 2.2 引出挑战 一般用图表来展现出我们的挑战&#xff08;直观&#xff0c;解决什…

echarts环形图 legend文字过长显示...鼠标移动上展示全称

legend: {type: scroll,orient: vertical,x: left,y: bottom,top: "42%",left: 13%,data: this.dutyNames,textStyle: { color: #fff },triggerEvent: true,tooltip: {show: true,trigger: item,//鼠标移动上去展示全称},formatter: function (params) {var val &qu…

HTML五彩缤纷的爱心

写在前面 小编准备了一个五彩缤纷的爱心&#xff0c;送给各位小美女们~ 在桌面创建一个.txt文本文件&#xff0c;把代码复制进去&#xff0c;将后缀.txt改为.html&#xff0c;然后就可以双击运行啦&#xff01; HTML简介 HTML&#xff08;超文本标记语言&#xff09;是一种…

C++——二叉树搜索树

前面写了初阶数据结构——二叉树&#xff1b;本文内容是来对它来进行结尾 目录 一概念 二实现 2.1查找 2.2插入 2.3删除 完整源代码 三二叉树的应用 四二叉搜索树的性能分析 五二叉搜索树相关的面试题 一概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树…

妙笔生花,创作无限——WonderPen妙笔 for Mac

写作&#xff0c;是灵感的流淌&#xff0c;是心灵的独白。WonderPen妙笔 for Mac&#xff0c;为您的灵感插上翅膀&#xff0c;让您的创作更加流畅自如。它拥有简洁直观的界面设计&#xff0c;让您的思绪在纯净的写作环境中自由飞翔。多种写作模式&#xff0c;满足您不同的创作需…

Ps 滤镜:绘图笔

Ps菜单&#xff1a;滤镜/滤镜库/素描/绘图笔 Filter Gallery/Sketch/Graphic Pen 绘图笔 Graphic Pen滤镜可以模拟传统绘画技术&#xff0c;特别是模拟使用细油墨笔进行绘制的艺术效果。该滤镜主要用于将图像中的细节以细线的形式表现出来&#xff0c;非常适合于增强图像的线条…

c语言题库之多个数组从两边移动向中间汇聚

文章目录 题目分析代码实现代码分析 题目 c语言题库之多个数组从两边移动向中间汇聚 呈现效果&#xff1a;输入想要输入的字符数组呈现数组从两边向中间逐渐打开的样子 分析 首先我们需要一组我们想要输入的字符数组用来展示打开的字符其次我们需要进行对数组的替换&#x…

nss刷题(2)

1、[NSSCTF 2022 Spring Recruit]ezgame 打开题目是一个游戏界面 发现是有分数的&#xff0c;猜测分数达到某个之后可以获得flag&#xff0c;查看源码看一下 看到末尾显示分数超过65后显示flag 在js中找到了一个score,将他的值改为大于65的数后随意玩一次就可以得到flag同时&a…

Adobe Animate 2024软件下载

Adobe Animate 2024软件下载&#xff1a; 百度网盘下载https://pan.baidu.com/s/1cQQCFL16OUY1G6uQWgDbSg?pwdSIMS Adobe Animate 2024&#xff0c;作为Flash技术的进化顶点&#xff0c;是Adobe匠心打造的动画与交互内容创作的旗舰软件。这款工具赋予设计师与开发者前所未有的…

day05-面向对象内存原理和数组

day05 面向对象内存原理和数组 我们在之前已经学习过创建对象了,那么在底层中他是如何运行的。 1.对象内存图 1.1 Java 内存分配 Java 程序在运行时&#xff0c;需要在内存中分配空间。为了提高运算效率&#xff0c;就对空间进行了不同区域的划分&#xff0c;因为每一片区域…

【LeetCode算法】242. 有效的字母异位词

提示&#xff1a;此文章仅作为本人记录日常学习使用&#xff0c;若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、题目二、思路三、解决方案 一、题目 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每…

docker搭建redis6.0(docker rundocker compose演示)

文章讲了&#xff1a;docker下搭建redis6.0.20遇到一些问题&#xff0c;以及解决后的最佳实践方案 文章实现了&#xff1a; docker run搭建redisdocker compose搭建redis 搭建一个redis’的过程中遇到很多问题&#xff0c;先简单说一下搭建的顺序 找一个redis.conf文件&…

当代 Qt 正确的 安装方法 及 多版本切换

此文写于 20240511 首先去网站Index of /official_releases/online_installers下载一个安装器 安装器有什么用? 可以浏览安装版本 安装组件 安装器版本越能 能装的东西越多 现在只能选Qt5 和 Qt6 至于你公司用的Qt4 我也没招 见招时再拆招 安装器 默认国外源 可以换国内…

嵌入式全栈开发学习笔记---C语言笔试复习大全15

目录 指针运算 笔试题17 思考&#xff1a;*px、*px和(*px)的区别&#xff01; 笔试题18 补充命令8&#xff1a;“cd ..”退回到上一级目录 补充命令9&#xff1a;“man 3 函数名”可以查看库函数的原型 const 修饰指针是什么意思&#xff1f;&#xff08;笔试重点&#…

C++入门指南(上)

目录 ​编辑 一、祖师爷画像 二、什么是C 三、C发展史 四、C在工作领域的应用 1. 操作系统以及大型系统软件开发 2. 服务器端开发 3. 游戏开发 4. 嵌入式和物联网领域 5. 数字图像处理 6. 人工智能 7. 分布式应用 五、如何快速上手C 一、祖师爷画像 本贾尼斯特劳斯…

第二届“盘古石杯”全国电子数据取证大赛wp

服务器取证 先对网站进行重构 [rootstudy ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 643626ab3d8b mattermost/mattermost-pre…