主题中讨论的其他器件:ADS8686S、 ADS8686SEVM-PDK、 SysConfig、 C2000WARE
早上好、各位同事、
我不熟悉德州微控制器编程。 我正在使用 TMS320F28388D 的扩展坞对其进行编程。 我想通过 SPI 与 TI ADC 进行通信、特别是 ADS8686S 及其 ADS8686SEVM-PDK 评估板。
该 ADC 允许通过用于 ADCA 的双通道 SDOA 和用于 ADCB 的 SDOB 进行 SPI 通信、但我只想使用1个、因此阅读数据表、SDOB 接地和在 SDOA 中发送两次转换。
我的问题与 SPI 通信本身有关。 我编写了一个代码、基本上要使用这些代码执行一些非常基本的功能:
1.首先、写入 ADC 寄存器以按照我需要的方式对其进行配置(配置、输入电压范围、低通滤波器类型等)。
2.发送它来转换一个通道,让它给我返回转换。
此 ADC 利用 SPI 通信信号(PICO、POCI、SCLK、CS (GPIO 输出))、CONVST (GPIO 输出)、 BUSY (GPIO 输入)以及它们的使用根据 ADC 数据表时序图中显示的内容进行。 我在 SysConfig 的帮助下编写了一个代码(我仍然没有经验)、它会编译代码。 但是、当我连接两个器件并连接信号时、我看到它会卡在这个环路中。
我已经用示波器进行检查、微控制器的 SCLK 输出为0、它不会生成时钟脉冲。 我想知道您是否可以帮助我使用此代码。 基本上、阅读 ADC 数据表、我认为它的工作方式如下:
1.写入 ADC 寄存器:
-在50ns 的小周期内设置为1个转换。
随后,通过将 CS 设置为0来启用 SPI 通信。 清除
- SPI 帧与要配置的寄存器一起发送。
-等待接收一个中断标志进行接收。
-进入中断程序以接收来自 ADC 的消息并清除标志。
- CS 通过设置1停用。
2.读取 ADC 转换:
-在50ns 的小周期内设置为1个转换。
-如果设置为1、则 ADC 会将 BUSY 信号返回为1、直到转换完成。
当 BUSY 返回0时,即转换完成时,通过将 CS 设置为0来启用 SPI 通信。 清除
-等待接收中断标志。
进入中断程序接收 ADC 转换并清除标志。
-通过将 CS 设置为1来禁用 CS。 设置
我将给您留下我完成的代码和 SysConfig、以防您知道为什么时钟信号甚至没有随 ADC 发送、尽管在调试过程中它会滞留在中断标志的 while 部分。
#include "driverlib.h" #include "device.h" #include "board.h" #include "f2838x_device.h" //#include "C:/ti/c2000/C2000Ware_5_00_00_00/device_support/f2838x/headers/include/f2838x_device.h" //#include "F28x_Project.h" //#include "F2838x_PieCtrl.h" // // // #ifdef __cplusplus #pragma DATA_SECTION("SpiaRegsFile") #else #pragma DATA_SECTION(SpiaRegs,"SpiaRegsFile"); #endif volatile struct SPI_REGS SpiaRegs; #ifdef __cplusplus #pragma DATA_SECTION("GpioDataRegsFile") #else #pragma DATA_SECTION(GpioDataRegs,"GpioDataRegsFile"); #endif volatile struct GPIO_DATA_REGS GpioDataRegs; #ifdef __cplusplus #pragma DATA_SECTION("PieVectTableFile") #else #pragma DATA_SECTION(PieVectTable,"PieVectTableFile"); #endif volatile struct PIE_VECT_TABLE PieVectTable; #ifdef __cplusplus #pragma DATA_SECTION("DacaRegsFile") #else #pragma DATA_SECTION(DacaRegs,"DacaRegsFile"); #endif volatile struct DAC_REGS DacaRegs; volatile Uint16 lecturadatoADCdummy; volatile Uint16 flag_conf_noconversion=1; volatile Uint16 lecturaconvADCA; volatile Uint16 lecturaconvADCB; volatile Uint16 comandoADCconf; Uint16 tramaConfADC=((1 << 15) | (0x2 << 9) | (0x0)); //MANDA TRAMA DE CONFIGURACIÓN DONDE SE DEJA A 0 MODO BURST, SEQEN, OSR, STATUSEN, CRCEN Uint16 tramaRango_ADCA_0_3=((1 << 15) | (0x4 << 9) | (0x0)); //PONE EL RANGO DE ADC A DEL CANAL 0 AL 3 EN RANGO +-10V Uint16 tramaRango_ADCA_4_7=((1 << 15) | (0x5 << 9) | (0x0)); //PONE EL RANGO DE ADC A DEL CANAL 4 AL 7 EN RANGO +-10V Uint16 tramaRango_ADCB_0_3=((1 << 15) | (0x6 << 9) | (0x0)); //PONE EL RANGO DE ADC B DEL CANAL 0 AL 3 EN RANGO +-10V Uint16 tramaRango_ADCB_4_7=((1 << 15) | (0x7 << 9) | (0x0)); //PONE EL RANGO DE ADC B DEL CANAL 4 AL 7 EN RANGO +-10V Uint16 tramaFiltroPasoBajo=((1 << 15) | (0xD << 9) | (0x1)); //ESCRIBE FILTRO PASO BAJO DE FRECUENCIA DE CORTE 15kHz | ESCRIBIR 0x0 si se quiere de 39kHz o 0x2 si se quiere de 376kHz Uint16 conv_ADCA_CH0=((1 << 15) | (0x3 << 9) | (0x0)); //TRAMA QUE ESCRIBE EN REGISTRO PARA ACTIVAR CONVERSIÓN DEL CANAL 0 en ADCA y ADCB. Si se quiere cambiar, ver mapa de registros Uint16 conv_SEQ_STACK0=((1 << 15) | (0x20 << 9) | (0x0<<8) | (0x0)); //ESCRITURA DE STACK 0 CON SECUENCIA CHA0,CHB0 siguiendo al siguiente Stack Uint16 conv_SEQ_STACK1=((1 << 15) | (0x21 << 9) | (0x0<<8) | (0x11)); //ESCRITURA DE STACK 1 CON SECUENCIA CHA1,CHB1 siguiendo al siguiente Stack Uint16 conv_SEQ_STACK2=((1 << 15) | (0x22 << 9) | (0x0<<8) | (0x22)); //ESCRITURA DE STACK 2 CON SECUENCIA CHA2,CHB2 siguiendo al siguiente Stack Uint16 conv_SEQ_STACK3=((1 << 15) | (0x23 << 9) | (0x0<<8) | (0x33)); //ESCRITURA DE STACK 3 CON SECUENCIA CHA3,CHB3 siguiendo al siguiente Stack Uint16 conv_SEQ_STACK4=((1 << 15) | (0x24 << 9) | (0x0<<8) | (0x44)); //ESCRITURA DE STACK 4 CON SECUENCIA CHA4,CHB4 siguiendo al siguiente Stack Uint16 conv_SEQ_STACK5=((1 << 15) | (0x25 << 9) | (0x0<<8) | (0x55)); //ESCRITURA DE STACK 5 CON SECUENCIA CHA5,CHB5 siguiendo al siguiente Stack Uint16 conv_SEQ_STACK6=((1 << 15) | (0x26 << 9) | (0x0<<8) | (0x66)); //ESCRITURA DE STACK 6 CON SECUENCIA CHA6,CHB6 siguiendo al siguiente Stack Uint16 conv_SEQ_STACK7=((1 << 15) | (0x26 << 9) | (0x1<<8) | (0x77)); //ESCRITURA DE STACK 7 CON SECUENCIA CHA7,CHB7 Volviendo al Stack 0 si burst mode. Si no, termina secuencia. // SPI_receive16Bits(uint32_t base, SPI_endianess endianness, uint16_t dummyData, uint16_t txDelay); // Main // volatile Uint16 DatoSPI; interrupt void INT_SPIADC_EXT_CHAB_RX_ISR(void); interrupt void INT_SPIADC_EXT_CHAB_TX_ISR(void); void configuracionADC(void); void lecturaconvADC(void); void main(void) { Uint16 comandoADC; // // Initialize device clock and peripherals // Device_init(); // // Disable pin locks and enable internal pull ups. // Device_initGPIO(); // // Initialize PIE and clear PIE registers. Disables CPU interrupts. // Interrupt_initModule(); // // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // Interrupt_initVectorTable(); // // Disable sync(Freeze clock to PWM as well) // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // // Configure GPIO0/1 , GPIO2/3 and GPIO4/5 as ePWM1A/1B, ePWM2A/2B and // ePWM3A/3B pins respectively // Configure EPWM Modules // Board_init(); SPI_enableHighSpeedMode(SPIADC_EXT_CHAB_BASE); // Enable sync and clock to PWM // SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // // Enable ePWM interrupts // // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; // // IDLE loop. Just sit and loop forever (optional): // PieVectTable.SPIA_RX_INT = &INT_SPIADC_EXT_CHAB_RX_ISR; PieVectTable.SPIA_TX_INT = &INT_SPIADC_EXT_CHAB_TX_ISR; /////////////////////////////////////////////REALIZAR CONFIGURACIÓN DEL ADC configuracionADC(); //////////// //ESCRIBIR EN REGISTRO QUE SE QUIERE CONVERTIR CANAL 0 (TRAMA conv_ADCA_CH0) Y APLICAR SEÑAL DE CONVST lecturaconvADC(); while(1){} } void configuracionADC(void){ //ENVIAR CONFIGURACIÓN DE CONFIGURATION REGISTER 0x2 GPIO_writePin(CONVST, 1); //Debe estar CONV high mínimo 50ns -VISTO EN OSCILOSCOPIO QUE HAY UN DELAY DE 480ns si se ponen seguidos los writepin de CONVST // while (GPIO_readPin(BUSY)==1){} //Se espera a que se ponga a 0 BUSY GpioDataRegs.GPACLEAR.bit.GPIO23=1; //CS a 0 se activa. GPIO_writePin(CONVST, 0); comandoADCconf=tramaConfADC; SpiaRegs.SPITXBUF = comandoADCconf; // Master transmite la configuración while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Espera hasta que envíe todos los bits de la trama. //INTERRUPCIÓN DE RECEPCIÓN GpioDataRegs.GPASET.bit.GPIO23=1; //CS a 0 se desactiva. //ENVIAR CONFIGURACIÓN DE RANGO DE CANALES 0-3 DE ADCA GPIO_writePin(CONVST, 1); GpioDataRegs.GPACLEAR.bit.GPIO23=1; //CS a 0 se activa. GPIO_writePin(CONVST, 0); comandoADCconf=tramaRango_ADCA_0_3; SpiaRegs.SPITXBUF = comandoADCconf; // Master transmite la configuración while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Espera hasta que envíe todos los bits de la trama. //INTERRUPCIÓN DE RECEPCIÓN GpioDataRegs.GPASET.bit.GPIO23=1; //CS a 0 se desactiva. //ENVIAR CONFIGURACIÓN DE RANGO DE CANALES 4-7 DE ADCA GPIO_writePin(CONVST, 1); GpioDataRegs.GPACLEAR.bit.GPIO23=1; //CS a 0 se activa. GPIO_writePin(CONVST, 0); comandoADCconf=tramaRango_ADCA_4_7; SpiaRegs.SPITXBUF = comandoADCconf; // Master transmite la configuración while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Espera hasta que envíe todos los bits de la trama. //INTERRUPCIÓN DE RECEPCIÓN GpioDataRegs.GPASET.bit.GPIO23=1; //CS a 0 se desactiva. //ENVIAR CONFIGURACIÓN DE RANGO DE CANALES 0-3 DE ADCB GPIO_writePin(CONVST, 1); GpioDataRegs.GPACLEAR.bit.GPIO23=1; //CS a 0 se activa. GPIO_writePin(CONVST, 0); comandoADCconf=tramaRango_ADCB_0_3; SpiaRegs.SPITXBUF = comandoADCconf; // Master transmite la configuración while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Espera hasta que envíe todos los bits de la trama. //INTERRUPCIÓN DE RECEPCIÓN GpioDataRegs.GPASET.bit.GPIO23=1; //CS a 0 se desactiva. //ENVIAR CONFIGURACIÓN DE RANGO DE CANALES 4-7 DE ADCA GPIO_writePin(CONVST, 1); GpioDataRegs.GPACLEAR.bit.GPIO23=1; //CS a 0 se activa. GPIO_writePin(CONVST, 0); comandoADCconf=tramaRango_ADCB_4_7; SpiaRegs.SPITXBUF = comandoADCconf; // Master transmite la configuración while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Espera hasta que envíe todos los bits de la trama. //INTERRUPCIÓN DE RECEPCIÓN GpioDataRegs.GPASET.bit.GPIO23=1; //CS a 0 se desactiva. //ENVIAR CONFIGURACIÓN DE FILTRO PASO BAJO DE ENTRADA GPIO_writePin(CONVST, 1); GpioDataRegs.GPACLEAR.bit.GPIO23=1; //CS a 0 se activa. GPIO_writePin(CONVST, 0); comandoADCconf=tramaFiltroPasoBajo; SpiaRegs.SPITXBUF = comandoADCconf; // Master transmite la configuración while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Espera hasta que envíe todos los bits de la trama. //INTERRUPCIÓN DE RECEPCIÓN GpioDataRegs.GPASET.bit.GPIO23=1; //CS a 0 se desactiva. flag_conf_noconversion=0; } void lecturaconvADC(void){ //ENVIAR CONFIGURACIÓN DE CONFIGURATION REGISTER 0x2 GPIO_writePin(CONVST, 1); //uso de DEVICE_DELAY_US???? GPIO_writePin(CONVST, 0); //Debe estar CONV high mínimo 50ns -VISTO EN OSCILOSCOPIO QUE HAY UN DELAY DE 480ns si se ponen seguidos los writepin de CONVST while (GPIO_readPin(BUSY)==1){} GpioDataRegs.GPACLEAR.bit.GPIO23=1; //CS a 0 se activa. while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Espera hasta que envíe todos los bits de la trama. //INTERRUPCIÓN DE RECEPCIÓN GpioDataRegs.GPASET.bit.GPIO23=1; //CS a 0 se desactiva. } interrupt void INT_SPIADC_EXT_CHAB_RX_ISR(void){ if (flag_conf_noconversion==1){ SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1; // Clear Overflow flag SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1; // Clear Interrupt flag SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag // FlWaitADC_Ext=0; lecturadatoADCdummy = SpiaRegs.SPIRXBUF; // Read data y resetea flag INT_FLAG } else{ SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1; // Clear Overflow flag SpiaRegs.SPIFFTX.bit.TXFFINTCLR=1; // Clear Interrupt flag SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag // FlWaitADC_Ext=0; lecturaconvADCA = SpiaRegs.SPIRXBUF; // Read data y resetea flag INT_FLAG // DAC_setShadowValue(, lecturaconvADCA); } // PieCtrlRegs.PIEACK.all |= PIEACK_GROUP6; // Issue PIE ack } interrupt void INT_SPIADC_EXT_CHAB_TX_ISR(void){ SpiaRegs.SPIFFTX.bit.TXFFINTCLR = 1; // Clear Interrupt flag // PieCtrlRegs.PIEACK.all |= PIEACK_GROUP6; // Issue PIE ACK }
我也对高速模式有疑问、以及我可以从哪里在 SysConfig 中配置该选项、根据微控制器的数据表、您可以达到50MHz 速度、但我在 SysConfig 中看不到该选项。 我要做的是根据微控制器的数据表选择数据速度的 PICO、POCI、SCLK 的 GPIO 引脚、但不会应用"SPICCR.HS_MODE = 1"。 如果我选择一个12.5MHz 的比特率,程序运行到 while 循环,而如果我把它设置为50MHz ,我在 SPI_Init ()中得到一个错误。
因此、基本而言、我想指出以下几点: 是否有人可以帮助我创建一个可以在板上运行的代码以实现此相对简单的功能、为什么会出现这些错误、以及是否有人可以帮助我实施高速模式、无论是通过 SysConfig 还是 SysConfig 都可以实现 我想知道如何实现高速模式。
我也让您使用 SysConfig 操作系统工程的 zip 文件。 如果您能帮助我,我将不胜感激。 很抱歉可能有些愚蠢的问题。 提前感谢您。
Br、
佩德罗
e2e.ti.com/.../PRUEBA_5F00_SPI_5F00_ADC_5F00_F28388D.zip
在 SPI 中从 ADC 接收串行1线数据
在 SPI 中串行寄存器写入 ADC