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.
您好!
我正在尝试切换 GPIO 引脚、它看起来非常慢。
我的微控制器主时钟为120MHz。
我删除了中间延迟、但仍然非常慢。
下面是我的时钟的配置方式。 我已通过读取 uint32_t sys_clock 来验证时钟是否为120MHz。
//将系统时钟初始化为120MHz // uint32_t sys_clock; SYS_CLOCK = ROM_SysCtlClockFreqSet ( (SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480)、 System_clock); assert (sys_clock == system_clock);
以及用于切换引脚的代码;
void adc_conv_start (void) { GPIOPinWrite (ADC_CTRL1_PORT、ADC_CNVSTARTA |ADC_CNVSTARTB、0); //for (i=0;i<1;i++){} //SysCtlDelay (1); GPIOPinWrite (ADC_CTRL1_PORT、ADC_CNVSTARTA | ADC_CNVSTARTB、ADC_CNVSTARTA | ADC_CNVSTARTB); }
这里是示波器的快照、显示延迟为3.9微秒。
您好、Sahil、
我同意速度相当慢、您是否有任何可能占用 MCU 的中断或其他进程在运行?
您是否可以尝试将时钟设置 API 与我们的闪烁项目一起使用,删除 main()中的延迟环路,并报告您在那里看到的结果? 如果我们看到在这种情况下进行较高速度的切换、这将表示从 GPIO 触发某项操作并导致延迟。 您可能需要将引脚从 N0更改为易于访问的内容、如进行此测试的 N2。
如您所建议。 我尝试了闪烁项目、它工作正常、因为在120MHz 时钟下、需要156nsec 来切换 LED、而在将 LED 设置为高电平和低电平之间没有任何延迟环路。 我尝试了用于切换目的的端口 M、并且端口 M 也在156nsec 切换。 这听起来不错。
这是快照;
但是、由于没有中断将处理器拉出、我仍然看不到我的项目有任何问题。
由于工程是独立的、这意味着所有库都位于工程文件夹中、不需要调整编译器包含路径或任何其他工作。 它只是包含和运行某种项目。 我在这里作为压缩文件附加。
您好!
我已通过将代码缩减为更短的程序来进一步简化代码。 仍然不幸运。 我非常怀疑它与 FreeRTOS 有关系。
这是整个代码;
#include #include #include "main.h" #include "drivers/pinout.h" #include "utils/uartstdio.h" // TivaWare 包含 #include "driverlib/sysctl.h" #include "driverlib/debug.h" #include "driverlib/rom.h" #include "driverlib/rom_decute.h 命令#include "driverlib#define rtos"#define rtos void #define #include "driverlib/rtos"#defconfig #define #define #task#define #define #define rtos #include "#define #tog.000task#define #include "#include "driverlib_rtos" //主函数 int main (void) { //将系统时钟初始化为120 MHz uint32_t output_clock_rate_Hz; output_clock_rate _Hz = ROM_SysCtlClockFreqSet ( (SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480)、 System_clock); assert (output_clock_rate _Hz = system_clock); //初始化 Launchpad 的 GPIO 引脚 PinoutSet (false、false); ROM_GPIOPinTypeGPIOOutput (GPIO_PORTM_BASE、GPIO_PIN_4 | GPIO_PIN_5); GPIOPadConfigSet (GPIO_PORTM_BASE、GPIO_PIN_4 | GPIO_PIN_5、GPIO_Strength _2mA、GPIO_PIN_TYPE_STD); //创建演示任务 xTaskCreate (demLEDTask、(const portCHAR *)"LED"、 configMINIMAL_STACK_SIZE、NULL、2、NULL); xTaskCreate (demSerialTask、(const portCHAR *)"Serial"、 configMINIMAL_STACK_SIZE、NULL、1、NULL); vTaskStartScheduler(); 返回0; } //刷写 launchpad 上的 LED void demoLEDTask (void *pvParameters) { 对于(;) { GPIOPinWrite (GPIO_PORTM_BASE、GPIO_PIN_4 |GPIO_PIN_5、0); //for (i=0;i<1;i++){} //SysCtlDelay (1); GPIOPinWrite (GPIO_PORTM_BASE、GPIO_PIN_4 | GPIO_PIN_5、GPIO_PIN_4 | GPIO_PIN_5); // //打开 LED 1 // LEDWrite (0x0F、0x01); // vTaskDelay (100); // //打开 LED 2 // LEDWrite (0x0F、0x02); // vTaskDelay (100); // //打开 LED 3 // LEDWrite (0x0F、0x04); // vTaskDelay (100); // //打开 LED 4 // LEDWrite (0x0F、0x08); // vTaskDelay (100); } } //通过 Stellaris 调试接口 UART 端口编写文本 void SerialdemTask (void *pvParameters) { //设置连接到虚拟 COM 端口的 UART UARTStdioConfig (0、57600、system_clock); 对于(;) { UARTprintf ("\r\nHello、World from FreeRTOS 9.0!"); vTaskDelay (5000 / portTIK_PERIOD_MS); } } /* assert() Error 函数 * 来自 driverlib/debug.h 的 failed assert()在该函数中执行 */ void __error__(char *pcFilename,uint32_t ui32Line) { //在此处放置一个断点以捕获错误,直到日志记录例程完成 while (1) { } }
有任何提示吗?
我通过注释掉大部分代码来缩小问题范围。 我已经注释掉了所有 FreeRTOS 包括的内容。 我甚至禁用 了运行 FreeRTOS 调度程序的 port.c 中的 SysTick 计时器、并且还对该调度程序进行了注释。 通过这种方法、我完全隔离了 FreeRTOS 部件。
我只需在代码中看到一个 while (1)循环。 现在、我的代码非常短、但问题仍然存在。
它表示代码末尾带有 void __error__(char *pcFilename、uint32_t ui32Line)函数的某些内容。
但是、当我尝试注释掉此函数时、编译器会给出以下错误。
但是、如果我不注释掉上述函数。 它在编译时没有任何错误、并产生3.125usec 的缓慢延迟。 此外、我的项目包含所有 c 文件以及包含.h 文件的文件、并且不需要在链接器路径中包含 driverlib.lib。
这是注释掉所有 FreeRTOS 内容后的代码。 此消息随附了同一项目。
#include #include void include "main.h" #include "drivers/pinout.h" #include "utils/uartstdio.h" // TivaWare 包含 #include "driverlib/sysctl.h" //#include "driverlib/debug.h" #include "driverlib/rom_demo.h"/#include "task/freepdt/#include "out/void trabout.trabout/#tog/#def/#t/#def_trabout/#tog/#def_trl.statement/#include "#t/#def_trates/#definc/trates#def_true/#tog./#def_true/#tog./#include "#definc/#def_true/#tage/#tog./#definc/#defintrue/#tog/#tage/#def_statement/#tes#def/#def_trines#tes#tes#tage/ uint32_t i; I = 0; //将系统时钟初始化为120 MHz uint32_t output_clock_rate_Hz; output_clock_rate _Hz = ROM_SysCtlClockFreqSet ( (SYSCTL_XTAL_25MHz | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480)、 System_clock); //assert (output_clock_rate _Hz = system_clock); //初始化 Launchpad 的 GPIO 引脚 //PinoutSet (false、false); ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOM); ROM_GPIOPinTypeGPIOOutput (GPIO_PORTM_BASE、GPIO_PIN_4 | GPIO_PIN_5); //GPIOPadConfigSet (GPIO_PORTM_BASE、GPIO_PIN_4 | GPIO_PIN_5、GPIO_Strength _2mA、GPIO_PIN_TYPE_STD); //创建演示任务 // xTaskCreate (demLEDTask、(const portCHAR *)"LEDs"、configMINIMAL_STACK_SIZE、NULL、2、 空); // // xTaskCreate (demSerialTask、(const portCHAR *)"Serial"、configMINIMAL_STACK_SIZE、NULL、 1、NULL); while (1) { GPIOPinWrite (GPIO_PORTM_BASE、GPIO_PIN_4 |GPIO_PIN_5、0); //for (i=0;i<2;i++){} //SysCtlDelay(); GPIOPinWrite (GPIO_PORTM_BASE、GPIO_PIN_4 | GPIO_PIN_5、GPIO_PIN_4 | GPIO_PIN_5); } //vTaskStartScheduler(); 返回0; } //刷写 launchpad 上的 LED //void demLEDTask (void *pvParameters) //(; )// //{ ////// GPIOPinWrite (GPIO_PORTM_BASE、GPIO_PIN_4 |GPIO_PIN_5、0); // //for (i=0;i<1;i++){} // //SysCtlDelay (1); // GPIOPinWrite (GPIO_PORTM_BASE、GPIO_PIN_4 | GPIO_PIN_5、GPIO_PIN_4 | GPIO_PIN_5); // //打开 LED 1 // LEDWrite (0x0F、0x01); // vTaskDelay (100); // //打开 LED 2 // LEDWrite (0x0F、0x02); // vTaskDelay (100); // //打开 LED 3 // LEDWrite (0x0F、0x04); // vTaskDelay (100); // //打开 LED 4 // LEDWrite (0x0F、0x08); // vTaskDelay (100); //} // 通过 Stellaris 调试接口 UART 端口写入文本 // void SerialTask (void *pvParameters) //{ // ////////////设置连接到虚拟 COM 端口的 UART // UARTStdioConfig (0、57600、system_clock); // // (针对 //) UARTprintf ("\r\nHello、World from FreeRTOS 9.0!"); // vTaskDelay (5000 / portTIK_PERIOD_MS); //} //} //* assert() Error 函数 * 从 driverlib/debug.h 中执行失败的断言()在此函数中 */ void __error_(* pcchar、uint32_t ui32Line) { //在此处放置一个断点以捕获错误,直到日志记录例程完成 while (1) { } }
您好!
[引用 USER="Sahil]void adc_conv_start (void)
{
GPIOPinWrite (ADC_CTRL1_PORT、ADC_CNVSTARTA |ADC_CNVSTARTB、0);
//for (i=0;i<1;i++){}
//SysCtlDelay (1);
GPIOPinWrite (ADC_CTRL1_PORT、ADC_CNVSTARTA | ADC_CNVSTARTB、ADC_CNVSTARTA | ADC_CNVSTARTB);
}[/报价]
可能会尝试切换函数的静态 void? 很明显、它被切换之间的另一个调用中断、或者操作系统任务处理程序计时器的运行速度低于 GPIO 切换速率。 请注意、从 非按位和 "((~LED)& 0x10)"切换 LED 可能会产生意外结果。 和按位非"&(~pin)"应 用于反转位、但 CCS 编译器似乎从未 按预期反转引脚。 GPIOPinWrite()在使用 kiss 方法时效果更好,只使用十六进制值,不 按位,不使用 OR,并添加到语法中。
您好、Ralph、
是的、我正在考虑将我的部分引脚移植到芯片的 PWM 引脚。 尤其是在外部连接的 ADC 启动 ADC 转换时所需的时间。
在处理该问题时、我注意到以下两件事、只是想理解;
GPIO 切换的部分改进来自于优化部分下的速度与尺寸折衷设置。 如下文所示。 我的问题是这在技术上意味着什么以及它是如何工作的? 已附加快照。
2.我注意到切换脉冲的间隔不均匀,如下图所示。 由于这两个寄存器都由同一指令驱动,所以写入寄存器的值与不均匀间隔的值是什么不同的? 附加的快照
GPIOPinWrite (ADC_CTRL2_PORT、ADC_CS | ADC_READ、0); // GPIOPinWrite (ADC_CTRL2_PORT、ADC_CS | ADC_READ、ADC_CS | ADC_READ);
谢谢
您好、Sahil、
[引用 user="Sahil]1. GPIO 切换的部分改进来自于优化部分下的速度与尺寸折衷设置。 如下文所示。 我的问题是这在技术上意味着什么以及它是如何工作的? 已附加快照。[/quot]
它与编译器如何实际分解 C 代码并将其转换为 MCU 的程序代码有关。 从较高层次的角度来看、我将描述 优化速度、因为编译器会尝试尽可能地缩短指令执行时间、但代价是在需要时通过重复代码来使用更多空间、以便更快地访问指令。 相反、优化大小使编译器尝试尽可能多地重用代码、但代价是扩展操作会导致某些代码块的访问时间增加、因为需要处理的附加指令会增加执行时间。
[引用 user="Sahil]2. 我注意到切换脉冲的间隔不均匀、如下图所示。 由于这两个寄存器都由同一指令驱动,所以写入寄存器的值与不均匀间隔的值是什么不同的? 附加的快照[/报价]
我最初的反应是、该工具的数字部分由于其采样方式可能显示拉伸周期、我在自己的 LSA 上看到了很多(尽管它的功能肯定不如您的示波器那样强大)。 您是否检查了示波器功能的模拟部分上的波形、以查看它们是否与数字部分上显示的波形完全一致?