我已经为 GPS 编写了一个代码。我使用了三个计时器计时器0 A 用于5s、计时器1A 用于100ms、计时器2A 用于30s、 所有这些都被用作中断。最初一切运行正常,但经过一段时间后,程序会在中断中出现 stcks,并且不会跟随主函数内的 while 循环。根据我的了解,while 循环始终在运行,计时器在后台运行, 但在一段时间后、计时器会继续运行、但程序不会进入 while 循环。
/*************
这是用于监控 Pi 状态的主要程序应用程序
PPD0引脚接收来自 Pi 的状态。 每次切换时、
状态会更新、并由 LED 显示。 有4种状态:
第一个状态表示 PI 最近是否重新启动、
其中其他3个引脚显示 PI 状态。 PI 的当前状态、
由相应 LED 的参考文献表示
它利用 TM4C123G 的 WTimer0来实现内部时序。
如果程序在60秒内未从 PI 接收到任何状态、
程序将重新初始化。
系统还会在 GPS 的帮助下每秒获得更新时间。
它连接到 UART1、NMEA 语句通过存储在环形缓冲器中
UART 中断。 当句子时、通过数据解析提取时间信息
终止。
它会生成自己的脉冲、以告知 PI 何时传输数据。 它会自动同步
每30分钟使用 GPS 的 PPS 以消除计时器漂移。 使用 WTimer 1
要监控重新同步超时、使用计时器1将脉冲设置为零
连接:
PD0 -> Pi 状态切换引脚
PB1 -> LED1 (表示 Pi 最近是否重新启动)
PB2 -> LED2
Pb3 -> LED3
PB4 -> LED4
GND -> Pi 接地
PC4 (U1RX)-> GPS TX
PC6 -> GPS PPS
PC7 -> PI GPIO 引脚(指示 PI 启动传输)
3.3V -> GPS VIN 引脚
GND -> GPS GND
秘书长的报告 /
#include
#include
#include
#include
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include
#include "driverlib/timer.h"
#include "drivers/buttons.h"
#include "inc/tm4c123gh6m.h"
#include "inc/SysTick .h"
#include "inc/lcd.h"
#include "strfunc.h"
#include "uartConfiguration.h"
#include "utils/scheduler.h"
#include "utils/ustdlib.h"
#include "utils/uartstdio.h"
#include "adafruitUltimateGPS.h"
// SysTick 频率(用于 SysTick 中断时序),设置为200Hz
#define TICKS_PER_second 200
#define PI_TIMER_Timout 60 //超时(以秒为单位)、之后在没有状态变化的情况下复位 PI
#define PI_TOTAL_States 4 //状态总数/LED
#define PPS_TIMEOUT 5.0 // 1秒
#define PPS_RESUNC_TIME 30 //1800sec=30分钟:内部计时器必须与 GPS PPS 重新同步之后的时间
#define PPS_HIGH_PULSE_TIME 对于 PPS 脉冲的高电平脉冲、为100 //时间(以 ms 为单位)
int 计数= 0;
//--------
//函数原型
//--------
//void configWtimer (void);//configur
void configWatchDog (void);
void pioStateCurrBlink (void *pvParam);
bool isDeviceIDSyncPrepTime (char* currTimeString、uint8_t currDeviceID);
//------
//全局变量//
//------
bool pioStatus[pi_total_states];//bool 数组、用于存储所有状态的状态
int piCurrentState=0;//用于存储当前状态的变量
int piStateCurrentToggle = 0xFF;//变量来存储闪烁(当前)状态上的逻辑
bool PPSInterruptOccaled=false;//bool 变量、用于存储重新同步请求后是否发生 pps 中断
bool ResyncTimeout=true;//flag,用于说明是否发生了与 PPS 重新同步的超时
bool PPSTimerEnabled=false;//flag、用于存储是否启用 PPS 计时器
uint32_t lastSyncWithPPS = 0;//变量用于存储上次与 PPS 重新同步后经过的时间
int programState=0;//
const uint8_t device_id=1;//设备 ID
tSchedulerTask g_psSchedulerTable[]=//由调度程序要执行的任务(函数)组成的表
{
{pioStateCurrentBlink、(void*) 0、tICKS_PER_second/10、0、false}、 //每隔10秒闪烁一次当前状态 LED
};
uint32_t g_ui32SchedulerNumTasks =(sizeof (g_psSchedulerTable)/ sizeof (tSchedulerTask));//任务数
///--------------------
////////////////// 功能定义\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
///--------------------
void configPiStatusGPIO()
{
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);//启用 PORTD 外设
GPIOPinTypeGPIOInput (GPIO_PORTD_base、GPIO_PIN_0);//将端口 D 引脚0设置为输入类型
GPIOIntTypeSet (GPIO_PORTD_base、GPIO_PIN_0、GPIO_BLE_EDGE);//将 int 设置为两个边沿(在状态切换时将调用)
ROM_IntEnable (INT_GPIOD);
GPIOIntEnable (GPIO_PORTD_base、GPIO_PIN_0);//启用中断
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);//启用端口 B 外设
GPIOPinTypeGPIOOutput (GPIO_PORTB_BASE、0xFE);//将端口 B 引脚1-7设置为输出类型
GPIOPinWrite (GPIO_PORTB_BASE、0xFE、0x00);//将 PB0-7引脚设置为0
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
//LED
GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2);
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0x00);
}
空 configPiStatusTimer()
{
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_WTIME0);//启用宽 timer0 peropheral
ROM_TimerDisable (WTIMER 0_BASE、TIMER_A);//禁用计时器以进行正确配置
ROM_TimerIntDisable (WTIMER 0_BASE、TIMER_TIMA_TIMEOUT);//禁用计时器
TimerClockSourceSet (WTIMER 0_BASE、TIMER_CLOCK 系统);//配置系统的定时器时钟源
ROM_TimerConfigure (WTIMER 0_BASE、TIMER_CFG_PERIODICRACRACASE);//将计时器设置为周期性递减计时器
TimerLoadSet64 (WTIMER 0_BASE、(uint64_t)(ROM_SysCtlClockGet ()*PI_TIMER_Timout);//加载1分钟的值
ROM_IntMasterEnable();//启用主中断
ROM_IntEnable (INT_WTIMEER0A);//启用宽 Timer0中断
ROM_TimerIntEnable (WTIMER 0_BASE、TIMER_TIMA_TIMEOUT);
ROM_TimerEnable (WTIMER 0_BASE、TIMER_A);//启用计时器
}
//检测状态引脚上的切换时产生中断
void pSTATUSGPIOInterrupt()
{
GPIOIntClear (GPIO_PORTD_base、GPIO_INT_PIN_0);//清除中断
TimerLoadSet64 (WTIMER 0_BASE、(uint64_t)(ROM_SysCtlClockGet ()*PI_TIMER_Timout));//重新加载计时器值
如果(++piCurrent State=pi_total_States)//在完成所有工作后重置引脚状态
pCurrentState=1;
if (piCurrentState!= 1)//更新状态 LED
GPIOPinWrite (GPIO_PORTB_BASE、1<<piCurrState, 1<<piCurrState);
其他
GPIOPinWrite (GPIO_PORTB_BASE、0xFE、0x00);
}
//切换当前状态引脚 LED
void pioStateCurrentBlink (void *pvParam)
{
// pioStateCurrent Toggle =~pioCurrentStateToggle;
// GPIOPinWrite (GPIO_PORTB_BASE、0x02<<piCurrState, piCurrStateToggle);
}
定时器超时时时时为//中断
空 PionStatusTimerInterrupt()
{
// ROM_TimerIntClear (WTIMER 0_BASE、TIMER_TINA_TIMEOUT);
////g_psSchedulerTable[0].bActive=false;
// GPIOPinWrite (GPIO_PORTB_BASE、0xFE、0x00);
////ROM/TimerDisable (TIMER0_BASE、TIMER_A);
//
//当前状态=0;
// pioStateCurrent Toggle = 0xFF;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// 在此处输入用于重置 PI 的代码//////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
void configPPSGPIO()
{
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOC);//启用 PORTC 外设
GPIOPinTypeGPIOInput (GPIO_PORTC_BASE、GPIO_PIN_6);//将端口 C 引脚6设置为输入类型
GPIOIntTypeSet (GPIO_PORTC_BASE、GPIO_PIN_6、GPIO_RISING _EDGE);//将 int 设置为上升沿(将在从低电平到高电平的变化时调用)
GPIOPinTypeGPIOOutput (GPIO_PORTC_BASE、GPIO_PIN_7);//将端口 C 引脚7设置为输出类型
GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、0x00);//将0写入 PC7
}
空 configPPSTIME()
{
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);//启用宽 timer0外设
ROM_TimerDisable (TIMER0_BASE、TIMER_A);//禁用计时器以进行正确配置
ROM_TimerIntDisable (TIMER0_BASE、TIMER_TIMA_TIMEOUT);//禁用计时器
TimerClockSourceSet (TIMER0_BASE、TIMER_CLOCK 系统);//配置系统时钟源
ROM_TimerConfigure (TIMER0_BASE、TIMER_CFG_PERIODICRACASE);//将计时器设置为周期性递减计时器
TimerLoadSet (TIMER0_BASE、TIMER_A、((ROM_SysCtlClockGet ())* PPS_TIMEOUT);//加载值为1秒
ROM_IntMasterEnable();//启用主中断
ROM_IntEnable (INT_TIMER0A);//启用宽 timer0中断
ROM_TimerIntEnable (TIMER0_BASE、TIMER_TINA_TIMEOUT);
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_Timer1);//启用宽 timer0 peropheral
ROM_TimerDisable (Timer1_base、timer_A);//禁用计时器以进行正确配置
ROM_TimerIntDisable (Timer1_base、timer_TINA_TIMEOUT);//禁用计时器
//TimerClockSourceSet (Timer1_base、timer_clock_system);//配置系统的计时器时钟源
ROM_TimerConfigure (Timer1_base、TIMER_CFG_ONE_SHOT);//将计时器设置为周期性递减计时器
TimerLoadSet (Timer1_base、timer_A、((ROM_SysCtlClockGet ()/1000)* PPS_HIGH_PULSE_TIME));//加载值100ms
ROM_IntMasterEnable();//启用主中断
ROM_IntEnable (INT_TIMER1A);//启用宽 timer0中断
ROM_TimerIntEnable (Timer1_base、timer_TINA_TIMEOUT);
ROM_IntPrioritySet (timer_A、0);
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_TIMER2);//启用宽 timer0 peropheral
//TimerClockSourceSet (TIMER2_base、timer_clock_system);//配置系统的计时器时钟源
ROM_TimerConfigure (TIMER2_base、TIMER_CFG_PERIODICRACRACASE);//将计时器设置为周期性递减计时器
TimerLoadSet (TIMER2_base、TIMER_A、((ROM_SysCtlClockGet ())* PPS_RESUNC_TIME);//加载值100ms
ROM_IntMasterEnable();//启用主中断
ROM_IntEnable (INT_TIMER2A);//启用宽 timer0中断
ROM_TimerEnable (TIMER2_base、TIMER_A);
ROM_TimerIntEnable (TIMER2_base、TIMER_TINA_TIMEOUT);
}
void synsynsynsWithGPSPPS()
{
TO_PC ("正在等待来自 GPS 的 PPS \r\n);
GPIOIntClear (GPIO_PORTC_BASE、GPIO_INT_PIN_6);//清除中断
ROM_IntEnable (INT_GPIOC);
GPIOIntEnable (GPIO_PORTC_BASE、GPIO_PIN_6);//启用中断
// delay_ms (3000);
//TimerLoadSet (TIMER0_BASE、TIMER_A、((ROM_SysCtlClockGet ())* PPS_TIMEOUT);
//// while (!PPSInterruptocc固 化)
////{
////}
//
/// ROM_IntDisable (INT_GPIOC);
////// GPIOIntDisable (GPIO_PORTC_BASE、GPIO_PIN_6);//禁用中断
//// PPSInterruptOccaled=false;//下次重置 PPSInterruptOcc固 化
}
空 PPSGPIOInterrupt()
{
GPIOIntClear (GPIO_PORTC_BASE、GPIO_INT_PIN_6);//清除中断
如果(!PPSTimerEnabled)//IT 在重新同步超时时时被禁用、并在第356行设置为 false
{
ROM_TimerEnable (TIMER0_BASE、TIMER_A);
PPSTimerEnabled=true;
TimerLoadSet (TIMER0_BASE、TIMER_A、((ROM_SysCtlClockGet ())* PPS_TIMEOUT);
}
ROM_IntDisable (INT_GPIOC);
GPIOIntDisable (GPIO_PORTC_BASE、GPIO_PIN_6);//禁用中断
// PPSInterruptOccaled=true;
lastSyncWithPPS = 0;
TO_PC ("PPS 已发生且控制器已同步\r\n);
}
void pPS_resync_timeout(){
ROM_TimerIntClear (TIMER2_base、TIMER_TINA_TIMEOUT);//清除中断
ResyncTimeout=true;
//programState = 1;
count = count + 5;
// TO_PC ("\r\n 状态2");
ROM_TimerDisable (TIMER0_BASE、TIMER_A);
ROM_TimerDisable (Timer1_base、timer_A);
programState = 2;
ROM_TimerDisable (TIMER2_base、TIMER_A);
TO_PC ("resync-time\r\n");
}
空 PPSHighTimerInterrupt()
{
ROM_TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT);//清除中断
GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、0xFF);//向 PC 写入1
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0xFF);//将1写入额外的引脚以进行调试
ROM_TimerEnable (Timer1_base、timer_A);//计时器1运行100ms - delay_ms (100)
TimerLoadSet (Timer1_base、timer_A、((ROM_SysCtlClockGet ()/1000)* PPS_HIGH_PULSE_TIME));//加载值100ms
TO_PC ("高脉冲\r\n");
}
空 PPSLowTimerInterrupt()
{
ROM_TimerIntClear (Timer1_base、timer_TINA_TIMEOUT);
GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、0x00);
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0x00);
//TimerLoadSet (Timer1_base、timer_A、((ROM_SysCtlClockGet ()/1000)* PPS_HIGH_PULSE_TIME));//加载值100ms
ROM_TimerDisable (Timer1_base、timer_A);
TO_PC ("低脉冲\r\n");
}
///--------------------
////////////////// 主功能
///--------------------
int main()
{
//初始化
ROM_SysCtlClockSet (SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHz);//设置系统频率80MHz
ROM_FPULazyStackingEnable();
SysTK_Init();
调度器初始化(tICKS_PER_second);//初始化调度程序
//configWatchdog();//initialize watchdog -要进行测试,请将其注释
configUART();//初始化应用程序使用的 UART
initgps();
initStreamer();
TO_PC ("initialized\r\n");
configPiStatusGPIO();
configPiStatusTimer();
configPPSGPIO();
configPPSTIME();
TO_PC ("configured\r\n");
programState=1;
while (1)
{
switch (programState)
{
情况0:
{
if (isGPSSentenceComplete())
{
GPSGetData();
if (isGPSDataUpdated())
{
if (isDeviceIDSyncPrepTime ((char*) GPSData->time、device_id)=true)
{
TO_PC (GPSData->Time);
TO_PC ("\r\n");
TO_PC ("\r\nShifting to State 1");
programState = 1;
TO_PC ("\r\n");
}
}
}
中断;
}
案例1:
{
TO_PC ("\r\nSTATE 1");
GPIOPinWrite (GPIO_PORTB_BASE、GPIO_PIN_0、0x00);
syncGPSPPS();
GPIO_PORTB_DATA_R |= 0x02;
GPIO_PORTB_DATA_R &=~0x1C;
TO_PC ("\r\nShifting to State 2");
programState = 2;
中断;
}
案例2:
{
//TO_PC ("\r\n S2");
IF (重新同步超时)
{
ROM_TimerEnable (TIMER2_base、TIMER_A);
TO_PC ("\r\n 状态2");
ROM_TimerDisable (TIMER0_BASE、TIMER_A);
ROM_TimerDisable (Timer1_base、timer_A);
PPSTimerEnabled = false;
programState = 1;
ResyncTimeout=false;
}
中断;
}
}
//检查 Pi 控制的两个 GPIO
//打开/关闭 LED
}
// while (1)
//{
// if (重新同步超时)
// synsWithGPSPPS();
// if (isGPSSentenceComplete())
//{
//// TO_PC ("comp\r\n");
// GPSGetData();
//// TO_PC ("receivd\r\n");
// if (isGPSDataUpdated())
//{
// TO_PC ("\r\n");
// TO_PC (GPSData->Time);
//
// TO_PC ("\r\n");
// delay_ms (100);
//}
//
//}
//
//}
//
}//end main
///----------------
//函数定义
///----------------
void configWatchdog()//配置看门狗计时器,在第二个超时后具有复位功能
{
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_WDOG0);
ROM_IntMasterEnable();
ROM_IntEnable (INT_Watchdog);
ROM_WatchdogReloadSet (WATCHDOG0_BASE、ROM_SysCtlClockGet ()*5);//将 Watcdog 超时设置为20秒
ROM_WatchdogResetEnable (WATCHDOG0_BASE);
ROM_WatchdogEnable (WATCHDOG0_BASE);
ROM_IntPrioritySet (INT_Watchdog、3);
}
空 WatchdogIntHandler (空)
{
ROM_WatchdogIntClear (WATCHDOG0_BASE);//清除看门狗中断
DELAY_us (1);
}
bool isDeviceIDSyncPrepTime (char* currTimeString、uint8_t currDeviceID)
{
char d_id[4];
strcpy (d_id、"1.000");
TO_PC ("\r\nDevice ID:");
TO_PC (d_id);
TO_PC ("\r\nDevice Time:");
TO_PC (&currTimeString[5]);
// TO_PC ("\r\n 设备时间:");
// char CURR_TIME_char[1];
// strcpy (CURR_TIME_CHAR、&currTimeString[5]);
// TO_PC (((char*) CURR_TIME_CHAR);
// uint8_t g = atoi (CURR_TIME_CHAR);
//
// TO_PC ("\r\nCheck:");
// uint8_t h = atoi (&currTimeString[5]);
//
// if (strncmp (&currTimeString[5]、"2.000"、4)=0 || strncmp (&currTimeString[5]、"2.000"、4)=0){
// TO_PC ("\r\nCheck Passed -->");
//}
if (strncmp (&currTimeString[5]、"1.000"、3)=0 || strncmp (&currTimeString[5]、"6.000"、3)=0){
TO_PC ("\r\n 触发时间:");
TO_PC (&currTimeString[5]);
返回 true;
}
否则{
返回 false;
}
}