PIC32MZ0512EFF相关的CAN配置

作者:神秘网友 发布时间:2020-10-15 22:35:03

PIC32MZ0512EFF相关的CAN配置

PIC32MZ0512EFF相关的CAN配置

PIC32MZ0512EFF相关的CAN配置(学习记录)

鉴于PIC相关资料较少,我在这记录分享一下自己经过一段时间的学习试验以后对PIC32系列的CAN的理解。记录不仅仅是分享,同样也是整理归纳查漏补缺的过程。在这个过程中大家互相学习,共同进步。

在使用芯片PIC32MZ0512EFF配置CAN初始化的过程中,我遇到了一个问题:这个芯片的CAN部分没有直接供我们使用的发送寄存器和接收寄存器。

下面会描述一下我的解决方法,并说说我的理解。

直接上干货:这里把对CAN2的初始化的全部过程都写出来。每个步骤在后文都会有详细的代码示例。

void CAN2_Init(void)
{
	CAN2_GPIOPPSConfig();
	//第一步:对CAN2进行引脚分配(PPS映射),以及设置相应的输入输出
	C2CONSET = _C2CON_ON_MASK;
	//第二步:启用can2模块,也可以写成C2CONbits.ON = 1;
	CAN2_ConfigurationMode();
	//第三步:顾名思义,就是进入CAN2的配置模式
	CAN2_BaudrateInit();
	//第四步:配置CAN2的波特率
	C2FIFOBA = 0x0000100;
	//第五步:设置FIFO起始地址
	CAN2_FIFOn();
	//第六步:设置FIFO,包括需要用到的FIFO数量以及每个FIFO相应的功能和容量大小
	CAN2_FilterMaskInit();
	//第七步:设置过滤器和屏蔽器
	CAN2_LoopMode();
	//第八步:进入CAN2的自检模式(环回模式),当然如果相应引脚与CAN收发器连接了,可以进入正常模式
}

注:后面按顺序分4个部分展示第一步,第三步和第八步,第四步,第五六七步的代码和我的理解

#第一部分

void CAN2_GPIOPPSConfig(void)
{
	SYSKEY = 0x00000000;
    SYSKEY = 0xAA996655;
    SYSKEY = 0x556699AA;
    CFGCONbits.IOLOCK = 0;
    //解锁序列
    //在芯片手册里有说到:正常工作状态下,对PPS管脚映射功能配置失效。要想使用,需要执行一个解锁序列,然后把IOLOCK清零
    C2RXR = 4;
    //把RD4设为C2RX
    RPD5R = 15;
    //把RD5设为C2TX
    CFGCONbits.IOLOCK = 1;
    SYSKEY = 0x00000000;
    //设完PPS后把管脚映射锁置1,把序列清零
    TRISDSET = _PORTD_RD4_MASK;
    //可以写成TRISDbits.TRISD4 = 1;
    TRISDCLR = _PORTD_RD5_MASK;
    //可以写成TRISDbits.TRISD5 = 0;
} 

注:对解锁序列的理解不深,这里就不发表看法了。但还是说一下我实际操作中的现象:

1、我在没有执行解锁序列的情况下也能使用管脚映射功能(这应该和我的配置位设置内容有关联)
2、如果之后要设置为环回模式,请确保所要使用的引脚悬空

#第二部分

void CAN2_ConfigurationMode(void)
{
    C2CONbits.REQOP = 4;//配置为配置模式
    while(C2CONbits.OPMOD!=4);//等待配置模式配置完毕
}
void CAN2_LoopMode(void)
{
    C2CONbits.REQOP = 2;//配置为环回模式
    while(C2CONbits.OPMOD!=2);//等待环回模式配置完毕
}
void CAN2_NormalMode(void)
{
    C2CONbits.REQOP = 0;//配置为正常模式
    while(C2CONbits.OPMOD!=0);//等待正常模式配置完毕
}

注:环回模式可以在不接外部芯片(比如CAN收发芯片MCP2551)的情况下测试程序

#第三部分

void CAN2_BaudrateInit(void)
{
    //500Mbps
    C2CFGbits.BRP = 9;//波特率预分频
    C2CFGbits.SJW = 0;//同步跳转宽度
    C2CFGbits.PRSEG = 0;//传播时间段(Prop_Seg)
    C2CFGbits.SEG1PH = 3;//相位缓冲段1(Phase_Seg1)
    C2CFGbits.SAM = 0;//在采样点采样一次
    C2CFGbits.SEG2PHTS = 1;//表示相位缓冲段2可自由编程
    C2CFGbits.SEG2PH = 3;//相位缓冲段2(Phase_Seg2)
}

/*波特率计算公式:
 *                                      PBCLK5
 *              baud = ----------------------------------------------  
 *                     (Prop_Seg+Phase_Seg1+Phase_Seg2+SJW)*2*(BRP+1)
 */
 //我用的外部晶振,在进行倍频处理后为200MHz,PBCLK5为CAN的外设时钟,外设时钟默认分频2,所以PBCLK5 = 100MHz

#第四部分

void CAN2_FIFOn(void)
{
    C2FIFOCON0bits.FSIZE = 31;//FIFO0深度为32个缓冲区
    C2FIFOCON0bits.TXEN = 1;//FIFO0配置为发送区
    
    
    C2FIFOCON1bits.FSIZE = 0;//FIFO1深度为1个缓冲区
    C2FIFOCON1bits.DONLY = 0;
    C2FIFOCON1bits.TXEN = 0;//FIFO1配置为接收区
    
    
    C2FIFOCON2bits.FSIZE = 0;//FIFO2深度为1个缓冲区
    C2FIFOCON2bits.DONLY = 0;
    C2FIFOCON2bits.TXEN = 0;//FIFO2配置为接收区
    
    
    C2FIFOCON3bits.FSIZE = 0;//FIFO3深度为1个缓冲区
    C2FIFOCON3bits.DONLY = 0;
    C2FIFOCON3bits.TXEN = 0;//FIFO3配置为接收区
    
    
    C2FIFOCON4bits.FSIZE = 0;//FIFO4深度为1个缓冲区
    C2FIFOCON4bits.DONLY = 0;
    C2FIFOCON4bits.TXEN = 0;//FIFO4配置为接收区
}
//这里解释一下FIFO的机制:就我所使用的芯片,拥有2个CAN区域,每个CAN拥有32个FIFO,每个FIFO拥有1-32个可配置的数据缓冲区,每个数据缓冲区
//可容纳4*32个bit或是1个报文(包括ID和数据)。每个FIFO都可以配置为发送区或是接收区,且FIFO紧密排列。
//例如上面的程序:CAN2的FIFO排列如下
//FIFO0   发送区   可以容纳32个报文  物理地址0X00000100
//FIFO1   接收区   可以容纳1 个报文  物理地址0X00000300
//FIFO2   接收区   可以容纳1 个报文  物理地址0X00000310 
//FIFO3   接收区   可以容纳1 个报文  物理地址0X00000320 
//FIFO4   接收区   可以容纳1 个报文  物理地址0X00000330 
//FIFO5   未分配   可以容纳1 个报文  物理地址0X00000340 
//FIFO6   未分配   可以容纳1 个报文  物理地址0X00000350 
//........
//FIFO31  未分配   可以容纳1 个报文  物理地址0X000004F0 

void CAN2_FilterMaskInit(void)
{
    C2FLTCON0bits.FSEL0 = 1;//接收到的与过滤器0匹配的数据存储在FIFO1中
    C2FLTCON0bits.MSEL0 = 1;//选择接收屏蔽器1
    C2RXF0bits.EID = 0x0;//设置过滤器0
    C2RXF0bits.SID = 0xE;
    C2RXF0bits.EXID = 1;
    
    
    C2FLTCON0bits.FSEL1 = 2;//接收到的与过滤器1匹配的数据存储在FIFO2中
    C2FLTCON0bits.MSEL1 = 1;//选择接收屏蔽器1
    C2RXF1bits.EID = 0x0;//设置过滤器1
    C2RXF1bits.SID = 0xA;
    C2RXF1bits.EXID = 1;
    
    
    C2FLTCON0bits.FSEL2 = 3;//接收到的与过滤器2匹配的数据存储在FIFO3中
    C2FLTCON0bits.MSEL2 = 1;//选择接收屏蔽器1
    C2RXF2bits.EID = 0x0;//设置过滤器2
    C2RXF2bits.SID = 0xC;
    C2RXF2bits.EXID = 1;
    
    
    C2FLTCON0bits.FSEL3 = 4;//接收到的与过滤器3匹配的数据存储在FIFO4中
    C2FLTCON0bits.MSEL3 = 1;//选择接收屏蔽器1
    C2RXF3bits.EID = 0x0;//设置过滤器3
    C2RXF3bits.SID = 0x8;
    C2RXF3bits.EXID = 1;
    
    
    C2RXM1bits.EID = 0x0;//设置屏蔽器1
    C2RXM1bits.SID = 0xF;
    C2RXM1bits.MIDE = 1;
    
    C2FLTCON0bits.FLTEN0 = 1;//启用过滤器
    C2FLTCON0bits.FLTEN1 = 1;
    C2FLTCON0bits.FLTEN2 = 1;
    C2FLTCON0bits.FLTEN3 = 1;
}

以下为接收发送时需要用到的宏,这几个宏在XC32编译器手册中被提到

typedef unsigned long _paddr_t; //物理地址
typedef unsigned long _vaddr_t; //虚拟地址
#define KVA_TO_PA(v) 	((_paddr_t)(v) & 0x1fffffff)//将内核地址转换成物理地址
#define PA_TO_KVA0(pa)	((void *) ((pa) | 0x80000000))//将物理地址转换成KSEG0虚拟地址
#define PA_TO_KVA1(pa)	((void *) ((pa) | 0xa0000000))//将物理地址转换成KSEG1虚拟地址

先上图:
PIC32MZ0512EFF相关的CAN配置
在PIC32中CPU所使用的是左边的虚拟地址,而外设使用的是右边的物理地址。也即使说软件操作写入外设寄存器(左边),CPU会对其转换为右边的物理地址。手册中指出C2FIFOBA、C2FIFOUAn为物理地址。C2FIFOUAn为FIFOn的起始地址,在需要从FIFO中读取或写入数据时,需要将C2FIFOUAn转换为左边的虚拟地址后通过软件读取或写入。

typedef union
{
    struct
    {
        unsigned TXCMSGSID_SID:11;
        unsigned :21;
        unsigned TXCMSGEID_DLC:4;
        unsigned TXCMSGEID_RB0:1;
        unsigned :3;
        unsigned TXCMSGEID_RB1:1;
        unsigned TXCMSGEID_RTR:1;
        unsigned TXCMSGEID_EID:18;
        unsigned TXCMSGEID_IDE:1;
        unsigned TXCMSGEID_SRR:1;
        unsigned :2;
        unsigned TXCMSGDATA0_Byte0:8;
        unsigned TXCMSGDATA0_Byte1:8;
        unsigned TXCMSGDATA0_Byte2:8;
        unsigned TXCMSGDATA0_Byte3:8;
        unsigned TXCMSGDATA1_Byte4:8;
        unsigned TXCMSGDATA1_Byte5:8;
        unsigned TXCMSGDATA1_Byte6:8;
        unsigned TXCMSGDATA1_Byte7:8;
    };
    uint32_t TXMessage[4];
}CANTXBuffer;

typedef union
{
    struct
    {
        unsigned RXCMSGSID_SID:11;
        unsigned RXCMSGSID_FILHIT:5;
        unsigned RXCMSGSID_CMSGTS:16;
        unsigned RXCMSGEID_DLC:4;
        unsigned RXCMSGEID_RB0:1;
        unsigned :3;
        unsigned RXCMSGEID_RB1:1;
        unsigned RXCMSGEID_RTR:1;
        unsigned RXCMSGEID_EID:18;
        unsigned RXCMSGEID_IDE:1;
        unsigned RXCMSGEID_SRR:1;
        unsigned :2;
        unsigned RXCMSGDATA0_Byte0:8;
        unsigned RXCMSGDATA0_Byte1:8;
        unsigned RXCMSGDATA0_Byte2:8;
        unsigned RXCMSGDATA0_Byte3:8;
        unsigned RXCMSGDATA1_Byte4:8;
        unsigned RXCMSGDATA1_Byte5:8;
        unsigned RXCMSGDATA1_Byte6:8;
        unsigned RXCMSGDATA1_Byte7:8;
    };
    uint32_t RXMessage[4];
}CANRXBuffer;

CANTXBuffer *CAN2TXBuffer;
CAN2TXBuffer = (CANTXBuffer*)(PA_TO_KVA1(C2FIFOUA0));
//相应内容存储于以下
//CAN2TXBuffer->TXMessage[0]
//CAN2TXBuffer->TXMessage[1]
//CAN2TXBuffer->TXMessage[2]
//CAN2TXBuffer->TXMessage[3]
CANRXBuffer *CAN2RXBuffer1,*CAN2RXBuffer2,*CAN2RXBuffer3,*CAN2RXBuffer4;
CAN2RXBuffer1 = (CANRXBuffer*)(PA_TO_KVA1(C2FIFOUA1));
//相应内容存储于以下
//CAN2RXBuffer1->RXMessage[0]
//CAN2RXBuffer1->RXMessage[1]
//CAN2RXBuffer1->RXMessage[2]
//CAN2RXBuffer1->RXMessage[3]
CAN2RXBuffer2 = (CANRXBuffer*)(PA_TO_KVA1(C2FIFOUA2));
//相应内容存储于以下
//CAN2RXBuffer2->RXMessage[0]
//CAN2RXBuffer2->RXMessage[1]
//CAN2RXBuffer2->RXMessage[2]
//CAN2RXBuffer2->RXMessage[3]
CAN2RXBuffer3 = (CANRXBuffer*)(PA_TO_KVA1(C2FIFOUA3));
//相应内容存储于以下
//CAN2RXBuffer3->RXMessage[0]
//CAN2RXBuffer3->RXMessage[1]
//CAN2RXBuffer3->RXMessage[2]
//CAN2RXBuffer3->RXMessage[3]
CAN2RXBuffer4 = (CANRXBuffer*)(PA_TO_KVA1(C2FIFOUA4));
//相应内容存储于以下
//CAN2RXBuffer4->RXMessage[0]
//CAN2RXBuffer4->RXMessage[1]
//CAN2RXBuffer4->RXMessage[2]
//CAN2RXBuffer4->RXMessage[3]

PIC32MZ0512EFF相关的CAN配置相关教程

  1. find 命令示例_带有示例的Arp-Scan命令教程

    find 命令示例_带有示例的Arp-Scan命令教程 find 命令示例 Network scanning is one of the steps of penetration testing. There are different and popular tools to scan network line masscan, nmap etc. Arp-scan is a tool specifically designed to sc

  2. Cannot resolve com.jeesite:jeesite-module-swagger:4.2.1-SNAP

    Cannot resolve com.jeesite:jeesite-module-swagger:4.2.1-SNAPSHOT 问题原因 在使用jeesite中出现了 Cannot resolve com.jeesite:jeesite-module-swagger:4.2.1-SNAPSHOT报错 说明依赖没有导进 一、解决方法 maven仓库配置的是阿里云的仓库,把阿里云的仓库

  3. webpack-dev-server启动报错Error: Cannot find module ‘webpac

    webpack-dev-server启动报错Error: Cannot find module ‘webpack-cli/bin/config-yargs‘ 由于webpack-cli版本4,删除了webpack-cli/bin/config-yargs文件,看图bin目录下没有config-yargs.js 图上显示我们要下载webpack-cli版本3的依赖,流程如下: 1.卸载w

  4. MapReduce没有打印相关信息

    MapReduce没有打印相关信息 MapReduce没有打印相关信息 控制台输出显示 解决办法 1 2 控制台输出显示 显示Log4信息不全 1 在Resource类别文件夹下面创建 log4j.properties 文件 内容如下: log4j.rootLogger=INFO, stdoutlog4j.appender.stdout=org.apache.lo

  5. 小程序生成二维码海报的组件-wxa-plugin-canvas

    小程序生成二维码海报的组件-wxa-plugin-canvas 在小程序开发完成之后,我们会时常遇到这样的一个问题,小程序该怎么推广,增加曝光量,让更多的人看到?我们都知道,小程序推广一般是给小程序增加一个分享的功能,可以分享到群里面。 但是不能发朋友圈,若是

  6. Spring源码系列(九)MapperScan注解的原理(一)

    Spring源码系列(九)MapperScan注解的原理(一) 前面的博客已经写了 BeanFactoryPostProcessor 的执行的时机和顺序,同时也介绍了对应的扫描机制,笔者也通过模拟了一个自定义的注解来模拟MapperScan注解,但是由于篇幅的原因,笔者只简单的模拟了一下,今天笔

  7. 如何使用wpa_supplicant从命令行配置Linux无线

    如何使用wpa_supplicant从命令行配置Linux无线 wpa_supplicant is used to connect wireless networks. wpa_supplicant.conf file is used to store related configuration file about the wireless network. Also wireless security policy is configured wi

  8. masscan端口扫描_如何使用Masscan扫描顶部端口?

    masscan端口扫描_如何使用Masscan扫描顶部端口? masscan端口扫描 masscan is an alternative tool to the popular nmap . Actually masscan provides very less of the nmap but provides some huge adventages. masscan is designed to be fast and perform