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**** 2610085 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/763416/tm4c123gh6pm-tm4c123gh6pm-systic-reload-value-issue

器件型号:TM4C123GH6PM

我已经编写了一个代码、以5秒的间隔生成100ms 的脉冲、如果我在 Systic 计时器中加载100ms 的值不会产生正确的结果、但如果我在加载寄存器中插入50的值、则会生成精确的脉冲。据我所知、在以80MHz 的 systic 工作时、 我们可以 每200ms 获得一次中断(最大计数时,计时器每200ms 溢出一次)。当100被放入此命令时(ROM_SysTickPeriodSet (SysCtlClockGet ()*100/1000);),我无法获得正确的值,但如果我放置50,我得到的结果是50ms 脉冲。 以下是代码。

/*************
这是用于监控 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 "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
//#include "utils/uartstdio.c"
//void PWMint();
#include
//#include "strfunc.h"
#include "inc/hw_ints.h"
#include "inc/hw_timer.h"
#include "inc/hw_gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.c"
#include "driverlib/sysctl.h"
#include "driverlib/Timer.c"
#include "driverlib/Timer.h"
#include "driverlib/gpio.c"
#include "driverlib/gpio.h"
#include "adafruitUltimateGPS.h"
#include
#include "UART.h"
//#include "SysTickInts.h"
//#include "pll.h"

bool isDeviceIDSyncPrepTime (char* currTimeString、uint8_t currDeviceID);

bool PPSInterruptOccaled=false;//bool 变量、用于存储重新同步请求后是否发生 pps 中断
bool ResyncTimeout=false;//flag、用于说明是否发生了与 PPS 重新同步的超时
bool PPSTimerEnabled=false;//flag、用于存储是否启用 PPS 计时器
uint32_t lastSyncWithPPS = 0;//变量用于存储上次与 PPS 重新同步后经过的时间
int programState=0;//
const uint8_t device_id=1;//设备 ID
int i=0;
int T_count=0;
int ResyncTime=720+1;
uint32_t g_ui32Flags;

//
//
//驱动程序库遇到错误时调用的错误例程。
//
//


//
//
//配置 UART 及其引脚。 这必须在 UARTprintf()之前调用。
//
//
无效
配置 UART (空)

//
//启用用于 UART0引脚的 GPIO 端口 A。
// TODO:将其更改为您正在使用的 GPIO 端口。
//
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);

//
//为端口 A0和 A1上的 UART0功能配置引脚复用。
//如果您的器件不支持引脚复用、则无需执行此步骤。
// TODO:更改此选项以选择您正在使用的端口/引脚。
//
GPIOPinConfigure (GPIO_PA0_U0RX);
GPIOPinConfigure (GPIO_PA1_U0TX);

//
//启用 UART0以便我们可以配置时钟。
//
SysCtlPeripheralEnable (SYSCTL_Periph_UART0);

//
//使用内部16MHz 振荡器作为 UART 时钟源。
//
UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC);

//
//为这些引脚选择替代(UART)功能。
// TODO:更改此选项以选择您正在使用的端口/引脚。
//
GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);

//
//初始化控制台 I/O 的 UART
//
UARTStdioConfig (0、115200、16000000);


void configPiStatusGPIO()

ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
//LED
GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2);
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0x00);

int 计数器、i、j=0;

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_SysTickPeriodSet (SysCtlClockGet ()*100/1000);// 1ms 周期

ROM_IntMasterEnable();
ROM_SysTickIntEnable();

void synsynsynsWithGPSPPS()

UARTprintf ("正在等待来自 GPS\r\n 的 PPS);
GPIOIntClear (GPIO_PORTC_BASE、GPIO_INT_PIN_6);//清除中断
ROM_IntEnable (INT_GPIOC);
GPIOIntEnable (GPIO_PORTC_BASE、GPIO_PIN_6);//启用中断


空 PPSGPIOInterrupt()

GPIOIntClear (GPIO_PORTC_BASE、GPIO_INT_PIN_6);//清除中断


ROM_SysTickPeriodSet (SysCtlClockGet ()*100/1000);//如果我在这里放置100,我不会得到正确的时间周期,我会得到44ms 的时间周期

ROM_IntMasterEnable();
ROM_SysTickIntEnable();
ROM_SysTickEnable();
UARTprintf ("\r\nShifting to State 2");
programState = 2;
计数器=0;
T_count=0;
ROM_IntDisable (INT_GPIOC);
GPIOIntDisable (GPIO_PORTC_BASE、GPIO_PIN_6);//禁用中断
//lastSyncWithPPS = 0;
UARTprintf ("PPS 已发生且控制器已同步\r\n);

空 TickHandler()

// if (counter>1){
GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、0x00);
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0x00);
//}
计数器=计数器+1;
if (counter=100){



GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、0xFF);
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0xFF);
计数器=0;
T_count=T_count+1;
UARTprintf ("高脉冲=%i\n"、T_count);

int main (空)


SysCtlClockSet (SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHz|SYSCTL_OSC_MAIN);
ROM_FPULazyStackingEnable();


//configWatchdog();//initialize watchdog -要进行测试,请将其注释
ConfigureUART();//初始化应用程序使用的 UART
//UART_Init();
initgps();
initStreamer();
UARTprintf ("initialized\r\n");
//
configPiStatusGPIO();
//configPiStatusTimer();
configPPSGPIO();
configPPSTIME();


ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
ROM_GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_1_GPIO_PIN_2|GPIO_PIN_3);// PF1-3作为输出


programState=1;
while (1)

//UARTprintf ("d");

switch (programState)

情况0:

if (isGPSSentenceComplete())

UARTprintf ("\r\nShifting to State 1");
GPSGetData();
if (isGPSDataUpdated())

UARTprintf ("\r\nShifting to State 1");
if (isDeviceIDSyncPrepTime ((char*) GPSData->time、device_id)=true)


UARTprintf (GPSData->Time);
UARTprintf ("\r\n");
UARTprintf ("\r\nShifting to State 1");
programState = 1;
UARTprintf ("\r\n");



中断;


案例1:


syncGPSPPS();


中断;

案例2:

if (T_count=ResyncTime){
UARTprintf ("Resynctimeout=true");
ROM_SysTickDisable();
programState = 1;


中断;

默认值:

UARTprintf ("卡在错误的程序状态...\r\n 重置为状态0...");
programState = 0;





bool isDeviceIDSyncPrepTime (char* currTimeString、uint8_t currDeviceID)

char d_id[4];
strcpy (d_id、"1.000");
UARTprintf ("\r\nDevice ID:");
UARTprintf (d_id);
UARTprintf ("\r\nDevice Time:");
UARTprintf (&currTimeString[5]);




if (strncmp (&currTimeString[5]、"1.000"、3)=0 || strncmp (&currTimeString[5]、"6.000"、3)=0){
UARTprintf ("\r\n 触发时间:");
UARTprintf (&currTimeString[5]);
返回 true;

否则{
返回 false;

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    SysCtlClockGet ()返回处理器时钟的时钟速率。 如果您启用 PLL、SysCtlClockGet 将返回8000000、即80MHz。 SysCtlClockGet 在一秒内不返回周期数。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    ROM_SysTickPeriodSet (SysCtlClockGet ()*100/1000);//如果我在这里放置100,我不会得到正确的时间周期,我会得到44ms 的时间周期
    该命令不会每100ms 产生一次中断,该命令可以精确地为等于或小于50的任何值生成中断。超过50时,我只查看了100个值。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是否可以尝试 SysTickPeriodSet(((int)SysCtlClockGet ()*100/1000);而不是?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    我没有听到你的反馈。 我将假定问题已解决。 我现在要关闭这个线程。 如果您仍有问题、您可以重新打开此主题或打开新主题以解决新问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉,我的回复很晚,我被其他一些东西震惊了。现在我得到的周期是200ms。它真的很奇怪。我应该每100ms 有一个超时。更多的是使用 ROM_SysTickPeriodSet(SysCtlClockGet()*50/1000);提供了很高的精确度,产生50ms 超时。 另一方面、在您的 ROM_SysTickPeriodSet((((int)SysCtlClockGet ()*100/1000);无论我放置100还是50、都会给出200 ms。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果您得到的"周期"为200ms、则意味着中断是在100ms 时生成的、不是? 我假设您尝试切换 ISR 内部的 LED。 为什么不尝试在 ISR 中切换 GPIO 引脚并在示波器中捕获信号? 测量信号的低相位和高相位、查看它们是否为100ms 宽。 如果是、那么您将在100ms 时生成中断。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    否这意味着每200ms 生成一次中断。 我正在使用示波器观察波形。当 GPIO 引脚 PC6发生中断时、代码的工作方式与此类似、Systic 计时器被激活并加载值100ms。 当 systic 计时器首次溢出 PC7时、PC7变为高电平、然后 在下一次溢出中、它被设为低电平、程序保持低电平、直到50次溢出、因为我希望每5秒产生100ms 的高电平脉冲。因此、在每50次溢出后、计时器将被设为高电平、然后在下一次溢出后变为低电平。
    我的算法在小于或等于50ms 的时间段内提供了正确的结果、但一旦我加载100ms 或更高的值问题发生、就好像在 systic 中无法加载100ms 或更高的值。我认为100ms 的重新加载值大于 systic 寄存器的大小、 尽管这与数据表的说明相反。根据数据表、在80MHz 频率和24位 sysic 寄存器的情况下、我可以每207ms 获得一次中断。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、让我知道这是不是正确的理解。 PC7上的周期实际上是5秒。 PC7上的高电平相位为100ms、而低电平相位为 (5s - 100ms)、为4.9s。  如果您尝试加载值为4.9的计数器、那么它肯定会使24位计数器溢出。 但我想您尝试计数50个溢出、每个溢出等于100ms、这应该为您提供5s。 在代码中的某个位置、您可能加载的值大于24位计时器可以执行的值。 查看 CCS 寄存器窗口中的 NVIC_ST_RELOAD 寄存器、查看您预加载的24位定时器的值是否大于24位可以保持的值。

    对于您的应用、我认为使用 GPtimer 而不是 SysTick 可能更容易。 GPtimer 是32位的、您甚至可以将其中的两个连接在一起以形成一个64位计时器。

    简单

    #include 
    #include 
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    
    
    
    
    
    
    
    #include "driverlib/rom.h"#include "driverlib/sctl.h"#include "driverlib/symdio.us
    //
    //! \addtogroup SysTK_examples_list
    //! 

    SysTick 中断(SysTick _int)

    //! //! 此示例展示了如何配置 SysTick 和 SysTick 中断。 //! //! 此示例使用以下外设和 I/O 信号。 您必须 //! 查看这些内容并根据您自己的董事会需要进行更改: //! -无 //! //! 以下 UART 信号仅配置为显示控制台 //! 消息。 操作 //! SysTick。 //! - UART0外设 //! - GPIO 端口 A 外设(用于 UART0引脚) //! - UART0RX - PA0 //! - UART0TX - PA1 //! //! 此示例使用以下中断处理程序。 要使用此示例 //! 在您自己的应用程序中、您必须将这些中断处理程序添加到 您的//! 矢量表。 //! -SysTickIntHandler // //************* // // //计数器来计算已调用的中断数。 //// ***************** 易失性 uint32_t g_ui32Counter = 0; //********* // //此函数将 UART0设置为用于控制台,以便 在示例运行时显示信息//。 //// ***************** void InitConsole (void) { // //启用用于 UART0引脚的 GPIO 端口 A。 // TODO:将其更改为您正在使用的 GPIO 端口。 // SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA); // //为端口 A0和 A1上的 UART0功能配置引脚复用。 //如果您的器件不支持引脚复用、则无需执行此步骤。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinConfigure (GPIO_PA0_U0RX); GPIOPinConfigure (GPIO_PA1_U0TX); // //启用 UART0以便我们可以配置时钟。 // SysCtlPeripheralEnable (SYSCTL_Periph_UART0); // //使用内部16MHz 振荡器作为 UART 时钟源。 // UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC); // //为这些引脚选择替代(UART)功能。 // TODO:更改此选项以选择您正在使用的端口/引脚。 // GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1); // //初始化控制台 I/O 的 UART // UARTStdioConfig (0、115200、16000000); } //********* // // SysTick 中断的中断处理程序。 //// ***************** void SysTickIntHandler (void) { // //更新 SysTick 中断计数器。 // G_ui32Counter++; 如果((g_ui32Counter % 2)= 0){ GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、GPIO_PIN_2); } 否则{ GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0); } } uint32_t i=0; int period_width=0; //********* // //将 SysTick 和 SysTick 中断的周期配置为1秒。 //// ***************** int main (void) { #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) uint32_t ui32SysClock; #endif uint32_t ui32PrevCount = 0; // //将时钟设置为直接从外部晶振/振荡器运行。 // TODO:必须更改 SYSCTL_XTAL_VALUE 以匹配的值 板上的//晶体。 // #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) ui32SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_OSC)、25000000); #else //SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | // SYSCTL_XTAL_16MHz); SysCtlClockSet (SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHz|SYSCTL_OSC_MAIN); #endif // //启用用于板载 LED 的 GPIO 端口。 // ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF); // //为 LED 启用 GPIO 引脚(PF2 & PF3)。 // ROM_GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2); // //设置用于显示消息的串行控制台。 这是 //仅用于此示例程序,SysTick 操作不需要。 // InitConsole(); // //在控制台上显示设置。 // UARTprintf ("SysTick 触发中断->"); UARTprintf ("\n 速率= 0.1sec\n"); // //初始化中断计数器。 // G_ui32Counter = 0; I = SysCtlClockGet (); // //设置 SysTick 计时器的周期。 SysTick 计时器周期 //等于系统时钟,产生1秒的周期。 // #if defined (target_IS_TM4C129_RA0)|| \ 已定义(TARGET_IS_TM4C129_RA1)|| \ 已定义(TARGET_IS_TM4C129_RA2) SysTickPeriodSet (ui32SysClock); #else SysTickPeriodSet ((int)SysCtlClockGet ()*100/1000); #endif // //启用到处理器的中断。 // IntMasterEnable(); // //启用 SysTick 中断。 // SysTickIntEnable(); // //启用 SysTick。 // SysTickEnable(); // //在 SysTick 运行时永久循环。 // while (1) { // //检查 SysTick 中断计数是否发生更改,如果发生更改 //打印带有计数的消息。 // if (ui32PrevCount!= g_ui32Counter) { // //打印中断计数器。 // UARTprintf ("中断数:%d\r"、g_ui32Counter); ui32PrevCount = g_ui32Counter; } }

    代码仅用于演示在100ms 时生成中断。 您可以观察示波器上的 PF2引脚并进行测量。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    您的问题是否已解决?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我使用了通用定时器、它们产生了正确的结果、通过它们、我可以生成更长的中断。