附录1. FDCAN寄存器配置
返回第7章 FDCAN的初始化
返回第9章 接收操作
- /**
- * @description: FDCAN1 初始化
- * @param {*}
- * @return {*}
- * @author: XL
- */
- void FDCAN1_Function_Init(void)
- {
- //在RCC_CCIPR寄存器中选择FDCAN时钟为HSE,即8MHz
- //
- FDCAN1->CCCR |= FDCAN_CCCR_INIT; //步骤3 置位INIT标志,开始配置寄存器(只有INIT标志位置位,才可置位CCE标志位)
- while (!(FDCAN1->CCCR & FDCAN_CCCR_INIT)); //步骤4 等待INIT标志位置位
- FDCAN1->CCCR |= FDCAN_CCCR_CCE; //步骤5 置位CCE标志位,解锁受保护的寄存器
- while (!(FDCAN1->CCCR & FDCAN_CCCR_CCE)); //步骤6 等待CCE标志位置位
- FDCAN_CONFIG->CKDIV = 0x0; //步骤7 配置时钟分频
- //只允许在FDCAN1初始化中配置
- //fdcan_clk = 168 / 1 = 168 MHz,影响到FDCAN2、3(FDCAN_CONFIG地址上来说,还是属于FDCAN1)
- FDCAN1->CCCR |= 0
- // |FDCAN_CCCR_NISO //bit15: 【0|ISO11898-1】【1|CANFD v1.0】
- // |FDCAN_CCCR_TXP //bit14: 【1|在下上一个成功帧后暂停两个bit再起始】
- // |FDCAN_CCCR_EFBI //bit13: 【1|同步检测边沿需要两个显性tq】
- // |FDCAN_CCCR_PXHD //bit12: 【0|启动协议异常处理】【1|禁用协议异常处理】
- // |FDCAN_CCCR_BRSE //bit09: 【1|启用波特率切换】
- // |FDCAN_CCCR_FDOE //bit08: 【0|FD操作禁止】【1|FD操作使能】
- // |FDCAN_CCCR_TEST //bit07: 【1|测试模式使能】
- |FDCAN_CCCR_DAR //bit06: 【0|启用发送失败后自动重传】【1|禁止自动重传】
- // |FDCAN_CCCR_MON //bit05: 【0|总线监控模式禁止】【1|总线监控模式使能】
- // |FDCAN_CCCR_CSR //bit04: 【0|无时钟停止请求】【1|时钟停止请求,当时钟停止请求发生,先置位INIT在置位CSA在所有传输请求完成并且CAN总线空闲】
- // |FDCAN_CCCR_CSA //bit03: 【0|没有时钟停止】【1|FDCAN可通过停止APB时钟和内核时钟来进行掉电】
- // |FDCAN_CCCR_ASM //bit02: 【1|启用限制模式,限制模式下不会主动发送数据】
- // |FDCAN_CCCR_CCE //bit01: 【1|允许配置受保护的寄存器,INIT标志位必须置位】
- // |FDCAN_CCCR_INIT //bit00: 【1|初始化开始】
- ;
- // FDCAN1->DBTP = 0 //数据帧的波特率(FDCAN模式需要配置,经典CAN不需要配置)
- // |FDCAN_DBTP_TDC //bit23: 【1|收发延时补偿使能】
- // |(0 << FDCAN_DBTP_DBRP_Pos) //bit[20:16]: tq = (BRP + 1)*fdcan_clk
- // |(22 << FDCAN_DBTP_DTSEG1_Pos) //bit[12:08]: 一阶段采样 8000000
- // |(7 << FDCAN_DBTP_DTSEG2_Pos) //bit[07:04]: 二阶段采样 波特率 = 8000000/(3+DTSEG1+DTSEG2) = 8000000/32 = 250k
- // |(4 << FDCAN_DBTP_DSJW_Pos) //bit[03:00]: 同步脉宽
- // ;
- FDCAN1->NBTP = 0 //步骤8 配置波特率
- |(4 << FDCAN_NBTP_NSJW_Pos) //bit[31:25]: 同步脉宽 必须小于SEG2
- |(0 << FDCAN_NBTP_NBRP_Pos) //bit[24:16]: BRP tq = (BRP + 1)*fdcan_clk
- |(22 << FDCAN_NBTP_NTSEG1_Pos) //bit[15:08]: 一阶段采样
- |(7 << FDCAN_NBTP_NTSEG2_Pos) //bit[06:00]: 二阶段采样 波特率 = 8000000/(3+DTSEG1+DTSEG2) = 8000000/32 = 250k
- ;
- //步骤9 配置中断
- FDCAN1->IE |= 0
- // |FDCAN_IE_ARAE //bit23: 访问保留地址使能
- // |FDCAN_IE_PEDE //bit22: 数据阶段协议错误
- // |FDCAN_IE_PEAE //bit21: 仲裁阶段协议错误
- // |FDCAN_IE_WDIE //bit20: 看门狗使能
- // |FDCAN_IE_BOE //bit19: 总线关闭使能
- // |FDCAN_IE_EWE //bit18: 警告状态中断使能
- // |FDCAN_IE_EPE //bit17: 错误被动中断使能
- // |FDCAN_IE_ELOE //bit16: 错误记录语出中断使能
- // |FDCAN_IE_TOOE //bit15: 超时中断使能
- // |FDCAN_IE_MRAFE //bit14: 信息RAM访问失败中断使能
- // |FDCAN_IE_TSWE //bit13: 时间戳重复中断使能
- // |FDCAN_IE_TEFLE //bit12: TX事件FIFO元素丢失中断使能
- // |FDCAN_IE_TEFFE //bit11: TX时间FIFO满中断使能
- // |FDCAN_IE_TEFNE //bit10: TX事件FIFO新元素进入中断使能
- // |FDCAN_IE_TFEE //bit09: TXFIFO空中断使能
- // |FDCAN_IE_TCFE //bit08: 发送取消完成中断使能
- // |FDCAN_IE_TCE //bit07: 传输完成中断使能
- // |FDCAN_IE_HPME //bit06: 高优先级消息中断使能
- // |FDCAN_IE_RF1LE //bit05: RXFIFO1报文丢失中断使能
- // |FDCAN_IE_RF1FE //bit04: RXFIFO1消息满中断使能
- |FDCAN_IE_RF1NE //bit03: RXFIFO1新消息中断使能
- // |FDCAN_IE_RF0LE //bit02: RXFIFO0报文丢失中断使能
- // |FDCAN_IE_RF0FE //bit01: RXFIFO0消息满中断使能
- |FDCAN_IE_RF0NE //bit00: RXFIFO0新消息中断使能
- ;
- FDCAN1->ILE = 0x00000000
- |FDCAN_ILE_EINT1 //bit01: 中断总线 fdcan_intr1_it 使能
- |FDCAN_ILE_EINT0 //bit00: 中断总线 fdcan_intr0_it 使能
- ;
- FDCAN1->ILS = 0x00000000 //中断总线选择
- // |FDCAN_ILS_PERR //bit06:
- // ARAL: Access to reserved address line
- // PEDL: Protocol error in data phase line
- // PEAL: Protocol error in arbitration phase line
- // WDIL: Watchdog interrupt line
- // BOL: Bus_Off status
- // EWL: Warning status interrupt line
- // |FDCAN_ILS_BERR //bit05:
- // ELOL: Error logging overflow interrupt line
- // |FDCAN_ILS_MISC //bit04:
- // TOOL: Timeout occurred interrupt line
- // MRAFL: Message RAM access failure interrupt line
- // TSWL: Timestamp wraparound interrupt line
- // |FDCAN_ILS_TFERR //bit03:
- // TEFLL: Tx event FIFO element lost interrupt line
- // TEFFL: Tx event FIFO full interrupt line
- // TEFNL: Tx event FIFO new entry interrupt line
- // TFEL: Tx FIFO empty interrupt line
- // |FDCAN_ILS_SMSG //bit02:
- // TCFL: Transmission cancellation finished interrupt line
- // TCL: Transmission completed interrupt line
- // HPML: High-priority message interrupt line
- |FDCAN_ILS_RXFIFO1 //bit01:当邮箱1的事件在 fdcan1_intr1_it 中断分支中处理
- // RF1LL: Rx FIFO 1 message lost interrupt line
- // RF1FL: Rx FIFO 1 full Interrupt line
- // RF1NL: Rx FIFO 1 new message interrupt line
- // |FDCAN_ILS_RXFIFO0 //bit00:当邮箱0的事件在 fdcan1_intr0_it 中断分支中处理
- // RF0LL: Rx FIFO 0 message lost interrupt line
- // RF0FL: Rx FIFO 0 full interrupt line
- // RF0NL: Rx FIFO 0 new message interrupt line
- ;
- //步骤9 结束
- //步骤10 使能筛选器
- FDCAN1->RXGFC |= 0
- |(1 << FDCAN_RXGFC_LSE_Pos) //bit[27:24]: 列表信息拓展【0|无拓展消息过滤】【1|1~8拓展消息】【>8|被解释为8】
- |(2 << FDCAN_RXGFC_LSS_Pos) //bit[20:16]: 【0|无标准消息ID过滤】【1~28|标准消息ID元素过滤数量】【>28|被解释为28】
- // |FDCAN_RXGFC_F0OM //bit09: FIFO0模式:覆盖或者堵塞【0|阻塞模式】【1|覆盖模式】
- // |FDCAN_RXGFC_F1OM //bit08: FIFO1模式:覆盖或者堵塞【0|阻塞模式】【1|覆盖模式】
- |(2 << FDCAN_RXGFC_ANFS_Pos) //bit[05:04]: 定义如何处理接收到的id为11位且与筛选器列表中的任何元素不匹配的消息。【0|在FIFO0中接收】【1|在FIFO1中接收】【2~3|拒绝】
- |(2 << FDCAN_RXGFC_ANFE_Pos) //bit[03:02]: 定义如何处理接收到的id为29位且与筛选器列表中的任何元素不匹配的消息。【0|在FIFO0中接收】【1|在FIFO1中接收】【2~3|拒绝】
- |FDCAN_RXGFC_RRFS //bit01: 【1|拒绝所有11位ID远程标准帧】
- |FDCAN_RXGFC_RRFE //bit00: 【1|拒绝所有29位ID远程标准帧】
- ;
- // FDCAN1->XIDAM = 0x1FFFFFFF; //FDCAN 扩展 ID 和屏蔽寄存器
- // FDCAN1->TXBTIE = 0
- // // |0x00000004 //bit02: TxBuffer【1|发送中断使能】
- // // |0x00000002 //bit01: TxBuffer【1|发送中断使能】
- // |0x00000001 //bit00: TxBuffer【1|发送中断使能】
- // ;
- // FDCAN1->TXBCIE = 0
- // // |0x00000004 //bit02: TxBuffer【1|取消中断使能】
- // // |0x00000002 //bit01: TxBuffer【1|取消中断使能】
- // // |0x00000001 //bit00: TxBuffer【1|取消中断使能】
- // ;
- //步骤11 配置筛选器
- FDCAN1_RAM->FILTER_11BIT[0] = 0x00000000
- |(1 << FDCANx_RAM_FILTER11_S0_SFT_Pos) //【0|范围过滤,从SFID1~SFID2】【1|单独滤波SFID1和SFID2】【2|经典滤波】【3|禁用过滤】
- |(1 << FDCANx_RAM_FILTER11_S0_SFEC_Pos) //【0|禁用过滤元件】【1|匹配存储在FIFO0】【2|匹配存储在FIFO1】【3|匹配存就拒绝】【4|匹配设置优先级】【5|匹配设置优先级并存储到FIFO0中】【6|匹配设置优先级并存储到FIFO1中】【7|保留】
- |(0x600 << FDCANx_RAM_FILTER11_S0_SFID1_Pos) //【SFID1】
- |(0x609 << FDCANx_RAM_FILTER11_S0_SFID2_Pos) //【SFID2】
- ;//列表滤波,只接收 ID为0x600和0x609 的数据,并且这两个ID放入FIFO0中
- FDCAN1_RAM->FILTER_11BIT[1] = 0x00000000
- |(1 << FDCANx_RAM_FILTER11_S0_SFT_Pos) //【0|范围过滤,从SFID1~SFID2】【1|单独滤波SFID1和SFID2】【2|经典滤波】【3|禁用过滤】
- |(2 << FDCANx_RAM_FILTER11_S0_SFEC_Pos) //【0|禁用过滤元件】【1|匹配存储在FIFO0】【2|匹配存储在FIFO1】【3|匹配存就拒绝】【4|匹配设置优先级】【5|匹配设置优先级并存储到FIFO0中】【6|匹配设置优先级并存储到FIFO1中】【7|保留】
- |(0x209 << FDCANx_RAM_FILTER11_S0_SFID1_Pos) //【SFID1】
- |(0x209 << FDCANx_RAM_FILTER11_S0_SFID2_Pos) //【SFID2】
- ;//列表滤波,只接收 ID为0x209 的数据,并且这个ID放入FIFO1中
- FDCAN1_RAM->FILTER_29BIT[0][0] = 0x00000000
- |(1 << FDCANx_RAM_FILTER29_F0_EFEC_Pos) //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
- |(0x0CCCCCCC << FDCANx_RAM_FILTER29_F0_EFID1_Pos) //【EFID1】
- ;
- // FDCAN1_RAM->FILTER_29BIT[0][1] = 0x00000000
- // |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos) //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos) //【EFID2】
- // ;
- // FDCAN1_RAM->FILTER_29BIT[1][0] = 0x00000000
- // |(1 << FDCANx_RAM_FILTER29_F0_EFEC_Pos) //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F0_EFID1_Pos) //【EFID1】
- // ;
- // FDCAN1_RAM->FILTER_29BIT[1][1] = 0x00000000
- // |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos) //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos) //【EFID2】
- // ;
- // FDCAN1_RAM->FILTER_29BIT[2][0] = 0x00000000
- // |(1 << FDCANx_RAM_FILTER29_F0_EFEC_Pos) //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F0_EFID1_Pos) //【EFID1】
- // ;
- // FDCAN1_RAM->FILTER_29BIT[2][1] = 0x00000000
- // |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos) //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos) //【EFID2】
- // ;
- // FDCAN1_RAM->FILTER_29BIT[3][0] = 0x00000000
- // |(2 << FDCANx_RAM_FILTER29_F0_EFEC_Pos) //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F0_EFID1_Pos) //【EFID1】
- // ;
- // FDCAN1_RAM->FILTER_29BIT[3][1] = 0x00000000
- // |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos) //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos) //【EFID2】
- // ;
- // FDCAN1_RAM->FILTER_29BIT[4][0] = 0x00000000
- // |(2 << FDCANx_RAM_FILTER29_F0_EFEC_Pos) //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F0_EFID1_Pos) //【EFID1】
- // ;
- // FDCAN1_RAM->FILTER_29BIT[4][1] = 0x00000000
- // |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos) //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
- // |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos) //【EFID2】
- // ;
- //步骤12 清除INIT标志位
- FDCAN1->CCCR &= ~FDCAN_CCCR_INIT;//退出初始化模式,CCE会自动清除
- while (FDCAN1->CCCR & FDCAN_CCCR_INIT);//等待退出
- }
复制代码
附录2 发送函数
返回第8章 发送操作
- /**
- * @description: 发送11位地址的报文
- * @param {uint8_t} FDCAN_Index FDCANx 1~3 FDCAN外设索引使用FDCAN1/2/3
- * @param {uint16_t} ID 11位ID发送
- * @param {uint8_t} RTR 0-数据帧 1-远程帧
- * @param {uint8_t} DLC 数据长度 0~8
- * @param {Buffer_72Byte_Struct} *buffer 发送数组地址
- * @return {uint8_t} SUCCEED/FAILED/ERROR
- * @author: XL
- */
- uint8_t FDCAN_11ID_SendData(uint8_t FDCAN_Index, uint16_t ID,uint8_t RTR,uint8_t DLC,Buffer_72Byte_Struct *buffer)
- {
- uint8_t Free_Mailbox;//空闲邮箱索引
- FDCAN_RAM_Struct* FDCAN_RAM;//FDCANx_RAM指针
- FDCAN_GlobalTypeDef* FDCAN;//FDCANx指针
- switch (FDCAN_Index)//根据索引确定使用FDCANx
- {
- case 1:
- FDCAN_RAM = FDCAN1_RAM;
- FDCAN = FDCAN1;
- break;
- case 2:
- FDCAN_RAM = FDCAN2_RAM;
- FDCAN = FDCAN2;
- break;
- case 3:
- FDCAN_RAM = FDCAN3_RAM;
- FDCAN = FDCAN3;
- break;
- default:
- return ERROR;//输入索引错误,无效
- break;
- }
- if(FDCAN->TXFQS & FDCAN_TXFQS_TFQF)
- { //CanBus判断是否有空闲的发送寄存器,然后发送,否则等待
- return FAILED;//没有空闲邮箱
- }
- else
- { //只要第一个邮箱空闲,始终先使用第一个,然后是第二个,第三个邮箱
- Free_Mailbox = ((uint8_t)(FDCAN->TXFQS >> 16)) & 0x03;//获取空闲邮箱
- FDCAN_RAM->Tx_BUFFER[Free_Mailbox][0] = ((uint32_t)ID << FDCANx_RAM_TxBuffer_T0_11ID_Pos);//写入地址
- FDCAN_RAM->Tx_BUFFER[Free_Mailbox][1] = (DLC << FDCANx_RAM_TxBuffer_T1_DLC_Pos);//发送长度
- FDCAN_RAM->Tx_BUFFER[Free_Mailbox][2] = buffer->DataWord[0];//发送的数据
- FDCAN_RAM->Tx_BUFFER[Free_Mailbox][3] = buffer->DataWord[1];//发送的数据
- FDCAN->TXBAR |= (0x0001 << Free_Mailbox);//置位发送请求
- return SUCCEED;//返回成功
- }
- }
复制代码
|