×
单片机 > 单片机程序设计 > 详情

stm32 can中断通信

发布时间:2020-08-28 发布时间:
|

1、初始化can时钟


void canRCCInit()

{

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);


2、配置can的GPIO引脚


void canGPIOConfigure()

{

    GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);


    GPIO_InitTypeDef gpioInit;

    gpioInit.GPIO_Pin = GPIO_Pin_8;

    gpioInit.GPIO_Mode = GPIO_Mode_IPU;

    gpioInit.GPIO_Speed = GPIO_Speed_50MHz;


    GPIO_Init(GPIOB, &gpioInit);


    gpioInit.GPIO_Pin = GPIO_Pin_9;

    gpioInit.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOB, &gpioInit);


3、配置并使能can


void canConfigure()

{

    CAN_InitTypeDef can_init;

    CAN_DeInit(CAN1);

    CAN_StructInit(&can_init);


    //关闭时间触发模式

    can_init.CAN_TTCM = DISABLE;    

    //关闭自动离线管理

    can_init.CAN_ABOM = DISABLE;

    //关闭自动唤醒模式

    can_init.CAN_AWUM = DISABLE;

    //禁止报文自动重发

    can_init.CAN_NART = DISABLE;

    //FIFO 溢出时报文覆盖原文件

    can_init.CAN_RFLM = DISABLE;

    //报文发送优先级取决于ID号

    can_init.CAN_TXFP = DISABLE;

    //回环模式

    can_init.CAN_Mode = CAN_Mode_LoopBack;


    //配置时钟频率

    can_init.CAN_SJW = CAN_SJW_1tq;

    can_init.CAN_BS1 = CAN_BS1_3tq;

    can_init.CAN_BS2 = CAN_BS2_2tq;

    can_init.CAN_Prescaler = 48;


    CAN_Init(CAN1, &can_init);


    CAN_FilterInitTypeDef can_filter;


    //屏蔽滤波

    can_filter.CAN_FilterNumber = 0;

    //屏蔽模式

    can_filter.CAN_FilterMode = CAN_FilterMode_IdMask;

    //32位寄存器

    can_filter.CAN_FilterScale = CAN_FilterScale_32bit;

    //高16位

    can_filter.CAN_FilterIdHigh = 0x0000;

    //低16位

    can_filter.CAN_FilterIdLow = 0;

    //屏蔽位高16位

    can_filter.CAN_FilterMaskIdHigh = 0;

    //屏蔽位低16位

    can_filter.CAN_FilterMaskIdLow = 0;

    //过滤器0关联到FIFO0

    can_filter.CAN_FilterFIFOAssignment = CAN_FilterFIFO0;

    //使能过滤器

    can_filter.CAN_FilterActivation = ENABLE;

    //初始化过滤器

    CAN_FilterInit(&can_filter);


    //使能接收中断

    CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

}

4、配置中断源


void canNvicConfigure()

{

    NVIC_InitTypeDef nvic_init;

    nvic_init.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;

    nvic_init.NVIC_IRQChannelPreemptionPriority = 0;

    nvic_init.NVIC_IRQChannelSubPriority = 0;

    nvic_init.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&nvic_init);


    nvic_init.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn;

    nvic_init.NVIC_IRQChannelPreemptionPriority = 0;

    nvic_init.NVIC_IRQChannelSubPriority = 1;

    nvic_init.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&nvic_init);

}


5、实现中断处理函数


void USB_LP_CAN1_RX0_IRQHandler(void)

{

    CanRxMsg rx;

    CAN_Receive(CAN1, CAN_FIFO0, &rx);

    for(int i = 0; i < rx.DLC; i++){

        printf("recv data: %crn",rx.Data[i]);

    }

}


void USB_HP_CAN1_TX_IRQHandler(void)

{

    if(count < len){

        txMessage.Data[0] = txBuf[count++];

        CAN_Transmit(CAN1, &txMessage);

    }

    else {

        CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE);

    }

}


6、实现发送函数


void canWrite(const char *p)

{

    strcpy(txBuf, p);

    len = strlen(p);

    count = 0;

    txMessage.StdId = 0xFE00 >> 5;

    txMessage.ExtId = 0;

    txMessage.IDE = CAN_ID_STD;

    txMessage.RTR = CAN_RTR_DATA;

    txMessage.DLC = 1;  //此处最多可传输8个字节

    txMessage.Data[0] = txBuf[count++];

    CAN_Transmit(CAN1, &txMessage);


    CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);

}


7、总结:在写can总线协议时,需要自己仔细阅读stm32的官方手册,can总线有多种模式及标识符列表模式、标识符屏蔽模式等,需要自己仔细琢磨。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
mu;C/OS-Ⅱ在ARM系列单片机S3C44B0x上的移植