This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C123GH6PM:Tm4c123gh下午6在一段时间后开始运行异常

Guru**** 2609555 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/760851/tm4c123gh6pm-tm4c123gh6pm-starts-to-behave-abnormally-after-some-time

器件型号:TM4C123GH6PM

我已经为 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;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Muhammad、

    我看了你的代码、但有很多事情在进行、我不太清楚所有东西是如何组合在一起的、所以我看不到任何令人惊讶的明显。

    我注意到的一件事是、我实际上看不到在什么地方调用了 PPS_RESUNC_TIMEOUT、尽管您的屏幕截图显示它可能已经被调用。

    我可以为您提供一些帮助调试的一般提示。

    1) 1)如果程序每次都在相同的位置停止、则您应查看该位置。 该函数中发生了什么、可能还有它前面的那个。

    2) 2)让调试器运行并等待其挂起、然后暂停调试器并查看代码所在的位置。 也许它会跳到您不期望的地方、您可以检查它。

    3) 3)由于您要处理计时器、因此请确保所有计时器的中断均已正确处理、这样您就不会卡在计时器中、不过如果是、您应该可以通过第2步了解这一点。

    希望该建议可以帮助您在程序中找到问题。