2 votes

<div>Microcontrôleur STM32F103 messages CAN</div>

Je me demande si quelqu'un est familier avec les microcontrôleurs STM32f10x ?

Si c'est le cas, j'ai quelques problèmes pour configurer un pilote CAN. Je peux exécuter le code de démonstration, qui est configuré en mode loop_Back, mais je n'arrive pas à faire fonctionner le Normal_Mode.

J'ai lu tous les fiches techniques, et tout est configuré correctement sauf que le INAK dans le registre CAN_MSR ne se réinitialise jamais à 0. Je peux fournir plus de détails si nécessaire, mais d'abord je dois savoir s'il y a quelqu'un qui a travaillé avec un microcontrôleur STM32F103 et des messages CAN.

3voto

Ron Points 488

Vous avez configuré la broche Tx en Out_PP, mais elle devrait être configurée comme fonction alternative. Voici mon code d'initialisation pour le CAN sur un STM32F107. Je l'ai copié-collé et nettoyé à partir d'un projet existant donc certaines choses ne sont pas nécessaires (comme toutes les broches GPIO ne doivent pas être activées). Notez également que j'ai utilisé la fonction de remappage pour mettre les broches CAN Rx et Tx sur le port D.

Cette configuration définit la vitesse du bus à 500 kbit/s lorsqu'on utilise une horloge de 72 MHz.

Int HardwareInit(void)
{
    Int retval = 0;

    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef   NVIC_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
    CAN_InitTypeDef        CAN_InitStructure;
    CAN_FilterInitTypeDef  CAN_FilterInitStructure;

    SystemInit();

    /* Activation des horloges des GPIOs */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
                           RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE| RCC_APB2Periph_AFIO, ENABLE);

    /* 2 bits pour la priorité de préemption, 2 bits pour la sous-priorité */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

    CAN_DeInit(CAN1);
    CAN_StructInit(&CAN_InitStructure);

    /* Initialisation de la cellule CAN */
    CAN_InitStructure.CAN_TTCM = DISABLE;
    CAN_InitStructure.CAN_ABOM = DISABLE;
    CAN_InitStructure.CAN_AWUM = DISABLE;
    CAN_InitStructure.CAN_NART = ENABLE;
    CAN_InitStructure.CAN_RFLM = DISABLE;
    CAN_InitStructure.CAN_TXFP = ENABLE;
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
    CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
    CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
    CAN_InitStructure.CAN_Prescaler = 8;
    CAN_Init(CAN1, &CAN_InitStructure);

    /* Initialisation du filtre CAN */
    CAN_FilterInitStructure.CAN_FilterNumber=0;
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);

    CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0xFF;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0xFF;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Configuration de la broche CAN : RX */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* Configuration de la broche CAN : TX */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    GPIO_PinRemapConfig(GPIO_Remap2_CAN1 , ENABLE);

    return retval;
}

L'envoi d'un message peut alors être fait comme ceci :

CanTxMsg TxMessage;
Nat8 mailbox;

TxMessage.StdId = 0x7E5;
TxMessage.RTR=CAN_RTR_DATA;
TxMessage.IDE=CAN_ID_STD;

TxMessage.Data[0] = 0x04;
TxMessage.Data[1] = (state) ? 0x01 : 0x00;
TxMessage.Data[2] = 0x00;
TxMessage.Data[3] = 0x00;
TxMessage.Data[4] = 0x00;
TxMessage.Data[5] = 0x00;
TxMessage.Data[6] = 0x00;
TxMessage.Data[7] = 0x00;
TxMessage.DLC = 8;

do
{
    mailbox = CAN_Transmit(CAN1, &TxMessage);
}
while (mailbox == CAN_NO_MB);

La réception se fait via IRQ :

CanRxMsg rx_message;
CAN_Receive(CAN1, CAN_FIFO0, &rx_message);

2voto

David Grayson Points 22459

J'ai travaillé avec des microcontrôleurs STM32F103 mais ma seule (petite) expérience avec le CAN était que l'activer faisait que l'USB ne fonctionnait pas. Les deux modules partagent un espace mémoire. Assurez-vous donc de désactiver le module USB et l'horloge de celui-ci (effacez le bit 23 du RCC_APB1ENR).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X