TIVA-TM4C123GH6PM的输入边沿计时模式的配置
正在学TIVA的TM4C123GH6PM板子,记录一下学习输入边沿计时模式的过程
2019年10月15日01:14:06更新
今天修复了Project里频率计的一个Bug。
可以测量低频率和任意频率啦!!!
想了个笨方法,定义了个全局变量tmp来记录进入中断函数那个瞬间他们的差值,即使仍然会进入CCPIntHandler(),其差值也已经被记录了下来。
不过还有一个问题就是测量的带宽不够大,一旦频率变高了,比如说大于200kHz,就会因为进入中断函数太快而导致无法执行calc_freq(),它被忽略掉了…导致频率测不出来
一. 实验简介
- 使用两个定时器
- 一个用PWM模式产生PWM波形
- 将此方波信号接入另一定时器的输入端,通过边沿计时模式来测量该信号的周期,并将其显示在液晶屏上
二. TM4C123输入边沿计时模式介绍
- 输入边沿计时模式用于捕捉输入信号的边沿时间,当输入信号有一个待捕捉的边沿时(上升沿或下降沿),计数器会产生一个中断信号。
- 对于上升沿检测,输入信号必须在上升沿之后保持高电平至少两个系统时钟周期,对于下降沿检测,输入信号必须在下降沿之后保持低电平至少两个系统时钟周期。根据这个标准,边沿检测的最大输入频率是系统频率的1/4。
- 选择输入边沿计时模式,需要将寄存器
GPTMTnMR
中的TnCMR
位置1
,且TnMR
位置0x3
,以选择捕获模式。 - 在输入边沿计时模式下,可以选择的边沿同样有上升沿,下降沿或双边沿,通过配置寄存器
GPTMCTL
的TnEVENT
位来选择。当定时器器独立工作时,可以使用预分频器将计数器的位数由16/32位扩展为24位/48位。 GPTMCTL
中的TnEN
被置位,计时开始。当有捕获事件(捕获到边沿信号)发生时,计数器的数值会被存储在寄存器GMTMTnR
和GPTMTnPS
中,并且可以被微处理器读取,之后产生一个捕获事件中断用于处理捕获事件。也就是说,只要检测到了自己设定的边沿的到来,就会进入一次中断- 处理完成后计数继续进行,直到GPTMCTL中的TnEN位被置
0
。而GPTMTnV
寄存器和GPTMTnPV
寄存器会保存当前独立运行的计数值和预分频器的值。当计数从0
达到了计数的初值
(递增计数模式,由装载寄存器设置)或是由初值达到0(递减计数模式)时,计数器重新装载初始值继续计数。
下图示范了采用递减计数模式,只捕获上升沿,计数器预设值为GPTMTnILR=0Xffff
,每当捕获一个上升沿时,计数器中的数值被写入GPTMTnR
和GPTMTnPS
寄存器(当使用预分频器时才使用此寄存器)中,注意只要检测到了边沿的到来就会进入一次中断。(当初我这块没弄明白,卡顿了好久…)
三. 库函数编程方法
首先使能对应的定时器模块,比如
Timer0
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //prototype:SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMERx);
找到该GPTM模块中
TnCCP0
和TnCCP1
(或是WTnCCP0
和WTnCCP1
)所对应的GPIO引脚,使能这些引脚所属的GPIO模块的时钟信号SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); //prototype:SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOBx);
将引脚设置为复用外设功能,如果要设置为定时器功能,调用以下函数
GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6); //prototype:GPIOPinTypeTimer(GPIO_PORTx_BASE, GPIO_PIN_x);
将GPTM模块的信号
TnCCP0
和TnCCP1
(或是WTnCCP0
和WTnCCP1
)配置到具体的的GPIO引脚上去:配置寄存器GPIOPCTL
。实际调用的是GPIOPinConfigure()
函数GPIOPinConfigure(GPIO_PB6_T0CCP0); //prototype:GPIOPinConfigure(GPIO_Pxx_TxCCPx);
配置定时器模块为捕捉-边沿计时模式
需要注意的是,在该模式下,
TimerConfigure
第二个参数是TIMER_CFG_SPLIT_PAIR
和一下之一相或:TIMER_CFG_A_CAP_TIME
模块A捕捉-边沿减计时模式TIMER_CFG_A_CAP_TIME _UP
模块A捕捉-边沿加计时模式TIMER_CFG_B_CAP_ TIME
模块B捕捉-边沿减计时模式TIMER_CFG_B_CAP_ TIME _UP
模块B捕捉-边沿加计时模式
例如
TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP);
设置计时范围,
TimerLoadSet
无论加计时还是减计时,都用这个函数设置Preload
值,这个值是指经过了多少个检测到的脉冲边沿后将重新装载(而不是检测到了多少个边沿才发生一次中断)除了要作通用配置外,每种定时器根据不同模式还要作具体的初始化配置,一会儿在src里体现
四. 示例代码
实现了输入任意频率PWM波形的频率检测,可以充当频率计使用,PB6接收PWM脉冲边沿,PF3输出PWM波形
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_timer.h"
#include "inc/hw_ints.h"
#include "inc/hw_gpio.h"
#include "inc/hw_i2c.h"
#include "inc/hw_sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/i2c.h"
#include "driverlib/udma.h"
#include "driverlib/fpu.h"
#include "driverlib/rom.h"
#include "uc1701.h"//*****************************************************************************
//Attention
//TM4C123 NMI unlock - To those who want to use PF0 and PD7, be reminded that these pins defaults as NMI ! ! !
//
//*****************************************************************************// The error routine that is called if the driver library encounters an error.
#ifdef DEBUG
void __error__(char *pcFilename, unsigned long ulLine)
{}
#endif
//*****************************************************************************//*************************Global variables*************************//
unsigned char pulse;
unsigned long freq;
unsigned long TIMER_TICK[2];
unsigned short i = 0;
unsigned long CCPLoadSet;
unsigned long PWM_Frep;
//******************************************************************////*************************Function dedclarations*************************//
void calc_freq(void);
void PWM_1B_IntHandler(void);
void CCP_Init(void);
void PWM_Set_PWM_Frep(unsigned long freq);//modified parts
void CCP_Set_Load(unsigned long load);//modified parts
void PWM_Init(unsigned long Freq_Hz, unsigned char duty);
void CCPIntHandler(void);
//*************************Function dedclarations*************************//
void main(void)
{SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);PWM_Set_PWM_Frep(131e3); //modified partsPWM_Init(PWM_Frep, 1);InitUC1701();UC1701CharDispaly(0, 4, "Freq Meter");UC1701CharDispaly(1, 9, "Hz");UC1701CharDispaly(2, 9, "kHz");UC1701CharDispaly(3, 9, "%");CCP_Set_Load(SysCtlClockGet() - 1); //modified partsCCP_Init();IntMasterEnable();while(1){calc_freq();UC1701DisplayN(1, 2, freq);DisPlayDataFloat_lower_than_100(2, 2, freq / 1000.00);UC1701DisplayN(3, 4, 100 - pulse);}
}
//*************************Initialization modules*************************//
void PWM_Init(unsigned long Freq_Hz, unsigned char duty){pulse = 100 - duty;SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);GPIOPinConfigure(GPIO_PF3_T1CCP1);GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_3);TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PWM);TimerIntRegister(TIMER1_BASE, TIMER_B, PWM_1B_IntHandler);IntEnable(INT_TIMER1B); //Enables a timer interruptTimerIntEnable(TIMER1_BASE, TIMER_CAPB_EVENT); //Enables individual timer interrupt sourcesIntMasterEnable(); //Enables the processor interruptTimerLoadSet(TIMER1_BASE, TIMER_B, SysCtlClockGet() / Freq_Hz - 1);TimerMatchSet(TIMER1_BASE, TIMER_B, (SysCtlClockGet() / Freq_Hz - 1) * (pulse / 100.0));TimerEnable(TIMER1_BASE, TIMER_B);
}
void CCP_Init(void){SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);GPIOPinConfigure(GPIO_PB6_T0CCP0);GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6);GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP);TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_NEG_EDGE);TimerLoadSet(TIMER0_BASE, TIMER_A, CCPLoadSet);TimerIntRegister(TIMER0_BASE, TIMER_A, CCPIntHandler);IntMasterEnable();TimerIntEnable(TIMER0_BASE, TIMER_CAPA_EVENT);IntEnable(INT_TIMER0A);TimerEnable(TIMER0_BASE, TIMER_A);
}
//*************************Initialization modules*************************////*************************Modified parts*************************//
void PWM_Set_PWM_Frep(unsigned long freq){PWM_Frep = freq;
}
void CCP_Set_Load(unsigned long load){CCPLoadSet = load;
}
//*************************Modified parts*************************////*************************InterruptHandlers modules*************************//
void PWM_1B_IntHandler(void){TimerIntClear(TIMER1_BASE, TIMER_CAPB_EVENT);
}
void CCPIntHandler(void){TimerIntClear(TIMER0_BASE, TIMER_CAPA_EVENT);if(i == 2)i = 0;TIMER_TICK[i++] = TimerValueGet(TIMER0_BASE,TIMER_A);
}
//*************************InterruptHandlers modules*************************////*************************Calculate frequence*************************//
void calc_freq(void)
{static unsigned long tmp;//ignore the re-execution of CCPIntHandler//save the current TIMER_TICK[0] - TIMER_TICK[1]//although TIMER_TICK is still varyingTimerIntClear(TIMER0_BASE, TIMER_A);tmp = abs(TIMER_TICK[1] - TIMER_TICK[0])freq = SysCtlClockGet() / tmp;
}
这个链接里可以找到完整项目代码,zip里有一些头文件和库
提取码: snih
五. 结果
别忘了把PB6和PF3跳线!因为它们是PWM接收和输出的端口~
我设置的PWM占空比为1%(设这么小主要是想看看极端条件下灵不灵敏),频率为50kHz
参考链接
[1]: Help with Frequency Meter(Google)
[2]: https://github.com/WadeGao/TIVA
TIVA-TM4C123GH6PM的输入边沿计时模式的配置相关推荐
- TIVA 123GXL的边沿计数模式测量低频PWM
TM4C123GXL频率计第二弹 上篇文章讲到了使用Edge Timer模式来测量频率较高的PWM信号的方法,这次写了个用另一种原理来测量频率的方法,那就是采用Edge Count(边沿计数模式)的方 ...
- linux(centos) NET模式网络配置
2019独角兽企业重金招聘Python工程师标准>>> linux虚拟机一般使用桥接和net模式,但是由于桥接在不同的网络环境中,需要重新配置,所以建议使用net模式,net模式的配 ...
- Vue Router history模式的配置方法及其原理
转载地址:https://segmentfault.com/a/1190000019391139 vue-router分为hash和history模式,前者为其默认模式,url的表现形式为http:/ ...
- VMware安装Ubuntu 18.04虚拟机(镜像下载、硬盘分区、创建虚拟机、安装系统、桥接模式网络配置)
1. VMware安装 安装VMware,Player免费,而且功能足够个人开发使用.(Pro的主要区别在于可以同时运行多个虚拟机,而Player只能同时运行一个) VMware Workstatio ...
- 三.STM32嵌入式学习--GPIO口(3)----通用输入的应用--按键的配置
前面我们讲了IO的通用输出的配置--点灯,今天我们讲讲按键输入. 依旧是学习思路: 如何让芯片内核判断到按键是否按下? 如果按键未按下,内核检测IO口是低电平,如果按下,则检测高电平. 如何检测IO口 ...
- GPIO的八种模式以及配置
STM32的GPIO 有8种可能的配置:(4种输入+2种输出+2种复用输出) (1) 浮空输入 GPIO_Mode_IN_FLOATING (2) 带上拉输入 GPIO_Mode_IPU (3) 带下 ...
- 帧中继环境下NBMA模式的配置
帧中继环境下NBMA模式的配置 1. 实验目的: 通过本次的实验,我们可以掌握如下技能 1) 帧中继静态映射及其broadcast参数的含义. 2) NBMA模式下的DR ...
- Apache之三种工作模式和配置性能优化
1 Apache的3种模式和版本 Apache目前一共有三种稳定的MPM(Multi-Processing Module,多进程处理模块)模式,它们分别是prefork,worker和event. 我 ...
- linux桥接设置静态,centos6.10 桥接模式下配置静态ip
centos6.10 桥接模式下配置静态ip主要是修改以下三个地方: /etc/sysconfig/network-scripts/ifcfg-eth0(这个文件名版本不同文件名也不同,可以先cd / ...
最新文章
- 7_12_2013 G: Mahjong problem
- 有向图缩点:tarjan强连通缩点(模板)
- linux_base-f10-10_7 linuxulator is not (kld)loaded
- 全球视频监控设备市场规模分析
- 使用 Tye 辅助开发 k8s 应用竟如此简单(五)
- 1095 解码PAT准考证 (25分)
- JavaScript文档对象模型document对象改变Html元素内容(3)
- 游戏开发之运算符重载(C++基础)
- Flutter String 常用方法
- 《吊打分析师》实战—深圳链家租房数据分析 | 附源码
- rcond--矩阵可逆的条件数估值
- 通信:5G孕育上游投资空间
- 神经网络预测鸢尾花的种类
- 山东赛区|数学建模国赛山东赛区成绩发布
- 使用canvas 绘制象棋棋盘
- 软件测试之第三方快捷支付_支付宝遭遇最强对手:银联正面PK快捷支付
- 淘宝直通车表格拖动时间段选择插件,纯手写80%还原
- Python爬取10529条《三十而已》热评,看看大家都说了些啥!
- Win10 / Win11、VScode内置终端美化教程(适用于 oh-my-posh 老版本 新版本请查看官网教程...)
- qq音乐正式版官方免费版