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.

[参考译文] RTOS/EK-TM4C123GXL:SPI 和 I2C 任务集成失败

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/777684/rtos-ek-tm4c123gxl-spi-and-i2c-task-integration-failed

器件型号:EK-TM4C123GXL

工具/软件:TI-RTOS

尊敬的团队:

 我有两个任务、一个是 I2C 事务、另一个是 SPI 事务。 当我禁用 SPI 任务 I2C 任务顺利运行时、事务 从传感器读取数据。 即使我启用 SPI 任务, I2C 任务也能正常工作。 但是、当我将 MISO 和 MOSI 线路连接到微控制器时。 I2C 事务将发生错误的 I2C 传输。  

简写:当我将 MISO 和 MOSI 线路连接到微控制器并启用 SPI 任务时。  执行 I2C 任务、从而生成 system_abort。

请提供您宝贵的建议、说明我在连接中出错的地方。

以下是每个模块的代码片段:

I2C 引脚配置:

GPIOPinTypeGPIOInput (GPIO_PORTB_BASE、GPIO_PIN_3);
GPIOPinTypeGPIOOutput (GPIO_PORTB_BASE、GPIO_PIN_2);
while (GPIOPinRead (GPIO_PORTB_BASE、GPIO_PIN_3)!= GPIO_PIN_3)
{
GPIOPinWrite (GPIO_PORTB_BASE、GPIO_PIN_2、0);
GPIOPinWrite (GPIO_PORTB_BASE、GPIO_PIN_2、GPIO_PIN_2);
}

//为 PB2配置 GPIO 引脚多路复用器- I2C0SCL

GPIOPinConfigure (GPIO_PB2_I2C0SCL);
GPIOPinTypeI2CSCL (GPIO_PORTB_BASE、GPIO_PIN_2);

//为 PB3配置 GPIO 引脚多路复用器- I2C0SDA

GPIOPinConfigure (GPIO_PB3_I2C0SDA);
GPIOPinTypeI2C (GPIO_PORTB_BASE、GPIO_PIN_3); 

I2C 通道开口:

// I2C 通道0打开

I2C_Params_init (&signal.i2c0Params);
signal.i2c0Params.bitrate = I2C_100kHz;
signal.i2c0 = I2C_open (I2C_IMU_left_dagonals、&signal.i2c0Params);
if (signal.i2c0 ==空)
{
System_abort ("初始化 I2C 通道时出错0\n");
}
其他
{
System_printf ("I2C 通道0已初始化!\n");

} 
#define I2C_IMU_left_diagonals I2C0_IMU_LEFT_DIAONals 

CONST I2CTIVA_HWAttrs i2cTivaHWAttrs[I2CCOUNT ={
{
baseAddr = I2C0_BASE、
.intNum = INT_I2C0、
.intPriority =(~0)
}、
{
baseAddr = I2C1_base、
.intNum = INT_I2C1、
.intPriority =(~0)
}

};

const I2C_Config I2C_config[]={
{
fxnTablePtr =&I2CTiva_fxnTable、
.object =&i2cTivaObjects[0]、
hwAttrs =&i2cTivaHWAttrs[0]
}、
{
fxnTablePtr =&I2CTiva_fxnTable、
.object =&i2cTivaObjects[1]、
hwAttrs =&i2cTivaHWAttrs[1]
}、
{NULL、NULL、NULL}

}; 

WriteRegister 代码:

void csupport:::i2c_writeRegister (I2C_Handle handle、unsigned char slaveAddr、uint16_t regAddr、uint32_t value、I2C_transfer_type transferType)
{

I2C_Handle i2cChannel1;
I2C_Params currI2cParams;

uint8_t txBuffer[4];
I2C_Transaction i2c 交易;

i2cTransaction.slaveAddress = slaveAddr;
i2cTransaction.writeBuf = txBuffer;

开关(传输类型)
{
案例 IMU_TRANSACTION:
//写入8位状态寄存器
i2cTransaction.writeCount = 2;
i2cTransaction.ReadCount = 0;

txBuffer[0]= regAddr & 0xFF;//lb Addr
TxBuffer[1]=值和0xFF;
中断;
案例 CURRENT_TRANSACTION:

i2cTransaction.writeCount = 3;
i2cTransaction.ReadCount = 0;

txBuffer[0]= regAddr & 0xFF;// 8位地址
txBuffer[1]=值>> 8;// HB 地址
txBuffer[2]=值和0xFF;// lb Addr
中断;

默认值:

//写入16位状态寄存器
i2cTransaction.writeCount = 4;
i2cTransaction.ReadCount = 0;

txBuffer[0]=(regAddr >> 8)& 0xFF;//HB Addr
txBuffer[1]= regAddr & 0xFF;//lb Addr
TxBuffer[2]=值& 0xFF;
txBuffer[3]=(值>> 8)& 0xFF;
中断;

}

if (!I2C_transfer (handle、&i2cTransaction)){
/*GPIO_write (Board_LED_RED、Board_LED_ON);*/
system_abort (" I2C 传输错误!");
}
} 

读取寄存器:

/*
此函数用于8位和16位寄存器的 I2C 事务中的读取操作
*需要提及传输类型
* IMU_事务 - 8位
* CURRENT_TRANSACTION - 16位
*/

void csupport::i2c_readRegister (I2C_Handle handle、unsigned char slaveAddr、
uint8_t regAddr、uint16_t *数据、size_t length、
I2C_TRANSFER_TYPE TRANSAGEType)
{
uint8_t txBuffer[2];
I2C_Transaction i2c 交易;

i2cTransaction.slaveAddress = slaveAddr;
i2cTransaction.writeBuf = txBuffer;
i2cTransaction.readBuf =数据;
i2cTransaction.ReadCount =长度;


开关(传输类型)
{
案例 IMU_TRANSACTION:
//写入8位状态寄存器
i2cTransaction.writeCount = 1;
txBuffer[0]= regAddr & 0xFF;//lb Addr
中断;
案例 CURRENT_TRANSACTION:
i2cTransaction.writeCount = 1;
txBuffer[0]= regAddr & 0xFF;// 8位地址
中断;
默认值:// 16位地址
i2cTransaction.writeCount = 2;
txBuffer[0]= regAddr >> 8;//HB Addr
txBuffer[1]= regAddr & 0xFF;//lb Addr
中断;

}
if (!I2C_transfer (handle、&i2cTransaction)){
GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、1);
system_abort (" I2C 传输错误!");
}
} 

I2C 任务:

void get_IMU()
{
uint16_t pwr = 0x00;
c 支助支助;
support.i2c_writeRegister (signal.i2c0、MPU6050_I2C_address、0x6B、0x80、IMU_transaction);
support.i2c_readRegister (signal.i2c0、MPU6050_I2C_address、0x6B、&pwr、1、IMU_transaction);
操作
{
support.i2c_readRegister (signal.i2c0、MPU6050_I2C_address、0x6B、&pwr、1、IMU_transaction);
}
while ((pwr & 0x40)!= 0x40);

//使用具有 X 轴陀螺仪基准的 PLL
support.i2c_writeRegister (signal.i2c0、MPU6050_I2C_address、0x6B、0x01、IMU_transaction);
//启用 I2C 主机模式
support.i2c_writeRegister (signal.i2c0、MPU6050_I2C_address、0x6A、0x20、IMU_transaction);
//设置采样率分频器
support.i2c_writeRegister (signal.i2c0、MPU6050_I2C_address、0x19、0x13、IMU_transaction);
support.i2c_writeRegister (signal.i2c0、MPU6050_I2C_address、0x67、0x11、IMU_transaction);
while (1)
{
Semaphore_pend (IMUSem、BIOS_wait_forever);
support.i2c_readRegister (signal.i2c0、MPU6050_I2C_address、0x3B、(uint16_t *)&signal.imu.mpu6050、14、IMU_transaction);
signal.imu.acx = signal.imu.mpu6050.AccelXH << 8 | signal.imu.mpu6050.AccelXL;
signal.imu.acy = signal.imu.mpu6050.AccelYH << 8 | signal.imu.mpu6050.AccelYL;
signal.imu.acz = signal.imu.mpu6050.AccelZH << 8 | signal.imu.mpu6050.AccelZL;
signal.imu.temperature =(((signal.imu.mpu6050.TempH << 8)| signal.imu.mpu6050.Templ)/ 340)+36.5;
signal.imu.GyX = signal.imu.mpu6050.gyroXH << 8 | signal.imu.mpu6050.gyroXL;
signal.imu.gy= signal.imu.mpu6050.gyroyH << 8 | signal.imu.mpu6050.gyl;
SIGNAL .IMU.GyZ = SIGNAL .IMU.mpu6050.GyroZH << 8 | SIGNAL .IMU.mpu6050.GyroZL;

}
I2C_Close (signal.i2c0);//取消初始化 I2C
System_printf ("I2C 通道0关闭!\n"\});
system_flush();
} 

SPI 引脚配置:

//为 PA2 - SSI0CLK 配置 GPIO 引脚多路复用器


GPIOPinConfigure (GPIO_PA2_SSI0CLK);
GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_2);


//为 PA3配置 GPIO 引脚多路复用器- SSI0FSS
GPIOPinTypeGPIOOutput (GPIO_PORTD_base、GPIO_PIN_0);//将芯片选择线路拉低。 因为驱动器 CS 未提供所需的结果

GPIOPinConfigure (GPIO_PA3_SSI0FSS);
GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_3);

//为 PA4配置 GPIO 引脚多路复用器- SSI0RX

GPIOPinConfigure (GPIO_PA4_SSI0RX);
GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_4);

//为 PA5配置 GPIO 引脚多路复用器- SSI0TX

GPIOPinConfigure (GPIO_PA5_SSI0TX);
GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_5); 

SPI 通道打开:

SPI_Params_init (&rightSpiParams);
rightSpi = SPI_open (right_oragon_SPI0、&rightSpiParams);
if (rightSpi =NULL) System_abort ("初始化右侧 SPI\n"时出错);
否则为 System_printf ("right SPI initialized\n"); 
#define SPI_right_diagonals 对角线_SPI0 
CONST SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[SPICOUNT]={
{
baseAddr = SSI0_BASE、
.intNum = INT_SSI0、
.intPriority =(~0)、
.scratchBufPtr =&spiTivaDMAscratchBuf[0]、
defaultTxBufValue = 0、
.rxChannelIndex = UDMA_CHANGE_SSI0RX、
txChannelIndex = UDMA_CHANGE_SSI0TX、
channelMappingFxn = uDMAChannelAssign、
.rxChannelMappingFxnArg = UDMA_CH10_SSI0RX、
txChannelMappingFxnArg = UDMA_CH11_SSI0TX
}、
{
baseAddr = SSI1_base、
.intNum = INT_SSI1、
.intPriority =(~0)、
.scratchBufPtr =&spiTivaDMAscratchBuf[1]、
defaultTxBufValue = 0、
.rxChannelIndex = UDMA_CHANGE_SSI1RX、
txChannelIndex = UDMA_CHANGE_SSI1TX、
channelMappingFxn = uDMAChannelAssign、
.rxChannelMappingFxnArg = UDMA_CH10_SSI1RX、
txChannelMappingFxnArg = UDMA_CH11_SSI1TX
}
};

const SPI_Config SPI_CONFIG[]={
{
fxnTablePtr =&SPITIvaDMA_fxnTable、
.object =&spiTivaDMAObjects[0]、
hwAttrs =&spiTivaDMAHWAttrs[0]
}、
{
fxnTablePtr =&SPITIvaDMA_fxnTable、
.object =&spiTivaDMAObjects[1]、
hwAttrs =&spiTivaDMAHWAttrs[1]
}、
{NULL、NULL、NULL}、
}; 
SPI 任务: 
void get_height (){

//事务缓冲区
unsigned char rightRxBuffer[8]={0};
无符号字符 rightTxBuffer[]={0x00、0x01、0x87、0x00、0x00、0x00、0x00、0x00、0x00};//对于2个计数器- 24位

SPI_Handle rightSpi、leftSpi、frontSpi;
SPI_Params rightSpiParams、leftSpiParams、FrontSpiParams;
SPI_Transaction rightSpiTrans、leftSpiTrans、FrontSpiTrans;
bool rightConfigure、leftConfigure、frontConfigure;
bool 右前接收机、左前接收机、前接收机;

SPI_Params_init (&rightSpiParams);
rightSpi = SPI_open (right_oragon_SPI0、&rightSpiParams);
if (rightSpi =NULL) System_abort ("初始化右侧 SPI\n"时出错);
否则为 System_printf ("right SPI initialized\n");

/*初始化正确的 SPI 事务结构*/
rightSpiTrans.count = sizeof (rightTxBuffer);
rightSpiTrans.txBuf =(ptr) rightTxBuffer;
rightSpiTrans.rxBuf =空;


/*配置编码器*/
GPIOPinWrite (GPIO_PORTD_BASE、GPIO_PIN_0、1);
GPIOPinWrite (GPIO_PORTD_BASE、GPIO_PIN_0、0);
rightConfigure = SPI_transfer (rightSpi、&rightSpiTrans);
GPIOPinWrite (GPIO_PORTD_BASE、GPIO_PIN_0、1);

if (rightConfigure) System_printf ("成功配置的正确 SPI\n");
否则 System_abort ("右侧 SPI 配置失败");
system_flush();

rightTxBuffer[0]={0x30};//在计数前重置计数器
rightTxBuffer[1]={0x03};
rightSpiTrans.rxBuf =(ptr) rightRxBuffer;
rightSpiTrans 计数= 2;
GPIOPinWrite (GPIO_PORTD_BASE、GPIO_PIN_0、0);
rightConfigure = SPI_transfer (rightSpi、&rightSpiTrans);
GPIOPinWrite (GPIO_PORTD_BASE、GPIO_PIN_0、1);

rightTxBuffer[0]={0x88};//读取计数器值
rightSpiTrans.rxBuf =(ptr) rightRxBuffer;
rightSpiTrans 计数= 7;

COUNTER_48位右编码器;

while (1){
Semaphore_pend (ENCSem、BIOS_WAIT_FOREVER);

GPIOPinWrite (GPIO_PORTD_BASE、GPIO_PIN_0、0); //建议使用2:1 MUX 在不同 SPI 从器件之间进行芯片选择
rightReceive= SPI_transfer (rightSpi、&rightSpiTrans);
GPIOPinWrite (GPIO_PORTD_BASE、GPIO_PIN_0、1);
if (!rightReceive) System_abort ("右 SPI receive failed:(");

signal.rightEncoder.counter1 =(rightRxBuffer[1])<<16|(rightRxBuffer[2]<<8)|(rightRxBuffer[3]);
signal.rightEncoder.counter0 =(rightRxBuffer[4])<<16|(rightRxBuffer[5])<8)|(rightRxBuffer[6]);
}

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

    不确定是什么问题。 不过、我有一些问题。
    0。您正在调用哪一行 System_abort? 您有 System_abort ("Error Initializing I2C channel0\n")和 System_abort ("Bad I2C transfer!")。
    1.当您连接 MISO 和 MOSI 引脚时、SPI 事务是否继续工作、或者您不知道您是否因为已由于 I2C 而中止?
    2.如果仅启用 SPI 而不启用 I2C、会发生什么情况? SPI 是否可以自行工作?
    使用较慢的 SPI 时钟、它是否会对 I2C 中止产生影响? 尝试使用速度要慢得多的 SPI 时钟、以便中断速度更慢。
    4.您能否使用 ROV 来确定是否存在任何堆栈问题?
    5.您是否正在使用 HWI? 由于 SSI0的默认优先级高于 I2C0、因此是否是中断优先级问题? 如果您手动更改该怎么办
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Charles、

     回答以下问题:

    [引用用户="Charles Tsaa"]

    0。您正在调用哪一行 System_abort? 您有 System_abort ("Error Initializing I2C channel0\n")和 System_abort ("Bad I2C transfer!")。

    [/报价]

    system_abort (" I2C 传输错误!") 在 readRegister 中,writeRegister 是随机发生的(主要在 i2c_readRegister()中)。

    [引用用户="Charles Tsaa"]

    1.当您连接 MISO 和 MOSI 引脚时、SPI 事务是否继续工作、或者您不知道您是否因为已由于 I2C 而中止?  

    [/报价]

    我认为 SPI 的工作原理是,我能够在 示波器中看到几波跳跃。  但没有很清楚地看到。

    [引用用户="Charles Tsaa"]

    2.如果仅启用 SPI 而不启用 I2C、会发生什么情况? SPI 是否可以自行工作?

    [/报价]

    是的。 如果仅启用 SPI 任务、则 SPI 工作正常。 (反之亦然、即如果 只启用 I2C 任务、I2C 也会工作)。   

    [引用用户="Charles Tsaa"]

    使用较慢的 SPI 时钟、它是否会对 I2C 中止产生影响? 尝试使用速度要慢得多的 SPI 时钟、以便中断速度更慢。  

    [/报价]

    我尝试使用500ms 配置、但没有任何可能的结果。\

    [引用用户="Charles Tsaa"]

    4.您能否使用 ROV 来确定是否存在任何堆栈问题?

    [/报价]

     我之所以给出2048、是因为 stacksize 希望它不会成为问题

    [引用用户="Charles Tsaa"]

    5.您是否正在使用 HWI? 由于 SSI0的默认优先级高于 I2C0、因此是否是中断优先级问题? 如果您手动更改该怎么办

    [/报价]

    否、我没有在系统中使用任何 HWI。 那么、希望没有必要改变什么呢?

    当我尝试连接 SPI 通道的 MISO 和 MOSI 时,系统出现故障。  即使启用了两个任务、系统也不会发生故障。 那么、连接有任何问题?( 我没有在任何通信 通道(SPI、I2C)中连接任何上拉电阻器。

    感谢您对问题进行了分析、并组织了问题的规划。

    此致、

    Yashwanth Kumar Gandeti。

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

    您好!

    [引用 user="Yashwanth Gandeti ]majorly 系统在我尝试连接 SPI 通道的 MISO 和 MOSI 时失败。  即使启用了两个任务、系统也不会发生故障。 那么、连接有任何问题吗?( 我没有在任何通信 通道(SPI、I2C)中连接任何上拉电阻器。[/quot]

     为了实现正确的 I2C 操作、您必须在 I2C_SCL 和 I2C_SDA 总线上具有适当的上拉电阻器。 无需在 SPI 上进行上拉。 我建议您首先向总线添加正确的上拉电阻器、然后查看是否有任何不同的结果。

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

    我将尝试使用上拉电阻器并让您知道状态。

    此致、
    Yashwanth Kumar。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Yashwanth、
    我没有听到你的反馈。 我假设在放置适当的上拉电阻器后、您的问题可以通过某种方式得到解决、因为这对于 I2C 的正确运行至关重要。 我现在要关闭这个线程。 如果您有新问题、您可以打开新主题、如果问题未得到解决、则重新打开此主题。