打印
[活动专区]

【AutoChips MCU评测报告】+CAN驱动实现

[复制链接]
1721|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
caizhiwei|  楼主 | 2020-6-3 17:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

#include "bsp_can.h"

stc_can_rxframe_t       stcRxFrame;
stc_can_txframe_t       stcTxFrame;
uint8_t                 u8RxFlag = FALSE;

static void Can_Gpio_Init(void)
{
    stc_gpio_cfg_t stcGpioCfg;

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    ///< 端口方向配置->输入
    stcGpioCfg.enDir = GpioDirIn;
    ///< 端口驱动能力配置->高驱动能力
    stcGpioCfg.enDrv = GpioDrvL;
    ///< 端口上下拉配置->无
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdDisable;
    ///< 端口开漏输出配置->开漏输出关闭
    stcGpioCfg.enOD = GpioOdDisable;
    ///< 端口输入/输出值寄存器总线控制模式配置->AHB
    stcGpioCfg.enCtrlMode = GpioAHB;

    Gpio_Init(EVB_CAN_RX_PORT, EVB_CAN_RX_PIN, &stcGpioCfg);
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(EVB_CAN_TX_PORT, EVB_CAN_TX_PIN, &stcGpioCfg);
    Gpio_Init(EVB_CAN_STB_PORT, EVB_CAN_STB_PIN, &stcGpioCfg);

    ///<CAN RX\TX复用功能配置
    Gpio_SetAfMode(EVB_CAN_RX_PORT, EVB_CAN_RX_PIN, GpioAf1);
    Gpio_SetAfMode(EVB_CAN_TX_PORT, EVB_CAN_TX_PIN, GpioAf1);

    ///<STB 低-PHY有效
    Gpio_ClrIO(EVB_CAN_STB_PORT, EVB_CAN_STB_PIN);
}


void BSP_Can_Init(void)
{
    stc_can_init_config_t   stcCanInitCfg;
    stc_can_filter_t        stcFilter;

        Can_Gpio_Init();
       
    Sysctrl_SetPeripheralGate(SysctrlPeripheralCan, TRUE);

    //<<CAN 波特率配置
        // 手册page884.exp: bt = (PRESC+1)((SEG_1+2) + (SEG_2+1))*(1/8M) = 1us (1000k)

#ifdef CAN_CONFIG_48MHZ_500K         
       
        stcCanInitCfg.stcCanBt.PRESC = 6-1;
        stcCanInitCfg.stcCanBt.SEG_1 = 9-2;
        stcCanInitCfg.stcCanBt.SEG_2 = 7-1;       
        stcCanInitCfg.stcCanBt.SJW   = 3-1;       
       
//        stcCanInitCfg.stcCanBt.PRESC = 8-1;
//  stcCanInitCfg.stcCanBt.SEG_1 = 7-2;
//  stcCanInitCfg.stcCanBt.SEG_2 = 5-1;
//  stcCanInitCfg.stcCanBt.SJW   = 5-1;
       
#endif

    stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10;
    stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16-1;

    stcCanInitCfg.enCanRxBufAll  = CanRxNormal;
    stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
    stcCanInitCfg.enCanSTBMode   = CanSTBFifoMode;

    CAN_Init(&stcCanInitCfg);

    //<<CAN 滤波器配置
    stcFilter.enAcfFormat = CanAllFrames;
    stcFilter.enFilterSel = CanFilterSel1;
    stcFilter.u32CODE     = 0x00000236;
    stcFilter.u32MASK     = 0x1FFFFFFF; /*0x1FFFFFFF is all received*/
    CAN_FilterConfig(&stcFilter, TRUE);

    //<<Can Irq Enable
    CAN_IrqCmd(CanRxIrqEn, TRUE); /* 接收中断使能 */
        CAN_IrqCmd(CanBusErrorIrqEn, TRUE); /*总线错误中断使能*/
               
    EnableNvic(CAN_IRQn, IrqLevel0, TRUE);
}



/********************************************************************************************************
**函数信息 :void CAN_send_Frame()
**功能描述 :CAN发送一帧报文
**输入参数 :stcTxFrame
**输出参数 :None
**    备注  目前只考虑标准帧
********************************************************************************************************/
void CAN_send_Frame(stc_can_txframe_t *TxFrame, uint32_t Can_ID,uint8_t frame_len)
{
        TxFrame->StdID = Can_ID;
        TxFrame->Control_f.DLC = frame_len;
        TxFrame->Control_f.IDE = 0; /*标准帧 or 扩展帧*/
        TxFrame->Control_f.RTR = 0; /*数据帧 or 远程帧*/
        TxFrame->enBufferSel = (en_can_buffer_sel_t)0U; /*使用主缓冲器*/
        CAN_SetFrame(TxFrame); /*数据塞进fifo缓冲器*/       
        CAN_TransmitCmd(CanPTBTxCmd);
}
       

void Can_IRQHandler(void)
{
    if(TRUE == CAN_Irq**Get(CanRxIrq**))
    {
        CAN_Irq**Clr(CanRxIrq**);
        CAN_Receive(&stcRxFrame);
        u8RxFlag = TRUE;
    }
         if(TRUE == CAN_Irq**Get(CanBusErrorIrq**))  /*当总线短路时,进入此中断*/
         {          
                  CAN_Irq**Clr(CanBusErrorIrq**);         
                // M0P_CAN->CFG_STAT = 0x00; /* 清除由硬件置位的Reset 标志位,必须在中断外部执行*/                 
         }
}


头文件:
#ifndef __BSP_CAN_H__
#define __BSP_CAN_H__

#include "can.h"
#include "gpio.h"


#define CAN_CONFIG_48MHZ_500K

void BSP_Can_Init(void);

void CAN_send_Frame(stc_can_txframe_t *TxFrame, uint32_t Can_ID,uint8_t frame_len);

extern uint8_t      u8RxFlag ;
extern stc_can_rxframe_t       stcRxFrame;
extern stc_can_txframe_t       stcTxFrame;

#endif


使用特权

评论回复

相关帖子

沙发
xddfandy| | 2020-6-3 21:33 | 只看该作者

使用特权

评论回复
板凳
caizhiwei|  楼主 | 2020-6-4 09:42 | 只看该作者

过江啦,大家一起学习,这个驱动可以直接用的

使用特权

评论回复
地板
JasonLee27| | 2020-6-8 14:46 | 只看该作者
看上去像是从st移植过来的驱动,不需要修改一下底层实现吗?

使用特权

评论回复
5
wangchong1| | 2020-7-4 11:54 | 只看该作者
你好,大神,我在使用华大072CAN的时候,用例程收发数据都正常,就是我把CAN H和CAN L两条线断开后,再连上,就无法收发数据了,必须把单片机复位一下,又可以收发了,不知道什么原因?能指点一下吗?我以前没用过CAN

使用特权

评论回复
6
caizhiwei|  楼主 | 2020-7-4 19:36 | 只看该作者
wangchong1 发表于 2020-7-4 11:54
你好,大神,我在使用华大072CAN的时候,用例程收发数据都正常,就是我把CAN H和CAN L两条线断开后,再连上 ...

问得好,总线错误了呢,参考我之前的帖子

使用特权

评论回复
7
caizhiwei|  楼主 | 2020-7-4 19:38 | 只看该作者
caizhiwei 发表于 2020-7-4 19:36
问得好,总线错误了呢,参考我之前的帖子

https://bbs.21ic.com/icview-2970238-1-1.html

使用特权

评论回复
8
wangchong1| | 2020-7-7 11:12 | 只看该作者
caizhiwei 发表于 2020-7-4 19:38
https://bbs.21ic.com/icview-2970238-1-1.html

大神,我看你说的清这个标志位必须放到中断外部,我感觉没什么区别吧,我是在中断里面写的,试了一下暂时也没什么问题,你能不能帮忙看看,我这样写有什么问题吗?多谢了?
这个是你的:// M0P_CAN->CFG_STAT = 0x00; /* 清除由硬件置位的Reset 标志位,必须在中断外部执行*/
下面是我写的,还请大神指点一下
void Can_IRQHandler(void)
{
    if(TRUE == CAN_Irq**Get(CanRxIrq**))
    {
        CAN_Irq**Clr(CanRxIrq**);
        CAN_IrqCmd(CanRxIrqEn, FALSE);

        CAN_Receive(&stcRxFrame);

        u8RxFlag = TRUE;
    }
               
                 if(TRUE == CAN_Irq**Get(CanBusErrorIrq**))
                 {
               
                         
                   CAN_Irq**Clr(CanBusErrorIrq**);
              
                         M0P_CAN->CFG_STAT = 0x01;//总线关闭状态
                         M0P_CAN->CFG_STAT = 0x00;//清除由硬件置位的Reset标志位
                 }

}

使用特权

评论回复
评论
wangchong1 2020-7-7 13:26 回复TA
@caizhiwei :好的,多谢了! 
caizhiwei 2020-7-7 12:32 回复TA
看了,这样也没问题,主要目的是让总线能恢复。 
9
lvhaoguang| | 2021-3-12 10:31 | 只看该作者
收藏

使用特权

评论回复
10
cr315| | 2021-3-12 11:03 | 只看该作者
楼主厉害了,赞

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

100

主题

857

帖子

14

粉丝