STM32L152RB problem s interruptom na I2C
nesvacil@posys.cz
nesvacil na posys.eu
Pondělí Září 16 08:53:02 CEST 2013
Zdravim,
dival jste se na nejake starsi priklady od ST ? Me tam zarazi spousta while cekacich casti, prave proto si rikam, zda to ma vyznam z hlediska casu CPU vubec delat pres hw i2c u ST32F1.. .
Navic nektere slave IO na sbernici se trosku rovnaji na CLK I2C tj. pokud by jste to udelal v nejake hlavni smycce misto delay-while, tak by to taky nemuselo fungovat nebo ne ?
Status I2C_Master_BufferWrite(I2C_TypeDef* I2Cx, uint8_t* pBuffer, uint32_t NumByteToWrite, I2C_ProgrammingModel Mode, uint8_t SlaveAddress )
{
__IO uint32_t temp = 0;
__IO uint32_t Timeout = 0;
/* Enable Error IT (used in all modes: DMA, Polling and Interrupts */
I2Cx->CR2 |= I2C_IT_ERR;
if (Mode == DMA) /* I2Cx Master Transmission using DMA */
{
Timeout = 0xFFFF;
/* Configure the DMA channel for I2Cx transmission */
I2C_DMAConfig (I2Cx, pBuffer, NumByteToWrite, I2C_DIRECTION_TX);
/* Enable the I2Cx DMA requests */
I2Cx->CR2 |= CR2_DMAEN_Set;
/* Send START condition */
I2Cx->CR1 |= CR1_START_Set;
/* Wait until SB flag is set: EV5 */
while ((I2Cx->SR1&0x0001) != 0x0001)
{
if (Timeout-- == 0)
return Error;
}
Timeout = 0xFFFF;
/* Send slave address */
/* Reset the address bit0 for write */
SlaveAddress &= OAR1_ADD0_Reset;
Address = SlaveAddress;
/* Send the slave address */
I2Cx->DR = Address;
/* Wait until ADDR is set: EV6 */
while ((I2Cx->SR1&0x0002) != 0x0002)
{
if (Timeout-- == 0)
return Error;
}
/* Clear ADDR flag by reading SR2 register */
temp = I2Cx->SR2;
if (I2Cx == I2C1)
{
/* Wait until DMA end of transfer */
while (!DMA_GetFlagStatus(DMA1_FLAG_TC6));
/* Disable the DMA1 Channel 6 */
DMA_Cmd(I2C1_DMA_CHANNEL_TX, DISABLE);
/* Clear the DMA Transfer complete flag */
DMA_ClearFlag(DMA1_FLAG_TC6);
}
else /* I2Cx = I2C2 */
{
/* Wait until DMA end of transfer */
while (!DMA_GetFlagStatus(DMA1_FLAG_TC4));
/* Disable the DMA1 Channel 4 */
DMA_Cmd(I2C2_DMA_CHANNEL_TX, DISABLE);
/* Clear the DMA Transfer complete flag */
DMA_ClearFlag(DMA1_FLAG_TC4);
}
/* EV8_2: Wait until BTF is set before programming the STOP */
while ((I2Cx->SR1 & 0x00004) != 0x000004);
/* Program the STOP */
I2Cx->CR1 |= CR1_STOP_Set;
/* Make sure that the STOP bit is cleared by Hardware */
while ((I2Cx->CR1&0x200) == 0x200);
}
else if (Mode == Polling) /* I2Cx Master Transmission using Polling */
{
Timeout = 0xFFFF;
/* Send START condition */
I2Cx->CR1 |= CR1_START_Set;
/* Wait until SB flag is set: EV5 */
while ((I2Cx->SR1&0x0001) != 0x0001)
{
if (Timeout-- == 0)
return Error;
}
/* Send slave address */
/* Reset the address bit0 for write*/
SlaveAddress &= OAR1_ADD0_Reset;
Address = SlaveAddress;
/* Send the slave address */
I2Cx->DR = Address;
Timeout = 0xFFFF;
/* Wait until ADDR is set: EV6 */
while ((I2Cx->SR1 &0x0002) != 0x0002)
{
if (Timeout-- == 0)
return Error;
}
/* Clear ADDR flag by reading SR2 register */
temp = I2Cx->SR2;
/* Write the first data in DR register (EV8_1) */
I2Cx->DR = *pBuffer;
/* Increment */
pBuffer++;
/* Decrement the number of bytes to be written */
NumByteToWrite--;
/* While there is data to be written */
while (NumByteToWrite--)
{
/* Poll on BTF to receive data because in polling mode we can not guarantee the
EV8 software sequence is managed before the current byte transfer completes */
while ((I2Cx->SR1 & 0x00004) != 0x000004);
/* Send the current byte */
I2Cx->DR = *pBuffer;
/* Point to the next byte to be written */
pBuffer++;
}
/* EV8_2: Wait until BTF is set before programming the STOP */
while ((I2Cx->SR1 & 0x00004) != 0x000004);
/* Send STOP condition */
I2Cx->CR1 |= CR1_STOP_Set;
/* Make sure that the STOP bit is cleared by Hardware */
while ((I2Cx->CR1&0x200) == 0x200);
}
else /* I2Cx Master Transmission using Interrupt with highest priority in the application */
{
/* Enable EVT IT*/
I2Cx->CR2 |= I2C_IT_EVT;
/* Enable BUF IT */
I2Cx->CR2 |= I2C_IT_BUF;
/* Set the I2C direction to Transmission */
I2CDirection = I2C_DIRECTION_TX;
SlaveAddress &= OAR1_ADD0_Reset;
Address = SlaveAddress;
if (I2Cx == I2C1) NumbOfBytes1 = NumByteToWrite;
else NumbOfBytes2 = NumByteToWrite;
/* Send START condition */
I2Cx->CR1 |= CR1_START_Set;
/* Wait until the START condition is generated on the bus: the START bit is cleared by hardware */
while ((I2Cx->CR1&0x100) == 0x100);
/* Wait until BUSY flag is reset: a STOP has been generated on the bus signaling the end
of transmission */
while ((I2Cx->SR2 &0x0002) == 0x0002);
}
return Success;
}
Jirka
Dne 16. 9. 2013 1:26, Stano napsal(a):
> DMA pouzivam pre prenos viac nez 1 byte, pre jeden byte pouzivam IRQ.
> V ST je kniznica CPAL, ta pouziva DMA aj IRQ. Dival som sa donej ale nemozem povedat ze ju ovladam do posledneho riadku, je totiz postavena na makrach a pisana takym stylom ze kym sa dostanete k informacii do akeho registra to vlastne zapisuje a co
> zapisuje prejdete mnoho a mnoho definicii a definicii definicii...
> Povedal by som ze ked sa snaha o abstraktnost prezenie vedie to k maximalne necitatelnemu kodu, zial tato kniznica je toho prikladom.
>
> A odpoved na vasu otazku, ta periferia na F1/L1 o ktorej je tento thread je naozaj problematicka ale skusal som aj I2C na F0/F3 a to bola priam radost. Ta mi prisla naozaj user fiendly. Pokial sa nejedna len o 1..2 byte HW periferia urcite zmysel
> ma. A na tej F0/F3 STM aj na ten jeden byte.
>
> nesvacil na posys.cz wrote / napísal(a):
>> Zdravim,
>> v DMA rezimu prenasite vice jak jeden byte ? Tak to je popsano v Err... .
>> Jinak pouzivame SW implementaci I2C prave z duvodu vsech moznych chyb I2C.
>>
>> Pokud vim, tak v knihovnach od ST jsou rutiny na DMA prenos, ty to zablokuji jen do doby vyslani startu na I2C ci prvniho byte... ? Dival jste se tam ?
>>
>> Docela by me taky zajimalo, zda nekdo provozuje produkcni I2C s hw implmenetaci ST. A zda to ma vyznam pro komunikaci jednoho ci dvou bytu v prenosu ... ?
>>
>> Jirka
>>
>>
>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
Další informace o konferenci Hw-list