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.

[参考译文] msp430f5529:有关 USB 数据传输和(GPIO)中断的问题

Guru**** 2567575 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/605702/msp430f5529-question-regarding-usb-data-transfer-and-gpio-interrupts

器件型号:MSP430F5529

您好!

我有以下问题:我使用外部触发信号(~8kHz)通过 SPI 接口获取数据。

当在相应的输入端口上使用中断处理程序时、工作正常。 现在、我要尝试传输

通过 USB 接口传输数据(使用 CCS 附带的 TI CDC 示例代码(C6_SendDataInBackground))。

USB 数据传输工作正常(660kB/s),但是触发输入端口的中断不会定期生成。

我已将代码简化为仅切换中断服务程序中的输出引脚、并且能够观察两个触发信号

示波器上的输出引脚...

我现在的问题是:在不丢失外部触发器的情况下使用 USB 进行数据传输的最佳方法是什么?

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

    您是否从 SPI 中断处理程序调用任何 USB 函数?

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

    克莱明、您好、感谢您的回复!

    不、我只是在那里填充一个缓冲器。

    下面是我的带有简化代码的中断处理程序、它也不能正常工作:

    #pragma vector=port2_vector
    __interrupt void Port_2 (void)
    {
    P2IFG &=(~BIT5);// P2.5 IFG 清零
    GPIO_setOutputHighOnPin (GPIO_PORT_P1、GPIO_PIN2);//默认情况下芯片选择为高电平。
    GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN2);//默认情况下芯片选择为高电平
    。}
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    port2_vector 不适用于 SPI。 您是否在软件中模拟 SPI?

    不管怎样、如果中断处理程序被延迟、那么它很可能是由其他代码导致的、这些代码禁用 GIE 的时间太长。 您的任何代码是否在任何位置禁用 GIE、或者您是否有任何其他中断处理程序?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您是正确的;在与 SPI 接口无关的外部信号上、我将启动 SPI 数据传输;µController 是主器件。 因此、我将在这里使用 port2_vector。
    我将深入探讨自动生成的 CDC 器件代码、以了解这是否会禁用 GIE。 我认为这个代码肯定会使用中断、因为有一个函数"USBCDC_sendDataInBackground"在调用后立即返回...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    以及如何处理 SPI 传输? SPI 中断处理程序有什么作用?

    (但 USB 功能也可能是问题的原因。)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    现在,在我的简化代码中,我根本不使用 SPI,只有 GPIO 来调试错误的原因,所以这里没有用于 SPI 的 ISR ;-)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    但您要发送 USB 数据包吗?

    延迟多长时间?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    延迟是随机的;我将进行一些测量。 下面是该示例的完整代码。 从原始代码(C6_SendDataBackground)中、我刚刚删除了例程等待的部分 
    按键。 此外、我刚刚添加了 InitPorts 例程和 Port2的 ISR。

    /*-版权所有-、BSD *版权所有(c) 2014、德州仪器(TI)公司 *保留所有权利。 * * 只要 符合以下条件*、允许以源代码和二进制形式重新分发和使用: * *源代码的重新分发必须保留上述版权 声明*、此条件列表和以下免责声明。 * ***二进制形式的再发行必须在 *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。 * ***未经 事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。 * *本软件由版权所有者和贡献者"按原样"提供 *、 不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或 *贡献者都不对任何直接、间接、偶然、特殊、 *模范、 或相应的损害(包括但不限于 *采购替代产品或服务;丧失使用、数据或利润; *或业务中断)、但出于任何责任理论 、*无论是在合同中、严格责任还是由于 使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他) 、*即使已获悉可能会发生此类损坏。 *--/copyrights-*/* === main.c ====== *使用 USBCDC_sendDataInBackground Demo 进行高效发送 :* 该示例展示了如何使用 *后台操作实现高效、高带宽发送。 它会提示按任何键、 当*发生这种情况时、应用程序会向主机发送大量数据。 * *------------------------------------------------ + *有关更多详细信息、请参阅示例指南。 ***********************************************************************************************。 */ #include #include "driverlib.h" #include "USB_config/descriptors.h" #include "USB_API/USB_Common/device.h" #include "USB_API/USB_Common/usb.h" //USB 专用函 数#include "USB_API/USB_CDC_API/Usbcdc.h" #include "USB_app/usbConstructs.h" //* 注意:修改 hal.h 以选择特定的评估板并针对 *您自己的板进行定制。 // #include "hal.h" //由事件 易失性 uint8_t bCDCDataReceived 事件设置的全局标志= false;//表示数据已被接收 //不进行打开的 Rx 操作 //应用程序全局变量 uint16_t w; volatile uint16_t ROUNDS = 0; char outString[32]; char pakOutString[16]; #define MEGA 数据长度2046 uint8_t bufferX[MEGA 数据长度]; uint8_t bufferY[MEGA 数据长度] ;uint8_DATA 端口[MEGA 数据长度](void )/片长度(选择) GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN2);//将 P1.2设置为调试输出引脚 GPIO_setOutputHighOnPin (GPIO_PORT_P1、GPIO_PIN2); // //使用 GPIO 中断。 缺点:中断优先级低于 USB 中断... P2IE |= 0x20;//为引脚 P2.5启用 GPOI 中断(外部触发器) P2IES &=~0x20; } #pragma vector=port2_vector __interrupt void Port_2 (void) { P2IFG &=(~BIT5);// P2.5 IFG 清零 GPIO_setOutputHighOnPin (GPIO_PORT_P1、GPIO_PIN2);//调试引脚高电平 GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN2);//调试引脚低 电平} // *=== main ==== */ void main (void) { uint8_t y; WDT_A_HOLD (WDT_A_base);//停止看门狗计时器 // USB API 所需的最小 Vcore 设置为 PMM_CORE_LEVEL_2。 PMM_setVCore (PMM_CORE_LEVEL_2); USBHAL_initPorts(); //配置用于低功耗(输出低电平)的 GPIO USBHAL_initClocks (8000000);//配置时钟。 MCLK=SMCLK=FLL=8MHz;ACLK=REFO =32kHz USB_setup (true、true);// Init USB & events;如果存在主机,则连接 InitPorts(); //用可见的 ASCII 字符(0x21到0x7E)预填充缓冲区 Y = 0x21; 对于(w = 0;w < mega_data_length;w++) { bufferX[w]= y; bufferY[w]= y++; 如果(y > 0x7E){ Y = 0x21; } } __ENABLE_INTERRUPT ();//全局启用中断 while (1) { 开关(USB_getConnectionState()) { //在上枚举您的设备时执行此例 // USB 主机 实例 ST_ENUM_ACTIVE: ////////////////////////////////////////////////////////////////// //持续发送数据 ////////////////////////////////////////////////////////////////////////////////////////// if (USBCDC_sendDataInBackground ((uint8_t*) bufferX、mega_data_length、 CDC0_INTFNUM、0))){ bCDCDataReceived 事件= false; //操作可能仍处于打开状态;取消 USBCDC_ABortSend (&W、CDC0_INTNUM); 中断; } //在这些函数之间,不要修改 bufferX。 但是、 //bufferY 可被修改。 if (USBCDC_sendDataInBackground ((uint8_t*) bufferY、mega_data_length、 CDC0_INTFNUM、0))){ bCDCDataReceived 事件= false; //操作可能仍处于打开状态;取消 USBCDC_ABortSend (&W、CDC0_INTNUM); 中断; } //直到下一次调用 sendData_inBackground(),不要 //修改 bufferY。 但是、bufferX 可以被修改。 如果(舍入++>= 500){ //准备传出字符串 strcpy (outString、 "\r\n 测试已完成。\r\n\r\n); //发送它 if (USBCDC_sendDataInBackground ((uint8_t*) outString、 strlen (outString)、CDC0_INTFNUM、0)){ //操作可能仍处于打开状态;取消 USBCDC_ABortSend (&W、CDC0_INTNUM); 中断; } bCDCDataReceived 事件= false; 舍入= 0; //Reject data from previous keypress、in preparation for //另一个 USBCDC_REProjectData (CDC0_INTFNUM); } //This been in the USB buffer... } 中断; //这些情况在设备断开连接时执行 //主机(意思是,未枚举);已枚举但已暂停 //由主机连接,或连接到没有 USB 主机的有源集线器 //存在。 案例 ST_PHYS_DISCONNECTED: 实例 ST_ENUM_Suspended: 案例 ST_PHYS_Connected: _bis_SR_register (LPM3_bits + GIE); _NOP(); 中断; //默认为瞬时状态执行 // ST_enum_in_progress。 通常、该状态仅持续少数几个状态 //秒。 确保在此状态下不进入 LPM3;USB //此处正在进行通信,因此必须使用模式 //为 LPM0或有源 CPU。 实例 ST_ENUM_IN_PROGRESS: 默认值:; } }//while (1) }//main() /* === UNMI_ISR ==== // #if defined (__TI_Compiler_version__)||(__IAR_systems_ICC__) #pragma vector = UNMI_Vector __interrupt void UNMI_ISR (void) #Elif defined (__GNUC__)&&(__MSP430__) void Compiler_attribute__((interrupt (UNMI_ISR)#vector (void)#UNMI_error! #endif { 开关(__evo_in_range (SYSUNIV、SYSUNIV_BUSIFG)) { 案例 SYSUNIV_NONE: __no_operation(); 中断; SYSUNIV_NMIIFG 案例: __no_operation(); 中断; SYSUNIV_OFIFG 案例: UCS_clearFaultFlag (UCS_XT2OFFG); UCS_clearFaultFlag (UCS_DCOFFG); SFR_clearInterrupt (SFR_oscillator_FAULT_INTERRUPT); 中断; 案例 SYSUNIV_ACCVIFG: __no_operation(); 中断; 案例 SYSUNIV_BUSIFG: //如果 CPU 在 USB 模块的同时访问 USB 内存 //挂起,可能会出现“总线错误”。 这会生成 NMI。 如果 // USB 在您的软件中自动断开连接,请设置 a //在这里断点并查看执行是否成功。 请参阅 //编程人员指南以了解更多信息。 SYSBERRIV = 0;//清除总线错误标志 USB_disable();//Disable } } //released_Version_5_00_01

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

    触发输入信号:1kHz

    在这种情况下、当没有 USB 传输正在进行时(CH1:输出引脚、CH4:触发输入信号 CH2:USB 信号)

    当 USB 传输正在进行时(CH1:输出引脚、CH4:触发输入信号 CH2:USB 信号)、情况就是如此

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这看起来就像您想要检测触发信号的上升沿一样。 就像 GPIO 中断仅在 USB 流量暂停时发生一样。

    请显示您的应用程序的主循环。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    主循环在上面发布3条消息。 在上升沿和中断服务之间存在非常不规则的延迟。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    代码持续轮询 CDC 接口的状态、但这不应阻止中断。

    这看起来好像其中一个函数禁用、但不能正确地重新启用中断。 尝试向主循环(以及 SendInBackground 中的等待循环)添加检查、以查看 GIE 标志是否在某个位置被清除。