Comment initialiser I2C sur STM32F0?

Récemment, j'ai essayé d'obtenir le bus I2C de travail sur la STM32F030F4P6 MCU, mais avec un peu de chance.

Je suis en utilisant un STM32F0 module et ont trouvé une foule de ressources pour la STM32F1 module I2C l'initialisation, mais rien de précis sur l'STM32F0 initialisation/processus de transfert.

Voici mon code d'initialisation:

void i2c_init(uint8_t ownAddress)
{
GPIO_InitTypeDef  GPIO_InitStructure;
I2C_InitTypeDef  I2C_InitStructure;

//Enable GPIOA clocks

RCC_APB2PeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

//Configure I2C1 clock and GPIO

GPIO_StructInit(&GPIO_InitStructure);


/* I2C1 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

/* I2C1 SDA and SCL configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* I2C1 Reset */

RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);


/* Configure I2C1                */

I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
//I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
//I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;


I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE); 

}

Afin de tester pour voir si mon installation est correcte, j'ai conçu quelques I2C transmission d'un code de transfert de données dans une boucle sans fin. Voici le code pour que:

while(1)
{
I2C_SlaveAddressConfig(I2C1, RegName);
I2C_GenerateSTART(I2C1, ENABLE);
I2C_NumberOfBytesConfig(I2C1, 8);
I2C_SendData(I2C1,0b00000000);
I2C_GenerateSTOP(I2C1, ENABLE);
}

Où:

RegName = 0x75

SDA = GPIO_PIN_10 sur GPIOA

SCL = GPIO_PIN_9 sur GPIOA

I2C = I2C1

ownAdrress = 0x68

Quand je l'ai portée I2C lignes après que j'ai commencer ce code j'obtiens une tension flottante autour de 160mV. Quand je marche à travers le code de chacun des I2C appels de fonction arriver et complète, c'est pourquoi je pensais qu'il avait quelque chose de plus à faire avec mon initialisation des pins eux-mêmes.

Mon problème est très similaire à ce fil, mais n'a jamais été répondu:

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fSTM32F0%20I2C%20code%20doesn%27t%20work&FolderCTID=0x01200200770978C69A1141439FE559eb459d7580009c4e14902c3cde46a77f0ffd06506f5b&currentviews=1342

Edit 1: Voici mon code plus tard; ne fonctionne toujours pas (Edit 2: mise à Jour de ce que j'ai actuellement; déplacé les choses en plus d'emplacements corrects):

void i2c_init(uint8_t ownAddress)
{

    /* TypeDefs for GPIOA and I2C1 */

    GPIO_InitTypeDef  GPIO_InitStructure;
    I2C_InitTypeDef  I2C_InitStructure;

    /* Enable GPIOA clocks and I2C1 clock enable */

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    /* Configure I2C1 clock and GPIO */

    GPIO_StructInit(&GPIO_InitStructure);

    /* I2C1 SDA and SCL configuration */

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //UP
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

    /* GPIO AF Configuration -> GPIO_AF_1: USART2, CEC, Tim3, USART1, USART2,EVENTOUT, I2C1, I2C2, TIM15 */

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* I2C1 Reset */

    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);


    //I2C_DeInit(I2C1);

    /* Configure I2C1 */

    I2C_StructInit(&I2C_InitStructure);

    I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

    I2C_Init(I2C1, &I2C_InitStructure);
    I2C_Cmd(I2C1, ENABLE);
    //I2C_AcknowledgeConfig(I2C1, ENABLE);

}

Comme vous pouvez le voir, j'ai ajouté les deux lignes GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); et GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1); où j'ai trouvé que GPIO_AF_1 avait la fonction de remplacement de I2C1 de le STM32F0 Standard Périphérique bibliotheek.

D'autres idées? J'ai été jouer avec les horloges pour voir si cela a changé quelque chose et ont été l'ajout d'extraits d'autres personnes de code juste pour voir si cela a un effet sur la sortie de mon appareil.

Edit 3: j'ai essayé de tirer à la fois le SDA et SCL lignes jusqu'à VCC avec une résistance d ' 1 kohm selon les instructions de ce guide: https://electronics.stackexchange.com/questions/57121/i2c-pullup-resistor-calculations

->(3.3 V-0.4)/3mA ~= d ' 1 kohm

Edit 4: Après être passé par mon code, ligne par ligne, j'ai essayé de la sortie de divers bit indicateur de registres. Ces registres: isr = I2C1->ISR;, cr1 = I2C1->CR1;, et cr2 = I2C1->CR2;

Le drapeau-je obtenir après le début de la I2C transfert de manutention avec I2C_TransferHandling(I2C1, 0x02, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Write); était 0x8001 qui peut être déchiffré à deux erreurs:

#define I2C_ISR_BUSY ((uint32_t)0x00008000) /*!< Bus busy */

et

#define I2C_ISR_TXE ((uint32_t)0x00000001) /*!< Transmit data register empty */

J'ai trouvé des solutions à ce lien ici (enlever l'espace après https: pour aller sur le lien -> débordement de pile ne me permet pas de poster plus d'1 lien pour une certaine raison): https: //my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FSTM32L151RB%20I2C%20Busy%20flag%20always%20set&FolderCTID=0x01200200770978C69A1141439FE559eb459d7580009c4e14902c3cde46a77f0ffd06506f5b&currentviews= 690 que je suis à la recherche à mettre en œuvre et de faire rapport dès que j'ai les essayer.

  • Probablement une question stupide. Avez-vous des pullups sur SDA et SDL? Sont-ils élevés avant d'exécuter ce code?
  • Hé, il n'y DoxyLover, essayé et n'ont pas de travail. Ne croyez pas qu'ils sont élevés avant j'ai couru ce code.
  • Qu'avez-vous exactement connecté à l'I2C lignes? Qu'est-ce que l'appareil esclave? Êtes-vous conscient que vous devez avoir des résistances de pull-up sont connectés entre chaque ligne I2C et Vcc?
  • Donc, pour l'instant je ne l'ai pas connecté à un autre appareil; c'est tout simplement un maître avec une traction séparé pour chacune des lignes SCL et SDA. Et oui, je suis conscient que je vais finir par avoir besoin d'un pullup pour chaque appareil, je l'ai connecté à. Maintenant je n'ai même pas un signal de démarrage de sortir (je devrais être en mesure de voir les données brutes comme est avec mon code actuel, ou au moins le signal de départ).
  • En fait, non, vous n'avez pas besoin de séparer le pull-ups pour chaque appareil. Juste un chacun pour SCL et SDA. Le fait que ces lignes sont bas avant de démarrer l'initialisation de l'I2C peut être un indice important. Le mode par défaut de ces pins semble être dictée (sortie) bas où j'avais l'habitude de drain ouvert (et donc, tiré de haut par les résistances). Malheureusement, j'ai un pas familier avec la série STM32 de la série donc je ne peux vraiment pas vous aider davantage.
  • Ouais, ça doit être quelque chose de très spécifique à la série STM32, plus précisément le STM32F0 de la série. Merci pour votre aide bien, je vais continuer et voir si je peux pas trouver une solution à mon propre compte.
  • Il vous manque des GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_Pin_9); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_Pin_10);. Je ne sais pas si c'est important, mais vous pourriez avoir besoin de le faire avant appeler GPIO_Init.
  • Ajouté ces lignes de code; voir mon édité réponse ci-dessus pour une mise à jour sur la situation.