/*
* 超声模块测距代码
*/
#ifndef PART_TM4C123GH6PM
#define PART_TM4C123GH6PM
#ifndef DOXYGEN
#define DOXYGEN
#include<stdint.h>
#include<stdbool.h>
#include"stdio.h"
#include"stdlib.h"
#include"math.h"
#include"inc/hw_memmap.h"
//#include"inc/hw_types.h"
#include"inc/hw_ints.h"
#include"driverlib/gpio.h"
#include"driverlib/pin_map.h"
#include"driverlib/pwm.h"
#include"driverlib/sysctl.h"
#include"driverlib/uart.h"
#include"driverlib/timer.h"
#include"driverlib/interrupt.h"
const double HEIGHT = 0.3;
unsigned char flag;
unsigned char RiseTime; //记录超声测距模块echo端高电平出现时的时钟
void Timer0AIntHandler();
int main(void) {
flag = 0;
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ); //配置时钟,但是需要查看自己板子上的晶振
//timer and interrupt
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // 启用Timer0模块
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // 启用PF0作为脉冲捕捉脚
GPIOPinConfigure(GPIO_PF0_T0CCP0); // 配置GPIO脚为使用Timer0捕捉模式
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_0);
GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_OD); // 为管脚配置开漏模式
TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME); // 配置使用Timer0的TimerA模块为边沿触发减计时计数模式
TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_BOTH_EDGES); // 使用边沿触发
TimerLoadSet(TIMER0_BASE, TIMER_A, 0x7d00); //设置计数范围为32000到0,为2ms,最长可以测0.7m,超声测距了
TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0AIntHandler); // 注册中断处理函数以响应触发事件
IntMasterEnable(); // 系统总中断开
TimerIntEnable(TIMER0_BASE, TIMER_CAPA_EVENT); // 时钟中断允许,中断事件为Capture模式中边沿触发
IntEnable(INT_TIMER0A); // NVIC中允许定时器A模块中断
//触发超声模块启动的引脚PF1
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);//Enable the port
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4); //配置输出端口PF1
//led
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
TimerEnable(TIMER0_BASE, TIMER_A); // 启动捕捉模块
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0x10);
SysCtlDelay(160/3); //延时10微秒
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, 0x00);
SysCtlDelay(SysCtlClockGet() / 3); //延时1s
if(flag == 1) return 0;
//GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, 0x00);
}
//注册中断函数
void Timer0AIntHandler()
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, 0xFF);
if(GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0) | 0xFE == 0xFF)RiseTime = TimerValueGet(TIMER0_BASE, TIMER_A);
else
{
uint32_t time = TimerValueGet(TIMER0_BASE, TIMER_A) > RiseTime ? RiseTime + 32000 – TimerValueGet(TIMER0_BASE, TIMER_A)
: RiseTime – TimerValueGet(TIMER0_BASE, TIMER_A);
if(time * 34 > (uint32_t)(HEIGHT * 1600000))
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, 0xFF);
flag = 1;
}
else
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, 0x02);
flag = 1;
}
SysCtlDelay((unsigned char)(SysCtlClockGet() / 3 * 5));
}
TimerIntClear(TIMER0_BASE, TimerIntStatus(TIMER0_BASE, TIMER_CAPA_EVENT)); //清除中断
}
#endif
#endif
Michael Sun:
脉冲捕获程序,建议楼主参考C:\ti\TivaWare_C_Series-2.1.0.12573\examples\peripherals\timer\edge_count.c的例程,并在启动代码中注册中断服务程序。
xyz549040622:
回复 Sun DaSheng Sun:
你用的什么板子呢,是你硬件的问题吧
Michael Sun:
回复 Sun DaSheng Sun:
M4的 NMI功能脚和JTAG功能脚在进行功能设置时,需要先解锁。
NMI脚就是pD7和PF0了。解锁有就可以进行GPIO寄存器配置。
user4180434:
问一下你。。为管脚配置开漏模式有什么用。。
Michael Sun:
回复 user4180434:
漏极开路模式在很多场合都很适用,例如多个漏极开路输出可以直接连在一起实现“线与”功能。
需要注意的是,使用漏极开路模式时,需要加上拉电阻。
user4180434:
回复 Michael Sun:
有资料说开漏不能有效接收输入信号。。“回读的仍是输出锁存器的状态而不是外部管脚的状态”,是吗??
为什么早期单片机都是不用管,既可以输入又能输出。。。现在的却不行了
Sun DaSheng Sun:
回复 Michael Sun:
是不是每一个端口,都能配置GPIO_PIN_TYPE_STD
GPIO_PIN_TYPE_WPU GPIO_PIN_TYPE_WPD GPIO_PIN_TYPE_OD GPIO_PIN_TYPE_ANALOG ?
如果不是的话怎么看哪个管脚能配置什么呢?
真是麻烦您了
Sun DaSheng Sun:
回复 Sun DaSheng Sun:
我现在PBO这个端口是作为T2CCP0捕捉模式使用,不是输出电压,而是检测电压,这样开漏模式还需要上拉电阻吗?
我用捕捉模式的时候配置成什么模式比较好呢?
我现在用这个捕捉模式进行超声波测距,可是同样的距离测几次都有很大的差距,这是为什么呢?
(原谅我问了这么多,真的是在这个问题上纠结了很多天了。实在不知道怎么办)