
下面的CAN初始化函数感觉应该是覆盖了所有CAN功能设置(若有遗漏提醒我,我加进去),无死角! 参数一定让你有些难受,但我觉得总比实现不了什么,过不去坎要好点 //---------------------------- AHR_CAN.C -------------------------------------------------------------- #include "AHR_CAN.H" int CANx_BASE = (unsigned int)0x40006400; //CAN1_BASE:0x40006400;CAN2_BASE:0x40006800; 2019-0208 //----------------------------------------------------------------------------------------------------- //CAN初始化全功能函数: unsigned int regCAN_MCR=0x00010002,regCAN_MSR=0x00000C02,regCAN_BTR=0x01230000; //参数cfgCAN位图: 31 30 29 28, 27 26 25 24 ,23 22 21 20,19 18 17 16,F~C,B A 9 8,7~4,3~0 //*-过滤器的 BTR_SILM&LBKM 激活*关联,模式*位宽 SJW[1:0],-- TS2[2:0]时间段TS1[3:0],Number* ◆_BRP[9:0] // 0x200: FMR (过滤器主控寄存器) 0x240: 过滤器组寄存器的起始地址 // 0x204: FM1R(过滤器模式寄存器) 0x214:FFA1R(过滤器FIFO关联寄存器) // 0x20C: FS1R(过滤器位宽寄存器) 0x21C: FA1R(过滤器激活寄存器) // 31: SILM 静默模式(调试)(SilentMode) 0-正常状态;1-静默模式。 // 0-CAN_Mode_Normal // 30: LBKM 环回模式(调试)(LoopBackMode(debug)) 0-禁止;1-允许环回模式。// 1-CAN_Mode_LoopBack // 29: FACTi 软置1-激活相应过滤器。仅当该位=0或CAN_FMR_FINIT=1后才能修改相应过滤器组i(CAN_FiR[0:1]) // 28: 关联:报文在通过了某过滤器的过滤后,将被存放到其关联的FIFO中。0-过滤器被关联到FIFO0;1-FIFO1; // 27: 0-过滤器组i的2个32位寄存器工作在标识符屏蔽位模式;1-过滤器组i的2个32位REG工作在标识符列表模式 // 26: 位宽:0-过滤器位宽为2个16位;1-过滤器位宽为单个32位 v--(reSynchronizationJumpWidth) // 25~24: SJW[1:0] 重新同步跳跃宽度:为了重新同步,CAN硬件在每位中可延缩n个时间单元的上限 // 22~20: TS2[2:0] 时间段2(TimeSegment2) 定义时间段2占用多少时间单元 tBS2 = tCAN x (TS2[2:0] + 1) // 19~16: TS1[3:0] 时间段1(TimeSegment1) 定义时间段1占用多少时间单元 tBS1 = tCAN x (TS1[3:0] + 1) // 15~10: 过滤器寄存器组x的组号(下面用变量i表示); // 09~00: BRP[9:0] (Baud Rate Prescaler) 该位域定义了时间单元(tq)的时间长度tq = ( BRP[9:0] + 1) x tPCLK //参数idCANcfg位图: 23 22 21 20 , 19 18 17 16 //该参数若未设置则缺省:0xFFFFFF13 // TTCM ABOM AWUM NART , RFLM TXFP 保留高电位 // 07_.CAN_TTCM=0;非时间触发通信模式//06_.CAN_ABOM=0;软件自动离线管理 // 05_.CAN_AWUM=0; 睡眠由软件唤醒;1-测报文硬件唤醒//04_.CAN_NART=1-允许重传直到成功; 0-只传一次! // 03_.CAN_RFLM=0; 报文新覆盖旧的;1-锁一后文全丢;// 02_.CAN_TXFP=0;发送次序按(0-标识符;1-请求号) // 例如:initCANx_Mode(1,二进制[0010,0100,0111,1000,nnnn,nn00,0000,0100]=0x24780004,0,0); //if(initCANx_Mode(1,0x24780004,0,0)==0xABCFACE) LCD_ShowString(10,99,99,30,16,"InitCAN OK!");//500Kbps //原函数配置:CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,1);so波特率为: 42M/((6+7+1)*6)=500Kbps //CANx->BTR:"modeCAN<<30": 模式由SILM和LBKM两位决定: 0-正常;1-正常+环回;2-静默;3-静默+环回 // "tsjw<<24":重新同步跳跃宽度(2位)Tsjw =tsjw+1个时间单位 //"tBS2<<20":时间段2占用多少时间单元 // v-- 分频系数 Fdiv = brp + 1 //"tBS1<<16":时间段1占用多少时间单元 // "brp-1"(Baud Rate Prescaler)定义: 时间单元tq = ( BRP[9:0] + 1) * tPCLK //Fpclk1初始化为42M 波特率 = Fpclk1/( ( tbs1 + 1 + tbs2 + 1 + 1 ) * brp ); //----------------------------------------------------------------------------------------------------- int initCANx_Mode(int idCANcfg,int cfgCAN,int CFid,int CFidMsk){ //艾和荣 定稿: 2019-0208 int waitAck=0x00,retStat=0xBADFACE; //tsjw:重新同步跳跃时间单元.范围: CAN_SJW_1tq~4tq uint32_t fltNumBitPos=0, i; //brp :波特率分频器. 范围: 1~1024; tq = (brp) * tpclk1 switch(0xffff&idCANcfg){ case 1: CANx_BASE = (unsigned int)0x40006400; // GPIOA12 <=GPIO_Mode_AF_PP B-50MHz复用推挽输出 *(unsigned int*)0x4002101C|=0x02000000; //2-CAN1;RCC_APB1PeriphClockCmd(RCC...ph_CAN1,1); *(unsigned int*)0x40021018|=0x00000004; //4-A口;1-AFIO;//RCC_APB2PClkCmd(RCC.ph_GPIOA,1); *(unsigned int*)0x40010804&=0xFFFF8FFF; //位带何异?? GPIOA11<=GPIO_Mode_IPU *(unsigned int*)0x40010804|=0x000B8000; break;// GPIOA11<=GPIO_Mode_IPU 8-上拉输入 case 2: CANx_BASE = (unsigned int)0x40006800; // GPIOB13 <=GPIO_Mode_AF_PP B-50MHz复用推挽输出 *(unsigned int*)0x4002101C|=0x04000000; //4-CAN2; ** 只有互联型才有CAN2 ** *(unsigned int*)0x40021018|=0x00000008; //8-GPIOB;1-AFIO; *(unsigned int*)0x40010C04&=0xFFF8FFFF; //GPIOB12 <= GPIO_Mode_IPU *(unsigned int*)0x40010C04|=0x00B80000; break;// GPIOB12 <= GPIO_Mode_IPU default: break; //保留: 为了更多的CAN } //v--while:等<INAK==1且waitAck==0xFFFF>胜出■CANx_4:MSR_0:INAK=1-正初;0-初完 *(unsigned int*)(CANx_BASE+0x00)&=~0x02;//■CANx->MCR &=(~(uint32_t)CAN_MCR_SLEEP); <0-唤醒>;1-睡眠 *(unsigned int*)(CANx_BASE+0x00)|= 0x01;//■CANx->MCR |= CAN_MCR_INRQ ;<申请初始化> <1-初始>;0-工作 while((((*(unsigned int*)(CANx_BASE+0x04))&1)!=1)&&(waitAck!=0xffff)) waitAck++; if (((*(unsigned int*)(CANx_BASE+0x04))&0x01)==0) retStat=0xBADFACE; //0xBADFACE-错误;0xACCFACE-OK else{ //当 CAN_4:MSR_0:INAK=1说明正在初始化,则: if((0xffff0000&idCANcfg)==0) i= 0xFFFFFF13; else i = 0xFFFFFF00|(idCANcfg>>16); //MCR设置值 *(unsigned int*)(CANx_BASE+0x00) &= i; //■功能扩展设置 初稿:2019-0202 10:48 *(unsigned int*)(CANx_BASE+0x1C) =(cfgCAN&0xC37F03FF)-1;//■MSK:0xC37F03FF 由cfgCAN个性次序决定 *(unsigned int*)(CANx_BASE+0x00) &= 0xFFFFFFFE; //■清CAN_0:MCR_0:INRQ=0以退出初始化 for(waitAck = 0;(((*(unsigned int*)(CANx_BASE+0x04))&1)==1)&&(waitAck!=0xffff);waitAck++){;} if (((*(unsigned int*)(CANx_BASE+0x04))&0x01)==1) retStat = 0xBADFACE; // 0xBADFACE:约定失败. else retStat = 0xABCFACE; // 0xABCFACE:约定成功! } //以下CAN_FilterInit(&sCF); 等<INAK==0并waitAck==0xFFFF>胜出■CANx_4:MSR_0:INAK=0-初完;1-正初 i = (cfgCAN >> 10)&0x3F; fltNumBitPos = ((uint32_t)1) << i; *(unsigned int*)(CANx_BASE+0x200) |= 0x01;//过滤器正在初始化 CAN1->FMR|=FMR_FINIT;(FMR_FINIT=0x01) *(unsigned int*)(CANx_BASE+0x21C) &=~(uint32_t)fltNumBitPos;//FA1R:只有0-禁用(1-激活)fltNumBitPos对 if (((cfgCAN >> 26)&0x01)==0){ // 0-Scale=16位; ^-应的过滤组才能对该组初始化!化后置1 *(unsigned int*)(CANx_BASE+0x20C)&= ~(uint32_t)fltNumBitPos; //位宽 CAN1->FS1R&=~fltNumBitPos; *(unsigned int*)(CANx_BASE+0x240+(i*0x08)+0x00)=(0xFFFF&CFidMsk)<<16|(0xFFFF&CFid);// *(unsigned int*)(CANx_BASE+0x240+(i*0x08)+0x04)=(0xFFFF0000&CFidMsk)|(0xFFFF&(CFid>>16)); } //位宽=32在下;16在上3行:FR0:MaskIdLow|IdLow;FR1偏移4:MaskIdHigh|IdHigh if (((cfgCAN >> 26)&0x01)==1){ *(unsigned int*)(CANx_BASE+0x20C)|= fltNumBitPos; //CAN1->FS1R &= ~(uint32_t)fltNumBitPos; *(unsigned int*)(CANx_BASE+0x240+(i*0x08)+0x00)=CFid; //每组FR0+FR1各32位故*8,FR0与FR1偏移0x4 *(unsigned int*)(CANx_BASE+0x240+(i*0x08)+0x04)=CFidMsk;//每组FR1再加偏移故+4 } //0x204:FM1R=0表示过滤器组x(x=0~13|27)的2个32位寄存器工作在标识符屏蔽位模式;=1:列表模式。 if (((cfgCAN >> 27)&0x01)==0) *(unsigned int*)(CANx_BASE+0x204)&=~(uint32_t)fltNumBitPos; else *(unsigned int*)(CANx_BASE+0x204)|= (uint32_t)fltNumBitPos; //下面的0和1表示:CAN_Filter_FIFO1=1;CAN_Filter_FIFO0=0; >>27:Mode >>28:CF_FIFOAssignment if (((cfgCAN >> 28)&0x01)==0) *(unsigned int*)(CANx_BASE+0x214)&=~(uint32_t)fltNumBitPos; else *(unsigned int*)(CANx_BASE+0x214)|= (uint32_t)fltNumBitPos; if (((cfgCAN >> 29)&0x01)==1) *(unsigned int*)(CANx_BASE+0x21C)|= fltNumBitPos; // 29:CF_Activation *(unsigned int*)(CANx_BASE+0x200) &=~0x01; //过滤器初始化完毕(CANx_200:FMR_0:FINIT=0)FMR:过滤器主控 return retStat; } // <over 2019-0208 aiherong suncun> int CAN_SendMessage(u8* msg,u8 len){ //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧) CAN_TxMsg TxMsg; //参数:len - 数据长度(最大为8);msg - 数据指针,最大为8个字节. u8 mailBOX = 0; u16 i = 0; uint32_t sendST = 0; // send state TxMsg.StdId=0x12; // 标准标识符为0 TxMsg.ExtId=0x12; // 设置扩展标示符(29位) TxMsg.IDE=0; // 使用扩展标识符 TxMsg.RTR=0; // 消息类型为数据帧,一帧8位 TxMsg.DLC=len; // 发送两帧信息 for(i=0;i<len;i++) TxMsg.Data[i]=msg[i]; // 第一帧信息 if (((*(unsigned int*)(CANx_BASE+0x08))&CAN_TSR_TME0) == CAN_TSR_TME0) mailBOX = 0; else if (((*(unsigned int*)(CANx_BASE+0x08))&CAN_TSR_TME1) == CAN_TSR_TME1) mailBOX = 1; else if (((*(unsigned int*)(CANx_BASE+0x08))&CAN_TSR_TME2) == CAN_TSR_TME2) mailBOX = 2; else mailBOX = 4; // #define CAN_TxStatus_NoMailBox 0x04 if (mailBOX != 4){ // #define CAN_TxStatus_NoMailBox 0x04 (*(unsigned int*)(CANx_BASE+0x180))&=0x01;//sTxMailBox[mailBOX].TIR&=(~)TMIDxR_TXRQ;发完硬清? if(TxMsg.IDE==CANid_Std)(*(unsigned int*)(CANx_BASE+0x180))|=((TxMsg.StdId)<<21)|(TxMsg.RTR); else (*(unsigned int*)(CANx_BASE+0x180))|=(TxMsg.IDE)|((TxMsg.ExtId)<< 3)|(TxMsg.RTR); TxMsg.DLC &= (uint8_t)0x0000000F; (*(unsigned int*)(CANx_BASE+0x184))&= (uint32_t)0xFFFFFFF0; (*(unsigned int*)(CANx_BASE+0x184))|= TxMsg.DLC; (*(unsigned int*)(CANx_BASE+0x18C))= ((uint32_t)TxMsg.Data[7]<<24| //sTxMailBox[mailBOX].TDHR (uint32_t)TxMsg.Data[6]<<16|(uint32_t)TxMsg.Data[5]<< 8|(uint32_t)TxMsg.Data[4]); (*(unsigned int*)(CANx_BASE+0x188))= ((uint32_t)TxMsg.Data[3]<<24| //sTxMailBox[mailBOX].TDLR (uint32_t)TxMsg.Data[2]<<16|(uint32_t)TxMsg.Data[1]<< 8|(uint32_t)TxMsg.Data[0]); (*(unsigned int*)(CANx_BASE+0x180))|=0x01;//sTxMailBox[mailBOX].TIR|=TMIDxR_TXRQ;发送数据请求 } for (i=0;i<0xffff;i++){ //等待发送结束 switch (mailBOX){ case 0:sendST=(*(unsigned int*)(CANx_BASE+0x08))&0x04000003;break;//&(TSR_RQCP0|_TXOK0|_TME0) case 1:sendST=(*(unsigned int*)(CANx_BASE+0x08))&0x08000300;break;//&(TSR_RQCP1|_TXOK1|_TME1) case 2:sendST=(*(unsigned int*)(CANx_BASE+0x08))&0x10030000;break;//&(TSR_RQCP2|_TXOK2|_TME2) default:sendST = 0x00; break; //#define CAN_TxStatus_Failed 0x00 } switch (sendST) { case 0x00000000:sendST = 2; break; //#define CAN_TxStatus_Pending 0x02 case 0x04000001: //case (CAN_TSR_RQCP0|CAN_TSR_TME0): case 0x08000100: //case (CAN_TSR_RQCP1|CAN_TSR_TME1): case 0x10010000:sendST = 0; break; //case (CAN_TSR_RQCP2|CAN_TSR_TME2): CAN_TxStatus_Failed case 0x04000003: //case (CAN_TSR_RQCP0|CAN_TSR_TXOK0|CAN_TSR_TME0) case 0x08000300: //case (CAN_TSR_RQCP1|CAN_TSR_TXOK1|CAN_TSR_TME1) case 0x10030000:sendST = 1; break; //case 说明:仅当"位TSR_TXOKn=1"才算成功(CAN_TxStatus_Ok) default: sendST = 0; break; } if ((sendST==0x01)&&(i<0xffff)) return 0xAbcFace;//#define CAN_TxStatus_Ok 0x01 返回成功 } if(i>=0xffff) return 0xBadFace; // 返回 0xBadFace - 失败 return 0xABCFACE; // 返回 0xAbcFace - 成功 } int CAN_RecvMessage(u8 *buf,int fifoNO){ //can口接收数据查询 参数:buf-数据缓存区;fifoNO-0或1; CAN_RxMsg RxMsg; u32 i; // 20190202 0点 //返回值:0-没收到数; x-接收的数据长度 if((fifoNO==0)&&((*(unsigned int*)(CANx_BASE+0x0C)&0x03)!=0)|| (fifoNO==1)&&((*(unsigned int*)(CANx_BASE+0x10)&0x03)!=0)){ // 以下仅FIFO0,未包含FIFO1: RxMsg.IDE=0x04&(*(unsigned int*)(CANx_BASE+0x1B0));//->sFIFOMailBox[fifoNO].RIR;即:FIFO0_RI0R if(RxMsg.IDE==CANid_Std) RxMsg.StdId=0x000007FF & ((*(unsigned int*)(CANx_BASE+0x1B0)) >> 21); else RxMsg.ExtId=0x1FFFFFFF & ((*(unsigned int*)(CANx_BASE+0x1B0)) >> 3); RxMsg.RTR = 0x02& (*(unsigned int*)(CANx_BASE+0x1B0)); //CANx->sFIFOMailBox[fifoNO].RIR; RxMsg.DLC = 0x0F& (*(unsigned int*)(CANx_BASE+0x1B4)); //CANx->sFIFOMailBox[fifoNO].RDTR; RxMsg.FMI = 0xFF&((*(unsigned int*)(CANx_BASE+0x1B4))>> 8); //即:FIFO0_RDT0R >> 8 RxMsg.Data[0]= 0xFF& (*(unsigned int*)(CANx_BASE+0x1B8)); //即:FIFO0_RDL0R RxMsg.Data[1]= 0xFF&((*(unsigned int*)(CANx_BASE+0x1B8))>> 8); RxMsg.Data[2]= 0xFF&((*(unsigned int*)(CANx_BASE+0x1B8))>>16); RxMsg.Data[3]= 0xFF&((*(unsigned int*)(CANx_BASE+0x1B8))>>24); RxMsg.Data[4]= 0xFF& (*(unsigned int*)(CANx_BASE+0x1BC)); //即:FIFO0_RDH0R RxMsg.Data[5]= 0xFF&((*(unsigned int*)(CANx_BASE+0x1BC))>> 8); RxMsg.Data[6]= 0xFF&((*(unsigned int*)(CANx_BASE+0x1BC))>>16); RxMsg.Data[7]= 0xFF&((*(unsigned int*)(CANx_BASE+0x1BC))>>24); if (fifoNO == CAN_FIFO0) *(unsigned int*)(CANx_BASE+0x0C)|=0x20;//CANx->RF0R |= CAN_RF0R_RFOM0; else *(unsigned int*)(CANx_BASE+0x10)|=0x20;//CANx->RF1R |= CAN_RF1R_RFOM1; for(i=0;i<RxMsg.DLC;i++) buf[i]=RxMsg.Data[i]; return RxMsg.DLC; } else return 0; //无数可收故退出 } //-------------------------------------------------- End of AHR_CAN.C --------------------------------- //--------------------- AHR_CAN.H --------------------------------------------------------------------- #ifndef AHR_CANETHUSB_H #define AHR_CANETHUSB_H #include "aiherong.h" #define CAN_FIFO0 ((uint8_t)0x00) #define CAN_FIFO1 ((uint8_t)0x01) #define CANid_Std ((uint32_t)0x00000000) #define CANid_Ext ((uint32_t)0x00000004) typedef struct{ //发送邮箱有3个 uint32_t StdId; //标准ID uint32_t ExtId; //扩展ID uint8_t IDE; // 标识符选择 (Identifier extension) 0-标准符;1-扩展符 uint8_t RTR; //远程发送请求 (Remote transmission request) 0-数据帧;1-远程帧 uint8_t DLC; //发送数据长度 (Data length code)决定1个报文包含0~8几个字节数据 uint8_t Data[8]; // 8 位数据 } CAN_TxMsg; typedef struct{ //接收邮箱有2个 uint32_t StdId; //标准ID uint32_t ExtId; //扩展ID uint8_t IDE; // 标识符选择 (Identifier extension) 0-标准符;1-扩展符 uint8_t RTR; //远程发送请求 (Remote transmission request) 0-数据帧;1-远程帧 uint8_t DLC; //发送数据长度 (Data length code)决定1个报文包含0~8几个字节数据 uint8_t Data[8]; // 8 位数据 uint8_t FMI; //过滤器匹配序号(Filter match index) } CAN_RxMsg; //CAN初始化 缺省映射F1:CAN1_RX ![]() ![]() ![]() ![]() int initCANx_Mode(int idCANcfg,int cfgCAN,int CFid,int CFidMsk);//(参数1高16位可设置且仅F103后才有CAN2) int CAN_SendMessage(u8* msg, u8 len); //发送数据 int CAN_RecvMessage(u8 *buf,int fifoNO); //接收数据 #endif //-------------------------------------------------- End of AHR_CAN.H --------------------------------- |
不挣钱的日子跟没头苍蝇一般,己快看不懂世界了