can控制器_can控制器芯片有哪些 - CSDN
精华内容
参与话题
  • CAN控制器-配置过滤器

    千次阅读 2015-09-17 10:38:32
    首先简单介绍一下CAN总线,关于CAN总线是谁发明的,CAN总线的历史,CAN总线的发展,CAN总线的应用场合,这些,通通不说。这里只是以我个人理解,简单说说CAN通信。CAN总线的端点没有地址(除非自己在帧里定义地址)...

    首先简单介绍一下CAN总线,关于CAN总线是谁发明的,CAN总线的历史,CAN总线的发展,CAN总线的应用场合,这些,通通不说。这里只是以我个人理解,简单说说CAN通信。CAN总线的端点没有地址(除非自己在帧里定义地址),CAN总线通信不用地址,用标识符,不是单独的谁发给谁,而是,你总是发送给整个网络。然后每个节点都有过滤器,对网络上的传播的帧的标识符进行过滤,自己想要什么样的帧,可以设置自己的过滤器,接收相关的帧信息。如果两个节点同时发送怎么办?这个不用我们担心,CAN控制器会自己仲裁,让高优先级的帧先发。

             然后我们可以了解一下stm32的CAN控制器。


             如上图所示,stm32有两个can控制器,can1(主),和can2(从),其中过滤器的设置是通过can1来设置,其他工作模式,波特率等,可以各自设置。每个控制器有三个发送邮箱,两个fifo,每个fifo有三个接收邮箱。



             发送:选择一个空的发送邮箱,把帧信息写到该发送邮箱的寄存器里,请求发送,控制器就会根据标识符的优先级把帧先后发送出去。

             接收:如果接收到的帧的标识符能过过滤表的一系列过滤,该帧信息就会保存在fifo接收邮箱的寄存器里。

             过滤器:stm32f407共有28组过滤器,每组过滤器可以设置关联到fifo0或者fifo1,每组都包括两个32位存储器,可以配置成一个32位有位屏蔽功能的标识符过滤器,或者两个32位完全匹配的标识符过滤器,或者两个16位有位屏蔽功能的标识符过滤器,或者四个16位完全匹配的标识符过滤器。如下图所示:



    我所说的完全匹配的意思是,接收到的帧的标识符每一位都要跟过滤器对应的位一样,才能过得了这个过滤器。有位屏蔽功能的意思是一个寄存器放标识符,一个放屏蔽掩码,屏蔽掩码为1的位对应的接收到的帧的标识符的位与对应的放标识符的寄存器的位一致,就能通过。


    为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。 
    为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。 
    应用程序不用的过滤器组,应该保持在禁用状态。 
    过滤器组中的每个过滤器,都被编号为(叫做过滤器号,图 32.1.11 中的 n)从 0 开始,到某
    最大数值-取决于过滤器组的模式和位宽的设置。 
    举个简单的例子,我们设置过滤器组 0 工作在:1 个 32 位过滤器-标识符屏蔽模式,然后
    置 CAN_F0R1=0XFFFF0000,CAN_F0R2=0XFF00FF00。其中存放到 CAN_F0R1 的值就是期
    收到的 ID,即我们希望收到的 ID(STID+EXTID+IDE+RTR)最好是:0XFFFF0000。而
    FF00FF00 就是设置我们需要必须关心的 ID,表示收到的 ID,其位[31:24]和位[15:8]这 16 个
    的必须和 CAN_F0R1 中对应的位一模一样,而另外的 16 个位则不关心,可以一样,也可以
    一样,都认为是正确的 ID,即收到的 ID必须是 0XFFxx00xx,才算是正确的(x 表示不关心)。




    传输一位的时间和波特率的计算:

     

             CAN控制器的波特率是由APB时钟线和CAN位时序寄存器CAN_BTR的TS2[3:0]、TS1[2:0]和BRP[9:0]确定的,其中,TS1[2:0]定义了时间段1占用多少个时间单元,TS2[3:0]定义了时间段2占用多少个时间单元,BRP[9:0]定义对APB1时钟的分频。

     

    PS:设置波特率为1M


    其中Tpclk为APB1的时钟周期,假设为

    Tpclk = 1/42M

    0≦TS1≦7

    0≦TS2≦15

    0≦BRP≦1021

    根据以上数据,有

    (TS2+TS1+3)(BRP+1)=42

    令BRP=2,有

    TS2+TS1=11

    令TS1=8,TS2=3

     

     



    设置步骤:

    1.     设置中断优先级分组(如果之前没有设置),这个最好一个程序里只在开头设置一次。

    2.     使能相关GPIO时钟。

    3.     选择相关GPIO引脚的复用功能。

    4.     设置相关GPIO引脚为复用模式。

    5.     设置相关GPIO引脚的速度,方式。

    6.     设置主控制寄存器MCR,进入初始化模式

    7.     等待进入初始化模式

    8.     设置波特率。

    9.     其他设置。

    10.  如果要用到中断,在中断使能寄存器IER中使能相关中断响应。

    11.  如果要用到中断,设置相关中断优先级(NVIC_IP)。

    12.  如果要用到中断,使能相关中断(NVIC_ISER)。

    13.  设置主控制寄存器MCR,进入正常工作模式。

    14.  设置FMR,使过滤器组工作在初始化模式。

    15.  设置FMR的CAN2SB,确定CAN2的过滤器组从哪一组开始。

    16.  设置用到的过滤器组的工作方式。

    17.  设置用到的过滤器组的位宽。

    18.  给fifo0和fifo2划分(关联)过滤组。

    19.  禁用用到的过滤器组。

    20.  设置过滤器组的标识符,帧类型等。

    21.  使能相关过滤器组。

    22.  设置FMR,使过滤器组工作在正常模式。

    23.  如果要用中断,编写中断服务函数(函数名是固定的)。

    24.  中断服务函数里检查是哪个中断。

    25.  编写相应服务程序。

     

    电路请参见本博客:小工具之——CAN收发器 


    程序:

    1. /************************************  
    2.     标题:操作CAN的练习  
    3.     软件平台:IAR for ARM6.21  
    4.     硬件平台:stm32f4-discovery  
    5.     主频:168M  
    6.       
    7.     描述:通过硬件收发器连接CAN1,CAN2  
    8.           组成一个两个端点的网络  
    9.   
    10.           CAN1循环发出数据帧  
    11.   
    12.           CAN2接收过滤数据帧  
    13.   
    14.           用uart把CAN2接收到  
    15.           的数据帧发到超级终端  
    16.   
    17.     author:小船  
    18.     data:2012-08-14  
    19. *************************************/  
    20.   
    21. #include <stm32f4xx.h>   
    22. #include "MyDebugger.h"  
    23.   
    24. #define RECEIVE_BUFFER_SIZE 20  
    25.   
    26. u32 CAN2_receive_buffer[RECEIVE_BUFFER_SIZE][4];  
    27. u8 UART_send_buffer[1800];  
    28. u8 Consumer = 0;  
    29. u8 Producer = 0;  
    30.   
    31. u32 Gb_TimingDelay;  
    32. void Delay(uint32_t nTime);  
    33. void TIM7_init();//定时1s  
    34. u32 get_rece_data();  
    35. void CAN_GPIO_config();  
    36.   
    37. void main ()  
    38. {     
    39.   
    40.   u32 empty_box;  
    41.   SysTick_Config(SystemCoreClock / 1000); //设置systemtick一毫秒中断  
    42.   SCB->AIRCR = 0x05FA0000 | 0x400;  //中断优先级分组 抢占:响应=3:1  
    43.    
    44.   MyDebugger_Init();  
    45.   TIM7_init();  
    46.   MyDebugger_Message( "\n\rtesting......\n\r" ,   
    47.                      sizeof("\n\rtesting......\n\r")/sizeof(char) );  
    48.     
    49.   CAN_GPIO_config();  
    50.     
    51.   RCC->APB1ENR |= ((1<<25)|(1<<26));//使能CAN1、CAN2时钟  
    52.     
    53.   CAN1->MCR = 0x00000000;  
    54.   /*  
    55.   请求进入初始化模式  
    56.   禁止报文自动重传  
    57.   自动唤醒模式  
    58.   */  
    59.   CAN1->MCR |= ((1<<0)|(1<<4)|(1<<5));  
    60.   CAN1->MCR &= ~(1<<16);//在调试时,CAN照常工作  
    61.     
    62.   while(!(CAN1->MSR & 0xfffffffe))  //等待进入初始化模式  
    63.   {  
    64.     MyDebugger_LEDs(orange, on);  
    65.   }  
    66.   MyDebugger_LEDs(orange, off);  
    67.     
    68.   /*  
    69.   正常模式  
    70.   重新同步跳跃宽度(1+1)tq  
    71.   TS2[2:0]=3  
    72.   TS1[3:0]=8  
    73.   BRP[9:0]=2  
    74.     
    75.   ps:  
    76.   tq = (BRP[9:0] + 1) x tPCLK,  
    77.   tBS2 = tq x (TS2[2:0] + 1),  
    78.   tBS1 = tq x (TS1[3:0] + 1),  
    79.   NominalBitTime = 1 × tq+tBS1+tBS2,  
    80.   BaudRate = 1 / NominalBitTime  
    81.     
    82.   波特率设为1M  
    83.   */  
    84.   CAN1->BTR = ((0<<30)|(0x01<<24)|(3<<20)|(8<<16)|(2<<0));  
    85.     
    86.   CAN1->MCR &= ~(0x00000001);//正常工作模式  
    87.     
    88.   CAN2->MCR = 0x00000000;  
    89.   /*  
    90.   请求进入初始化模式  
    91.   禁止报文自动重传  
    92.   自动唤醒模式  
    93.   */  
    94.   CAN2->MCR |= ((1<<0)|(1<<4)|(1<<5));  
    95.   CAN2->MCR &= ~(1<<16);//在调试时,CAN照常工作  
    96.     
    97.   while(!(CAN2->MSR & 0xfffffffe))  //等待进入初始化模式  
    98.   {  
    99.     MyDebugger_LEDs(orange, on);  
    100.   }  
    101.   MyDebugger_LEDs(orange, off);  
    102.     
    103.   /*  
    104.   正常模式  
    105.   重新同步跳跃宽度(1+1)tq  
    106.   TS2[2:0]=3  
    107.   TS1[3:0]=8  
    108.   BRP[9:0]=2  
    109.     
    110.   ps:  
    111.   tq = (BRP[9:0] + 1) x tPCLK,  
    112.   tBS2 = tq x (TS2[2:0] + 1),  
    113.   tBS1 = tq x (TS1[3:0] + 1),  
    114.   NominalBitTime = 1 × tq+tBS1+tBS2,  
    115.   BaudRate = 1 / NominalBitTime  
    116.     
    117.   波特率设为1M  
    118.   */  
    119.   CAN2->BTR = ((0<<30)|(0x01<<24)|(3<<20)|(8<<16)|(2<<0));  
    120.     
    121.   CAN2->IER &= 0x00000000;  
    122.   /*  
    123.   FIFO1消息挂号中断使能  
    124.   FIFO1满中断使能  
    125.   FIFO1溢出中断使能  
    126.   */  
    127.   CAN2->IER |= ((1<<4)|(1<<5)|(1<<6));  
    128.     
    129.     
    130.   NVIC->IP[65] = 0xa0;   //抢占优先级101,响应优先级0   
    131.   NVIC->ISER[2] |= (1<<1);  //使能中断线65,也就是can2_rx1中断  
    132.     
    133.   CAN2->MCR &= ~(0x00000001);//正常工作模式  
    134.     
    135.     
    136.   //总共有28组过滤器  
    137.   CAN1->FMR |= 1; //过滤器组工作在初始化模式  
    138.     
    139.   CAN1->FMR &= 0xffffc0ff;//CAN2的过滤器组从14开始  
    140.   CAN1->FMR |= (14<<8);  
    141.     
    142.   CAN1->FM1R |= (1<<14);//过滤器组14的寄存器工作在标识符列表模式  
    143.                          
    144.                         //位宽为16位,2个32位分为四个16位寄存器,过滤四个标识符  
    145.     
    146.   //CAN1->FS1R |= (1<<15);//过滤器组15为单个32位寄存器,用于扩展标识符  
    147.     
    148.   CAN1->FFA1R = 0x0fffc000;//0~13号过滤器组关联到fifo0,14~27号过滤器组关联到fifo1  
    149.     
    150.   CAN1->FA1R &= ~(1<<14);//禁用过滤器组14  
    151.     
    152.    /*  
    153.   过滤器组0寄存器分为4个十六位过滤器:  
    154.   标识符列表:  
    155.   过滤器编号        匹配标准标识符             RTR       IDE           EXID[17:15]  
    156.      0              0x7cb(111 1100 1011b)    数据帧    标准标识符     000b  
    157.      1              0x4ab(100 1010 1011b)    数据帧    标准标识符     000b  
    158.      2              0x7ab(111 1010 1011b)    数据帧    标准标识符     000b    
    159.      3              0x40b(100 0000 1011b)    数据帧    标准标识符     000b    
    160.   */  
    161.   CAN1->sFilterRegister[14].FR1 &= 0x00000000;  
    162.   CAN1->sFilterRegister[14].FR2 &= 0x00000000;  
    163.   CAN1->sFilterRegister[14].FR1 |= ((0x7cb<<5)|(0<<4)|(0<<3));  
    164.   CAN1->sFilterRegister[14].FR1 |= ((0x4ab<<21)|(0<<20)|(0<<19));  
    165.   CAN1->sFilterRegister[14].FR2 |= ((0x7ab<<5)|(0<<4)|(0<<3));  
    166.   CAN1->sFilterRegister[14].FR2 |= ((0x40b<<21)|(0<<20)|(0<<19));  
    167.     
    168.   CAN1->FA1R |= (1<<14);//使能过滤器组14  
    169.      
    170.   CAN1->FMR &= ~1; //过滤器组正常工作  
    171.     
    172.   while(1)  
    173.   {  
    174.     /*  
    175.     选择空的发送邮箱:  
    176.     标准标识符0x7ab(111 1010 1011b)  
    177.     数据帧  
    178.     不使用扩展标识符  
    179.     */  
    180.     if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )  
    181.     {  
    182.       empty_box = ((CAN1->TSR>>24) & 0x00000003);   
    183.       CAN1->sTxMailBox[empty_box].TIR = (0x7ab<<21);    
    184.         
    185.       CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;  
    186.       CAN1->sTxMailBox[empty_box].TDTR |= 0x00000008;//发送数据长度为8  
    187.         
    188.       CAN1->sTxMailBox[empty_box].TDLR = 0x12345678;  
    189.         
    190.       CAN1->sTxMailBox[empty_box].TDHR = 0x9abcdef0;  
    191.         
    192.       CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送  
    193.     }  
    194.     else  
    195.     {  
    196.       MyDebugger_LEDs(orange, on);  
    197.     }  
    198.     Delay(100);  
    199.       
    200.      /*  
    201.     选择空的发送邮箱:  
    202.     标准标识符0x4ab(100 1010 1011b)  
    203.     数据帧  
    204.     不使用扩展标识符  
    205.     */  
    206.     if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )  
    207.     {  
    208.       empty_box = ((CAN1->TSR>>24) & 0x00000003);   
    209.       CAN1->sTxMailBox[empty_box].TIR = (0x4ab<<21);    
    210.         
    211.       CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;  
    212.       CAN1->sTxMailBox[empty_box].TDTR |= 0x00000008;//发送数据长度为8  
    213.         
    214.       CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;  
    215.         
    216.       CAN1->sTxMailBox[empty_box].TDHR = 0x9abcdef0;  
    217.         
    218.       CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送  
    219.     }  
    220.     else  
    221.     {  
    222.       MyDebugger_LEDs(orange, on);  
    223.     }  
    224.     Delay(100);  
    225.       
    226.      /*  
    227.     选择空的发送邮箱:  
    228.     标准标识符0x7cb(100 1010 1011b)  
    229.     数据帧  
    230.     不使用扩展标识符  
    231.     */  
    232.     if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )  
    233.     {  
    234.       empty_box = ((CAN1->TSR>>24) & 0x00000003);   
    235.       CAN1->sTxMailBox[empty_box].TIR = (0x7cb<<21);    
    236.         
    237.       CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;  
    238.       CAN1->sTxMailBox[empty_box].TDTR |= 0x00000006;//发送数据长度为6  
    239.         
    240.       CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;  
    241.         
    242.       CAN1->sTxMailBox[empty_box].TDHR = 0x00009abc;  
    243.         
    244.       CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送  
    245.     }  
    246.     else  
    247.     {  
    248.       MyDebugger_LEDs(orange, on);  
    249.     }  
    250.     Delay(100);  
    251.       
    252.      /*  
    253.     选择空的发送邮箱:  
    254.     标准标识符0x40b(100 0000 1011b)  
    255.     数据帧  
    256.     不使用扩展标识符  
    257.     */  
    258.     if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )  
    259.     {  
    260.       empty_box = ((CAN1->TSR>>24) & 0x00000003);   
    261.       CAN1->sTxMailBox[empty_box].TIR = (0x40b<<21);    
    262.         
    263.       CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;  
    264.       CAN1->sTxMailBox[empty_box].TDTR |= 0x00000004;//发送数据长度为4  
    265.         
    266.       CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;  
    267.         
    268.       CAN1->sTxMailBox[empty_box].TDHR = 0x00000000;  
    269.         
    270.       CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送  
    271.     }  
    272.     else  
    273.     {  
    274.       MyDebugger_LEDs(orange, on);  
    275.     }  
    276.     Delay(100);  
    277.       
    278.    }  
    279. }  
    280.   
    281. /****************************************  
    282.   函数名:CAN_GPIO_config  
    283.   参数:无  
    284.   返回值:无  
    285.   功能:设置CAN1,2控制器用到IO口  
    286.   CAN1_TX---------PD1  
    287.   CAN1_RX---------PB8  
    288.   CAN2_TX---------PB13  
    289.   CAN2_RX---------PB5  
    290. ****************************************/  
    291. void CAN_GPIO_config()  
    292. {  
    293.   RCC->AHB1ENR |= ((1<<1) | (1<<3));//使能GPIOB、D时钟  
    294.   GPIOB->AFR[0] |= 0x00900000;      //AF9  
    295.   GPIOB->AFR[1] |= 0x00900009;  
    296.   GPIOD->AFR[0] |= 0x00000090;  
    297.       
    298.   GPIOB->MODER &= 0xF3FCF3FF; //第二功能  
    299.   GPIOB->MODER |= 0x08020800;  
    300.   GPIOD->MODER &= 0xFFFFFFF3;   
    301.   GPIOD->MODER |= 0x00000008;  
    302.     
    303.   GPIOB->OSPEEDR &= 0xF3FCF3FF; //50M  
    304.   GPIOB->OSPEEDR |= 0x08020800;  
    305.   GPIOD->OSPEEDR &= 0xFFFFFFF3;   
    306.   GPIOD->OSPEEDR |= 0x00000008;  
    307.     
    308.   GPIOB->PUPDR &= 0xF3FCF3FF;   //上拉  
    309.   GPIOB->PUPDR |= 0x04010400;  
    310.   GPIOD->PUPDR &= 0xFFFFFFF3;   
    311.   GPIOD->PUPDR |= 0x00000004;   
    312. }  
    313.   
    314. /****************************************  
    315.   函数名:CAN2_RX1_IRQHandler  
    316.   参数:无  
    317.   返回值:无  
    318.   功能:CAN2fifo1接收中断处理  
    319.         把信息存进循环队列  
    320. ****************************************/  
    321. void CAN2_RX1_IRQHandler()  
    322. {  
    323.   if(CAN2->RF1R & (0x00000003))//接收到新的消息,fifo1非空  
    324.   {  
    325.     Producer++;  
    326.     if(Producer == RECEIVE_BUFFER_SIZE)Producer = 0;  
    327.     if(Producer != Consumer)  
    328.     {  
    329.       CAN2_receive_buffer[Producer][0] = CAN2->sFIFOMailBox[1].RIR;  
    330.       CAN2_receive_buffer[Producer][1] = CAN2->sFIFOMailBox[1].RDTR;  
    331.       CAN2_receive_buffer[Producer][2] = CAN2->sFIFOMailBox[1].RDLR;  
    332.       CAN2_receive_buffer[Producer][3] = CAN2->sFIFOMailBox[1].RDHR;  
    333.     }  
    334.     else  
    335.     {  
    336.       if(Producer == 0)Producer = RECEIVE_BUFFER_SIZE;  
    337.       Producer--;  
    338.       MyDebugger_LEDs(blue, on);  
    339.     }     
    340.     CAN2->RF1R |= (1<<5);//释放邮箱  
    341.   }  
    342.     
    343.   if(CAN2->RF1R & (1<<3))//fifo0满  
    344.   {  
    345.     MyDebugger_LEDs(red, on);  
    346.     CAN2->RF1R &= ~(1<<3);  
    347.   }  
    348.     
    349.   if(CAN2->RF1R & (1<<4))//fifo0溢出  
    350.   {  
    351.     MyDebugger_LEDs(red, on);  
    352.     CAN2->RF1R &= ~(1<<4);  
    353.   }  
    354. }  
    355.   
    356. /****************************************  
    357.   函数名:TIM7_init  
    358.   参数:无  
    359.   返回值:无  
    360.   功能:初始化定时器7  
    361.         作1s定时用  
    362. ****************************************/  
    363. void TIM7_init()  
    364. {  
    365.   RCC->APB1ENR |= (1<<5); //打开TIM7时钟  
    366.   TIM7->PSC = 8399; //对时钟84M进行8400分频,使得计数频率为10k  
    367.   TIM7->ARR = 10000;  //定时一秒  
    368.   TIM7->CNT = 0;  //清空计数器  
    369.   TIM7->CR1 |= (1<<7); //自动重装载预装载使能  
    370.   TIM7->DIER |= 1; //使能中断  
    371.     
    372.   NVIC->IP[55] = 0xe0;  
    373.   NVIC->ISER[1] |= (1<<(55-32));  
    374.     
    375.   TIM7->CR1 |= 1; //开始计时  
    376. }  
    377.   
    378. /****************************************  
    379.   函数名:TIM7_IRQHandler  
    380.   参数:无  
    381.   返回值:无  
    382.   功能:定时器7中断处理  
    383.         1s定时到  
    384.         把can2收到的信息转换格式  
    385.         用usrt发送到超级终端显示  
    386. ****************************************/  
    387. void TIM7_IRQHandler(void)  
    388. {  
    389.   u32 length;  
    390.   if(TIM7->SR)  
    391.   {  
    392.     length = get_rece_data();  
    393.     MyDebugger_Message( UART_send_buffer, length );  
    394.     TIM7->SR &= ~(0x0001);   
    395.   }  
    396. }  
    397.   
    398. /****************************************  
    399.   函数名:get_rece_data  
    400.   参数:无  
    401.   返回值:length 整理后要发送数据的长度  
    402.   功能:把循环队列的信息取出  
    403.         进行格式转换  
    404.         把信息存到uart发送缓冲区  
    405. ****************************************/  
    406. u32 get_rece_data()  
    407. {  
    408.   u8 filter_No;  
    409.   u8 Data_length;   
    410.   char i;  
    411.   u32 length = 0;  
    412.   const char ascii[16] = {'0', '1', '2', '3', '4', '5', '6', '7',  
    413.                           '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};  
    414.   while(1)  
    415.   {  
    416.     if(Producer != Consumer)  
    417.       {  
    418.         Consumer++;  
    419.         if(Consumer == RECEIVE_BUFFER_SIZE)Consumer=0;  
    420.           
    421.         UART_send_buffer[length++] = '\n';  
    422.         UART_send_buffer[length++] = '\r';  
    423.         //Filter No.xx  
    424.         UART_send_buffer[length++] = 'F';  
    425.         UART_send_buffer[length++] = 'i';   
    426.         UART_send_buffer[length++] = 'l';  
    427.         UART_send_buffer[length++] = 't';  
    428.         UART_send_buffer[length++] = 'e';  
    429.         UART_send_buffer[length++] = 'r';   
    430.         UART_send_buffer[length++] = ' ';  
    431.         UART_send_buffer[length++] = 'N';   
    432.         UART_send_buffer[length++] = 'o';  
    433.         UART_send_buffer[length++] = '.';  
    434.      
    435.         filter_No = (CAN2_receive_buffer[Consumer][1]>>8) & 0x000000ff;  
    436.         UART_send_buffer[length++] = filter_No%100/10 + '0';  
    437.         UART_send_buffer[length++] = filter_No%10 + '0';  
    438.         UART_send_buffer[length++] = '\n';  
    439.         UART_send_buffer[length++] = '\r';  
    440.           
    441.         //DataLength:x  
    442.         UART_send_buffer[length++] = 'D';   
    443.         UART_send_buffer[length++] = 'a';  
    444.         UART_send_buffer[length++] = 't';   
    445.         UART_send_buffer[length++] = 'a';  
    446.         UART_send_buffer[length++] = 'L';  
    447.         UART_send_buffer[length++] = 'e';   
    448.         UART_send_buffer[length++] = 'n';  
    449.         UART_send_buffer[length++] = 'g';   
    450.         UART_send_buffer[length++] = 't';  
    451.         UART_send_buffer[length++] = 'h';  
    452.         UART_send_buffer[length++] = ':';  
    453.         Data_length = CAN2_receive_buffer[Consumer][1] & 0x0000000f;  
    454.         UART_send_buffer[length++] = Data_length % 10 + '0';  
    455.         UART_send_buffer[length++] = '\n';  
    456.         UART_send_buffer[length++] = '\r';  
    457.           
    458.           
    459.         if(CAN2_receive_buffer[Consumer][0] & (1<<1))  
    460.         {  
    461.           UART_send_buffer[length++] = 'R';   
    462.           UART_send_buffer[length++] = 'e';  
    463.           UART_send_buffer[length++] = 'm';   
    464.           UART_send_buffer[length++] = 'o';  
    465.           UART_send_buffer[length++] = 't';  
    466.           UART_send_buffer[length++] = 'e';   
    467.           UART_send_buffer[length++] = 'F';  
    468.           UART_send_buffer[length++] = 'r';   
    469.           UART_send_buffer[length++] = 'a';  
    470.           UART_send_buffer[length++] = 'm';  
    471.           UART_send_buffer[length++] = 'e';  
    472.         }  
    473.         else  
    474.         {  
    475.           UART_send_buffer[length++] = 'D';   
    476.           UART_send_buffer[length++] = 'a';  
    477.           UART_send_buffer[length++] = 't';   
    478.           UART_send_buffer[length++] = 'a';   
    479.           UART_send_buffer[length++] = 'F';  
    480.           UART_send_buffer[length++] = 'r';   
    481.           UART_send_buffer[length++] = 'a';  
    482.           UART_send_buffer[length++] = 'm';  
    483.           UART_send_buffer[length++] = 'e';  
    484.         }  
    485.         UART_send_buffer[length++] = '\n';  
    486.         UART_send_buffer[length++] = '\r';          
    487.           
    488.           
    489.         if(CAN2_receive_buffer[Consumer][0] & (1<<2))  
    490.         {  
    491.           UART_send_buffer[length++] = 'e';   
    492.           UART_send_buffer[length++] = 'x';  
    493.           UART_send_buffer[length++] = 't';   
    494.           UART_send_buffer[length++] = ' ';  
    495.           UART_send_buffer[length++] = 'I';  
    496.           UART_send_buffer[length++] = 'D';  
    497.           UART_send_buffer[length++] = ':';  
    498.             
    499.           UART_send_buffer[length++] =   
    500.             ascii[CAN2_receive_buffer[Consumer][0] >> 31];  
    501.           UART_send_buffer[length++] =   
    502.             ascii[(CAN2_receive_buffer[Consumer][0] >> 27)& 0x0000000f];  
    503.           UART_send_buffer[length++] =   
    504.             ascii[(CAN2_receive_buffer[Consumer][0] >> 23)& 0x0000000f];  
    505.           UART_send_buffer[length++] =   
    506.             ascii[(CAN2_receive_buffer[Consumer][0] >> 19)& 0x0000000f];  
    507.           UART_send_buffer[length++] =   
    508.             ascii[(CAN2_receive_buffer[Consumer][0] >> 15)& 0x0000000f];  
    509.           UART_send_buffer[length++] =   
    510.             ascii[(CAN2_receive_buffer[Consumer][0] >> 11)& 0x0000000f];  
    511.           UART_send_buffer[length++] =   
    512.             ascii[(CAN2_receive_buffer[Consumer][0] >> 7)& 0x0000000f];  
    513.           UART_send_buffer[length++] =   
    514.             ascii[(CAN2_receive_buffer[Consumer][0] >> 3)& 0x0000000f];  
    515.         }  
    516.         else  
    517.         {  
    518.           UART_send_buffer[length++] = 's';   
    519.           UART_send_buffer[length++] = 't';  
    520.           UART_send_buffer[length++] = 'd';   
    521.           UART_send_buffer[length++] = ' ';  
    522.           UART_send_buffer[length++] = 'I';  
    523.           UART_send_buffer[length++] = 'D';  
    524.           UART_send_buffer[length++] = ':';  
    525.             
    526.           UART_send_buffer[length++] =   
    527.             ascii[CAN2_receive_buffer[Consumer][0] >> 29];  
    528.           UART_send_buffer[length++] =   
    529.             ascii[(CAN2_receive_buffer[Consumer][0] >> 25)& 0x0000000f];  
    530.           UART_send_buffer[length++] =   
    531.             ascii[(CAN2_receive_buffer[Consumer][0] >> 21)& 0x0000000f];          
    532.         }  
    533.         UART_send_buffer[length++] = '\n';  
    534.         UART_send_buffer[length++] = '\r';  
    535.           
    536.         UART_send_buffer[length++] = 'D';   
    537.         UART_send_buffer[length++] = 'a';  
    538.         UART_send_buffer[length++] = 't';  
    539.         UART_send_buffer[length++] = 'a';  
    540.         UART_send_buffer[length++] = ':';  
    541.         if(Data_length > 4)  
    542.         {  
    543.           for(i = 2*Data_length - 8; i > 0; i--)  
    544.             UART_send_buffer[length++] =   
    545.               ascii[(CAN2_receive_buffer[Consumer][3] >> ((i-1)*4))& 0x0000000f];  
    546.             
    547.           for(i = 8; i > 0; i--)  
    548.             UART_send_buffer[length++] =   
    549.               ascii[(CAN2_receive_buffer[Consumer][2] >> ((i-1)*4))& 0x0000000f];  
    550.         }  
    551.         else  
    552.         {  
    553.           for(i = 2*Data_length; i > 0; i--)  
    554.             UART_send_buffer[length++] =   
    555.               ascii[(CAN2_receive_buffer[Consumer][2] >> ((i-1)*4))& 0x0000000f];           
    556.         }  
    557.         UART_send_buffer[length++] = '\n';  
    558.         UART_send_buffer[length++] = '\r';  
    559.       }  
    560.     else  
    561.       break;  
    562.   }  
    563.   return length;  
    564. }  
    565.   
    566.   
    567. void Delay(uint32_t nTime)  
    568. {   
    569.   Gb_TimingDelay = nTime;  
    570.   
    571.   while(Gb_TimingDelay != 0);  
    572. }  
    573.   
    574. void SysTick_Handler(void)  
    575. {  
    576.   if (Gb_TimingDelay != 0x00)  
    577.   {   
    578.     Gb_TimingDelay--;  
    579.   }  
    580. }  




    运行结果:

    展开全文
  • CAN总线】CAN_控制器

    2020-07-22 09:12:11
    此文章是关于单片机CAN总线的介绍。
  • CAN协议学习(二)MCAN控制器介绍

    千次阅读 2019-08-20 19:37:46
    MCAN2是Mentor公司开发的一个CAN2.0网络控制器的软核,初版2001年末版2006年。MCAN 2控制器实现了BOSCAN消息传输协议2.0a和2.0b。规范2.0a(相当于can 1.2)涵盖标准消息格式(11位标识符);规范2.0b涵盖标准和扩展消息...

    更多细节请参看MCAN2文档mcan2_ps.pdf。

    一、MCAN2简介

    MCAN2Mentor公司开发的一个CAN2.0网络控制器的软核,初版2001年末版2006年。MCAN 2控制器实现了BOSCAN消息传输协议2.0a2.0b。规范2.0a(相当于can 1.2)涵盖标准消息格式(11位标识符);规范2.0b涵盖标准和扩展消息格式(11位和29位标识符)

    二、总体架构

    下图显示了MCAN2设计的主要功能块。

     

    CPUmcan 2的访问是通过独立的地址、输入数据和输出数据总线进行的。由主机设备将用于传输的消息放置到发送缓冲器中,以便由位处理器进行传输。设备接收到的消息首先由接收过滤器过滤,然后放入接收FIFO中。

    CPU通过称为接收缓冲区的13字节窗口访问接收FIFO.结合接收FIFO使用接收缓冲区允许CPU在接收其他消息时处理一条消息。接收FIFO的总长度为64个字节,并以循环方式使用,使其能够同时容纳最多5个扩展的帧格式消息。

    位定时逻辑块负责设备的波特率,并且是可编程的。所支持的波特率范围取决于主系统时钟XTAL1的频率,并且可以容易地跨越比BOSCH规范所选择的125kbud-1MBaud更宽的波特率范围。

    CAN总线的接口由发送信号tx0tx1和接收的rx 0提供。TX1通常与tx0相反,也可以编程为输出发送时钟,这对于测试非常有用。

    三、发送、接收过程

    要传输的数据以标准帧格式(SFF)或扩展帧格式(EFF)写入mcan 2的发送缓冲器(如下)。发送缓冲器包括CAN地址10h1ch之间的13个字节,一个帧最多可以发送8个字节的数据。注意:在将数据写入缓冲区之前,需要检查传输缓冲区状态(状态寄存器,位2),以确保缓冲区“释放”(SR.2=1)。当缓冲区被锁定时写入缓冲区的任何数据(SR.2=0)都会丢失而没有任何指示。

     

    发送缓冲器描述符字段的位布局如下所示.

     

    FF代表frame format0为标准帧,1为拓展帧。

    RTR代表REMOTE TRANSMISSION REQUEST1表示为远程帧。

    DLC代表DATA LENGTH CODE:范围0-8,大于8的数被自动解释为8

    ID代表IDENTIFIER:标识符充当消息的名称,用于接收过滤,并确定总线访问优先级。标识符的二进制值越低,优先级就越高。在标准帧格式(SFF)中,标识符由11(id.28id.18)组成。在扩展帧格式(Eff)消息中,标识符由29(id.28id.0)组成。id.28是最高位,首先在总线上传输。

    mcan 2接收的数据首先由接收滤波器过滤,然后传递给接收FIFO。接受过滤器只传递那些具有与接收过滤器寄存器中记录的消息相匹配的标识位的消息。

    接收FIFO64个字节深,允许最多5个完整扩展帧格式(EFF)消息的空间,并以循环方式使用。

    放置在接收FIFO中的数据通过一个称为接收缓冲区的13字节窗口读取。该窗口位于can地址10h-1ch,即它占用与发送缓冲器相同的地址空间。与传输缓冲区一样,它足够宽,可以容纳一条包含最多8个字节数据的消息。

    四、信号&寄存器描述

    信号描述:

     

    寄存器描述:

     

    五、接收过滤

    与过滤相关的寄存器:

    10h-13h ACR03 Acceptance Code Registers 0-3

    14h-17h AMR03 Acceptance Mask Registers 0-3

    MCAN2的接收过滤模块首先将接收到的数据帧的ID部分与ACR即接收码寄存器比较,如果一致则接收,如果不一致则丢弃;AMR是接收掩码寄存器,如果某位设为‘1’,则将ACR对应的位设为‘不关心’。根据MOD.3为0或1来设置单过滤或双过滤模式,具体如下图。

     

    六、时序图

     

    七、测试程序(流程图&代码)

      1 //test CAN 2019.03.22 by zhou
      2 
      3     assign  F_can_rx[0]=(F_can_tx[3]==1'b1)?F_can_tx[0]:((F_can_tx[0]==1'b1)?F_can_tx[3]:1'bZ);        //star
      4     assign  F_can_rx[3]=(F_can_tx[0]==1'b1)?F_can_tx[3]:((F_can_tx[3]==1'b1)?F_can_tx[0]:1'bZ);        //earth
      5 
      6     assign  F_can_rx[1]=(F_can_tx[2]==1'b1)?F_can_tx[1]:((F_can_tx[1]==1'b1)?F_can_tx[2]:1'bZ);        //star
      7     assign  F_can_rx[2]=(F_can_tx[1]==1'b1)?F_can_tx[2]:((F_can_tx[2]==1'b1)?F_can_tx[1]:1'bZ);        //earth
      8     
      9 
     10 
     11 task CPU_READ_NPT;        //just read data, no display
     12     input [17:2] addr;
     13     output [15:0] rddata;
     14 
     15        begin
     16         #120ns
     17     @(posedge S_cpu_clk) 
     18     F_nrd = 1'b1;
     19     F_nwr = 1'b1;
     20     F_ncs = 1'b1;
     21     F_addr =addr;
     22     @(posedge S_cpu_clk) 
     23     F_nrd = 1'b0;
     24     F_nwr = 1'b1;
     25     F_ncs = 1'b0;
     26     F_addr =addr;
     27     @(posedge S_cpu_clk) 
     28     wait (F_nrdy==0);
     29     rddata = F_data_o;
     30     //$display("the addr %h read result is %h",addr, rddata);
     31     @(posedge S_cpu_clk) 
     32     F_nrd = 1'b1;
     33     F_nwr = 1'b1;
     34     F_ncs = 1'b1;
     35     F_addr =0;
     36        end
     37 endtask
     38 
     39 
     40 task CAN_TEST_ALL;
     41     begin
     42     CAN_TEST(16'h0700,16'h1201,16'h0500,16'h1100,8'h03);
     43     //CAN_TEST(16'h0701,16'h1200,16'h0600,16'h1000,8'h12);
     44     end
     45 endtask
     46 
     47 
     48 task CAN_TEST;
     49     input [15:0] reset_reg_star;
     50     input [15:0] reset_reg_earth;
     51     input [15:0] base_reg_star;
     52     input [15:0] base_reg_earth;
     53     input [7:0] connect;
     54 
     55     int i_cnt;
     56     logic [15:0] can_rdata;
     57 
     58     begin
     59     $display("=============CAN %h TEST START=============",connect);
     60 
     61     CPU_WRITE(reset_reg_star,16'h0000);//CAN1A RST begin
     62     #170ns;
     63     CPU_WRITE(reset_reg_star,16'h0001);//CAN1A RST end
     64     CPU_WRITE(reset_reg_earth,16'h0000);//CAN2B RST begin
     65     #170ns;
     66     CPU_WRITE(reset_reg_earth,16'h0001);//CAN2B RST end
     67 
     68 
     69     //can init 1A&2B begin////
     70     CPU_WRITE(base_reg_star,8'h09);    //CAN1A INIT [star]
     71     CPU_READ_NPT(base_reg_star,can_rdata);
     72     if(can_rdata != 8'h09)
     73     begin 
     74         $display("the addr base_reg_star read result is %h,wrong!(should be 8'h09)",can_rdata);
     75         $stop;
     76     end
     77     CPU_WRITE(base_reg_star+8'h1F,8'h08);
     78 
     79     CPU_WRITE(base_reg_star+8'h10,8'h00);
     80     CPU_WRITE(base_reg_star+8'h11,8'h00);
     81     CPU_WRITE(base_reg_star+8'h12,8'h00);
     82     CPU_WRITE(base_reg_star+8'h13,8'h00);
     83     CPU_WRITE(base_reg_star+8'h14,8'hFF);      // CARE ID:MUST 00                                                   
     84     CPU_WRITE(base_reg_star+8'h15,8'hFF);
     85     CPU_WRITE(base_reg_star+8'h16,8'hFF);
     86     CPU_WRITE(base_reg_star+8'h17,8'hFF);
     87 
     88     CPU_WRITE(base_reg_star+8'h04,8'h03);
     89     CPU_WRITE(base_reg_star+8'h06,8'h00);
     90     CPU_WRITE(base_reg_star+8'h07,8'h16);    
     91     CPU_WRITE(base_reg_star+8'h08,8'h00);
     92     CPU_WRITE(base_reg_star+8'h1E,8'h00);
     93     CPU_WRITE(base_reg_star+8'h00,8'h08);
     94 
     95     CPU_WRITE(base_reg_earth+8'h00,8'h09);    //CAN2B INIT [earth]
     96     CPU_READ_NPT(base_reg_earth+8'h00,can_rdata);
     97     if(can_rdata != 8'h09)
     98     begin 
     99         $display("the addr base_reg_earth+8'h00 read result is %h,wrong!(should be 8'h09)",can_rdata);
    100         $stop;
    101     end
    102     CPU_WRITE(base_reg_earth+8'h1F,8'h08);
    103 
    104     CPU_WRITE(base_reg_earth+8'h10,8'h12);         //  ID:MUST 122X
    105     CPU_WRITE(base_reg_earth+8'h11,8'h24);        
    106     CPU_WRITE(base_reg_earth+8'h12,8'h00);
    107     CPU_WRITE(base_reg_earth+8'h13,8'h00);
    108     CPU_WRITE(base_reg_earth+8'h14,8'h00);                                                
    109     CPU_WRITE(base_reg_earth+8'h15,8'h00);
    110     CPU_WRITE(base_reg_earth+8'h16,8'hFF);
    111     CPU_WRITE(base_reg_earth+8'h17,8'hFF);
    112 
    113     CPU_WRITE(base_reg_earth+8'h04,8'h01);
    114     CPU_WRITE(base_reg_earth+8'h06,8'h00);
    115     CPU_WRITE(base_reg_earth+8'h07,8'h16);    
    116     CPU_WRITE(base_reg_earth+8'h08,8'h02);
    117     CPU_WRITE(base_reg_earth+8'h1E,8'h00);
    118     CPU_WRITE(base_reg_earth+8'h00,8'h08);
    119     //can init end///
    120 
    121 
    122     CPU_WRITE(base_reg_star+8'h01,8'h0C);    //CLR RX FIFO
    123 
    124     CPU_READ(base_reg_star+8'h02,can_rdata);    //SR[2]=?0
    125     while(can_rdata[2] == 0)
    126     begin
    127         #1us;
    128         CPU_READ_NPT(base_reg_star+8'h02,can_rdata);
    129     end
    130     
    131     
    132         CPU_WRITE(base_reg_star+8'h10,8'h08);    //Transmit Frame Information:standard,8 data
    133     CPU_WRITE(base_reg_star+8'h11,8'h56);    //identifier:ff0
    134     CPU_WRITE(base_reg_star+8'h12,8'h60);    
    135     for(i_cnt=3;i_cnt<11;i_cnt++)
    136     begin
    137         CPU_WRITE(base_reg_star+8'h10+i_cnt,i_cnt);//write data to transmit buffer,发送一帧标准帧数据
    138     end
    139     
    140 
    141     CPU_WRITE(base_reg_star+8'h01,8'h01);    //trans enable
    142     
    143     CPU_READ(base_reg_star+8'h03,can_rdata);
    144     CPU_READ(base_reg_star+8'h02,can_rdata);
    145     while(can_rdata[2] == 0)
    146     begin    
    147         #1us;
    148         CPU_READ_NPT(base_reg_star+8'h02,can_rdata);
    149         
    150     end
    151     CPU_READ(base_reg_star+8'h03,can_rdata);
    152     CPU_READ(base_reg_star+8'h02,can_rdata);
    153     
    154     #2ms;
    155     CPU_READ(base_reg_earth+8'h10,can_rdata);
    156     CPU_READ(base_reg_earth+8'h11,can_rdata);
    157     CPU_READ(base_reg_earth+8'h12,can_rdata);
    158     CPU_READ(base_reg_earth+8'h13,can_rdata);
    159     CPU_READ(base_reg_earth+8'h14,can_rdata);
    160     CPU_READ(base_reg_earth+8'h15,can_rdata);
    161     CPU_READ(base_reg_earth+8'h16,can_rdata);
    162     CPU_READ(base_reg_earth+8'h17,can_rdata);
    163     CPU_READ(base_reg_earth+8'h18,can_rdata);
    164     CPU_READ(base_reg_earth+8'h19,can_rdata);
    165     //CPU_READ(base_reg_star+8'h03,can_rdata);
    166     //CPU_READ(base_reg_star+8'h02,can_rdata);
    167     CPU_READ(base_reg_earth+8'h1a,can_rdata);
    168 
    169     
    170     ///second sending///
    171     $display("####################################");
    172     CPU_WRITE(base_reg_star+8'h01,8'h0C);
    173     CPU_WRITE(base_reg_earth+8'h01,8'h0C);
    174 
    175     CPU_READ(base_reg_star+8'h02,can_rdata);    //SR[2]=?0
    176     while(can_rdata[2] == 0)
    177     begin
    178         #1us;
    179         CPU_READ_NPT(base_reg_star+8'h02,can_rdata);
    180     end
    181     CPU_READ(base_reg_star+8'h02,can_rdata);
    182 
    183     CPU_WRITE(base_reg_star+8'h10,8'h08);    //Transmit Frame Information:standard,8 data
    184     CPU_WRITE(base_reg_star+8'h11,8'h00);    //identifier:00
    185     CPU_WRITE(base_reg_star+8'h12,8'h00);    
    186     for(i_cnt=3;i_cnt<11;i_cnt++)
    187     begin
    188         CPU_WRITE(base_reg_star+8'h10+i_cnt,i_cnt);//write data to transmit buffer,发送一帧标准帧数据
    189     end        
    190 
    191 
    192     CPU_WRITE(base_reg_star+8'h01,8'h01);    //trans enable
    193     CPU_READ(base_reg_star+8'h02,can_rdata);    //SR[2]=?0
    194     #2ms
    195     CPU_READ(base_reg_earth+8'h10,can_rdata);
    196     CPU_READ(base_reg_earth+8'h11,can_rdata);
    197     CPU_READ(base_reg_earth+8'h12,can_rdata);
    198     CPU_READ(base_reg_earth+8'h13,can_rdata);
    199     CPU_READ(base_reg_earth+8'h14,can_rdata);
    200     CPU_READ(base_reg_earth+8'h15,can_rdata);
    201     CPU_READ(base_reg_earth+8'h16,can_rdata);
    202     CPU_READ(base_reg_earth+8'h17,can_rdata);
    203     CPU_READ(base_reg_earth+8'h18,can_rdata);
    204     CPU_READ(base_reg_earth+8'h19,can_rdata);
    205     //CPU_READ(base_reg_star+8'h03,can_rdata);
    206     //CPU_READ(base_reg_star+8'h02,can_rdata);
    207     CPU_READ(base_reg_earth+8'h1a,can_rdata);
    208     
    209     $display("CAN %h TEST Success!\n",connect);
    210     end
    211 
    212 endtask
    MCAN2测试代码

     

    转载于:https://www.cnblogs.com/zhouliyan/p/10612813.html

    展开全文
  • STM32 CAN控制器简介-寄存器简介

    千次阅读 2018-10-09 22:34:44
    1、CAN控制寄存器(CAN_MCR) 该寄存器的我们仅介绍下INRQ位,该位用来控制初始化请求。 设置INRQ=0,可使CAN从初始化模式进入正常工作模式。 设置INRQ=1,可使CAN从正常工作模式进入初始化模式 。 CAN初始...

    1、CAN主控制寄存器(CAN_MCR

    该寄存器的我们仅介绍下INRQ位,该位用来控制初始化请求。

    设置INRQ=0,可使CAN从初始化模式进入正常工作模式。

    设置INRQ=1,可使CAN从正常工作模式进入初始化模式 。

    CAN初始化时,先设置INRQ=1 ,进入初始化模式,进行初始化(尤其是CAN_BTR的设置,该寄存器,必须在CAN正常工作之前设置),之后再设置INRQ=0,进入正常工作模式。

    2、CAN位时序寄存器(CAN_BTR

    3、CAN接收FIFO寄存器(CAN_RF0R/CAN_RF1R

    4、CAN发送邮箱标识符寄存器(CAN_TIxR)(x=0~2

    5、CAN发送邮箱数据长度和时间戳寄存器 (CAN_TDTxR) (x=0~2)

    6、CAN发送邮箱数据寄存器(CAN_TDLxR/CAN_TDHxR) (x=0~2)

    图为CAN_TDLxR寄存器的描述,用于存储低4个字节的数据。CAN_TDHxR寄存器与之类似,用于存储高4个字节的数据。要发送的数据就是存储在这两个寄存器

    7、CAN接收FIFO邮箱标识符寄存器(CAN_RIxR(x=0/1)

    8、CAN接收FIFO邮箱数据长度和时间戳寄存器(CAN_RDTxR) (x=0/1)

    9、CAN接收FIFO邮箱邮箱数据寄存器(CAN_RDLxR/CAN_RDHxR) (x=0/1)

    图为CAN_RDLxR寄存器的描述,用于存储低4个字节的数据。CAN_RDHxR寄存器与之类似,用于存储高4个字节的数据。接收到的数据就存储在这两个寄存器

    10、CAN筛选器模式寄存器(CAN_FM1R

    该寄存器设置筛选器的工作模式,必须在CAN_FMR寄存器FINIT=1时配置,对于STM32F103ZET6只有[13:0]位有效,对于互联性STM32F1或者STM32F407,则全部有效

    11、CAN筛选器尺度寄存器(CAN_FS1R

    该寄存器用于设置筛选器的位宽,必须在CAN_FMR寄存器FINIT=1时配置,对于STM32F103ZET6,只有[13:0]位有效,对于互联性STM32F1或者STM32F407,则全部有效。

    12、CAN筛选器FIFO关联寄存器(CAN_FFA1R

    该寄存器设置报文通过筛选器组之后,被存入的FIFO,如果对应位为0,则存放到FIFO0;如果为1,则存放到FIFO1。该寄存器也只能在过滤器处于初始化模式( CAN_FMR 寄存器的FINIT=1 )下配置。

    13、CAN筛选器激活寄存器(CAN_FA1R

    该寄存器用于设置筛选器组的开启和关闭。对对应位置1,即开启对应的筛选器组;置0则关闭该筛选器组。

    14、CAN筛选器组i寄存器xCAN_FiRx(i=0~27,x=1/2)

    每个筛选器组的CAN_FiRx都由232位寄存器构成,即:CAN_FiR1CAN_FiR2。根据过滤器位宽和模式的不同设置,这两个寄存器的功能也不尽相同。关于过筛选器的映射,功能描述和屏蔽寄存器的关联,在前面已经介绍过了

    15、STM32 CAN控制器简介-初始化流程

    ①配置相关引脚的复用功能,使能CAN时钟。

            要用CAN,先要使能CAN的时钟,CAN的时钟通过APB1ENR的第25位来设置。其次要设置CAN的相关引脚为复用输出,这里我们需要设置PA11为上拉输入(CAN_RX引脚)PA12为复用输出(CAN_TX引脚),并使能PA口的时钟

    ②设置CAN工作模式及波特率等。

            通过先设置CAN_MCR寄存器的INRQ位,让CAN进入初始化模式,然后设置CAN_MCR的其他相关控制位。再通过CAN_BTR设置波特率和工作模式(正常模式/环回模式)等信息。 最后设置INRQ0,退出初始化模式。

    ③设置滤波器。

            本例程,我们将使用筛选器组0,并工作在32位标识符屏蔽位模式下。先设置CAN_FMRFINIT位,进入初始化模式,然后设置筛选器组0的工作模式以及标识符ID和屏蔽位。最后激活筛选器,并退出初始化模式。

    //CAN初始化
    //tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
    //tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
    //tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
    //brp :波特率分频器.范围:1~1024; tq=(brp)*tpclk1
    //波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
    //mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
    //Fpclk1的时钟在初始化的时候设置为42M,如果设置CAN1_Mode_Init(CAN_SJW_1tq,CAN_BS2_6tq,CAN_BS1_7tq,6,CAN_Mode_LoopBack);
    //则波特率为:42M/((6+7+1)*6)=500Kbps
    //返回值:0,初始化OK;
    //    其他,初始化失败; 
    u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
    {
    
      	GPIO_InitTypeDef GPIO_InitStructure; 
    	  CAN_InitTypeDef        CAN_InitStructure;
      	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
    #if CAN1_RX0_INT_ENABLE //中断使用 默认不使用
       	NVIC_InitTypeDef  NVIC_InitStructure;
    #endif
        //使能相关时钟
    	  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 
    
      	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	
    	
        //初始化GPIO
    	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12
    	
    	  //引脚复用映射配置
    	  GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11复用为CAN1
    	  GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12复用为CAN1
    	  
      	//CAN单元设置
       	CAN_InitStructure.CAN_TTCM=DISABLE;	//非时间触发通信模式   
      	CAN_InitStructure.CAN_ABOM=DISABLE;	//软件自动离线管理	  
      	CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
      	CAN_InitStructure.CAN_NART=ENABLE;	//禁止报文自动传送 
      	CAN_InitStructure.CAN_RFLM=DISABLE;	//报文不锁定,新的覆盖旧的  
      	CAN_InitStructure.CAN_TXFP=DISABLE;	//优先级由报文标识符决定 
      	CAN_InitStructure.CAN_Mode= mode;	 //模式设置 
    
    		//设置波特率
      	CAN_InitStructure.CAN_SJW=tsjw;	//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
      	CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
      	CAN_InitStructure.CAN_BS2=tbs2;//Tbs2范围CAN_BS2_1tq ~	CAN_BS2_8tq
      	CAN_InitStructure.CAN_Prescaler=brp;  //分频系数(Fdiv)为brp+1	
      	CAN_Init(CAN1, &CAN_InitStructure);   // 初始化CAN1 
        
    		//配置过滤器
     	  CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
      	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式
      	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位宽
      	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
      	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
      	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
      	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
       	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
      	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
      	CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
    		
    #if CAN1_RX0_INT_ENABLE
    	
    	  CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.		    
      
      	NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      	NVIC_Init(&NVIC_InitStructure);
    #endif
    	return 0;
    }   
    //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
    //len:数据长度(最大为8)				     
    //msg:数据指针,最大为8个字节.
    //返回值:0,成功;
    //		 其他,失败;
    u8 Can_Send_Msg(u8* msg,u8 len)
    {	
            u8 mbox;
            u16 i=0;
            CanTxMsg TxMessage;
            TxMessage.StdId=0x12;		// 标准标识符 
            TxMessage.ExtId=0x12;		// 设置扩展标示符 
            TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
            TxMessage.RTR=CAN_RTR_Data;		// 数据帧
            TxMessage.DLC=len;			// 要发送的数据长度
            for(i=0;i<len;i++)TxMessage.Data[i]=msg[i]; 
            mbox= CAN_Transmit(CAN1, &TxMessage);   
            i=0;
            while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;//等待发送结束
            if(i>=0XFFF)return 1;
            return 0; 
    }  
    
    //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
    //len:数据长度(最大为8)				     
    //msg:数据指针,最大为8个字节.
    //返回值:0,成功;
    //		 其他,失败;
    u8 Can_Send_Msg(u8* msg,u8 len)
    {	
            u8 mbox;
            u16 i=0;
            CanTxMsg TxMessage;
            TxMessage.StdId=0x12;		// 标准标识符 
            TxMessage.ExtId=0x12;		// 设置扩展标示符 
            TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
            TxMessage.RTR=CAN_RTR_Data;		// 数据帧
            TxMessage.DLC=len;			// 要发送的数据长度
            for(i=0;i<len;i++)TxMessage.Data[i]=msg[i]; 
            mbox= CAN_Transmit(CAN1, &TxMessage);   
            i=0;
            while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;//等待发送结束
            if(i>=0XFFF)return 1;
            return 0; 
    }  
    
    //can口接收数据查询
    //buf:数据缓存区;	 
    //返回值:0,无数据被收到;
    //		 其他,接收的数据长度;
    u8 Can_Receive_Msg(u8 *buf)
    {		   		   
            u32 i;
            CanRxMsg RxMessage;
            if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;	//没有接收到数据,直接退出 
            CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);	//读取数据	
            for(i=0;i<8;i++)buf[i]=RxMessage.Data[i];  
            return RxMessage.DLC;	
    }
    

     

     

    展开全文
  • CAN控制器及邮箱

    千次阅读 2018-12-05 14:47:18
    CAN基础知识 ISO11898是针对通信速率为125Kbps~1Mbps的高速通信标准。 CAN协议的特点: 多主控制。系统柔软性。速度快,距离远。具有错误检测、错误通知和错误恢复功能。故障封闭功能。连接节点多。 显性电平对应...

    CAN基础知识

    ISO11898是针对通信速率为125Kbps~1Mbps的高速通信标准。
    CAN协议的特点:
    多主控制。系统柔软性。速度快,距离远。具有错误检测、错误通知和错误恢复功能。故障封闭功能。连接节点多。
    显性电平对应逻辑:0
    CAN_H和CAN_L之差为2V左右。
    隐性电平对应逻辑:1

    CAN_H和CAN_L之差为0V。
    在这里插入图片描述
    显性电平具有优先权,只要有一个单元输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强)。另外,在CAN总线的起止端都有一个120Ω的终端电阻,来做阻抗匹配,以减少回波反射。
    CAN通信是以以下5种类型的帧进行的:
    数据帧遥控帧错误帧过载帧间隔帧
    数据帧和遥控帧有标准格式和扩展格式两种格式。
    标准格式有11 个位的标识符(ID),扩展格式有29 个位的ID 。
    数据帧由7个段组成:
    ①,帧起始。
    表示数据帧开始的段。
    ②,仲裁段。
    表示该帧优先级的段。
    ③,控制段。
    表示数据的字节数及保留位的段。
    ④,数据段。
    数据的内容,一帧可发送0~8个字节的数据。
    ⑤,CRC段。
    检查帧的传输错误的段。
    ⑥,ACK段。
    表示确认正常接收的段。
    ⑦,帧结束。
    表示数据帧结束的段。
    STM32自带了基本扩展CAN外设,又称bxCAN,bxCAN的特点如下:
    支持CAN协议2.0A和2.0B主动模式
    波特率最高达1Mbps
    支持时间触发通信
    具有3个发送邮箱
    具有3级深度的2个接收FIFO
    可变的筛选器组(也称过滤器组,最多28个)
    工作模式:
    ①初始化模式(INRQ=1,SLEEP=0)
    ②正常模式(INRQ=0,SLEEP=0)
    ③睡眠模式(SLEEP=1)
    测试模式
    ①静默模式( LBKM=0,SILM=1 )
    ②环回模式( LBKM=1,SILM=0 )
    ③环回静默模式(LBKM=1,SILM=1)
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • STM32学习之CAN控制器简介

    千次阅读 2018-10-09 22:16:33
    1、STM32自带了基本扩展CAN外设,又称bxCAN,bxCAN的特点如下: 支持CAN协议2.0A和2.0B主动模式 波特率最高达1Mbps 支持时间触发通信 ...2、STM32 CAN控制器简介-模式  ①初始化模式(INRQ=1...
  • CAN总线通信原理分析

    万次阅读 2015-04-13 18:26:38
    基于CAN总线系统结构构成,通过工程实践的具体应用以及对CAN控制器及收发器硬件结构的深入理解,并从通信的角度出发着重深入分析了CAN总线通信的节点同步机制、总线地址机制、总线仲裁机制(即总线的冲突解决机制)...
  • CAN数据帧结构与传输

    万次阅读 多人点赞 2018-04-22 20:23:24
    CAN-bus: Controller Area Network-bus,控制器局域网总线技术 CAN总线系统结构CAN 控制器接收控制单元中微处理器发出的数据,处理数据并传给CAN收发器CAN收发器将数据传到总线 or 从总线接收数据给控制器CAN数据...
  • 完整的CAN电路是由CAN控制器和CAN收发器组成的,二者之间一般通过TTL电平的收发信号(CANRX、CANTX)连接,由CAN收发器将CANTX的TTL信号转换为CAN规范差分信号输出、同时接收差分线上的实际信号并转换为TTL信号输出...
  • 基于FPGA的CAN总线控制器(支持CANFD)

    千次阅读 2016-05-15 11:10:41
    基于FPGA的CAN总线控制器(支持CANFD) CANFD协议与之前的CAN协议相比: 可变速率,CAN协议最高1Mbps,CANFD最高20Mbps以上(目前没关注了) 数据段最高可以有64个字节 ... 前段时间在公司做了一个CAN控制器IP,支持CA
  • CAN总线知识点梳理

    万次阅读 多人点赞 2018-09-01 17:20:57
    嵌入式的工程师一般都知道CAN总线广泛应用到汽车中,其实船舰电子设备通信也广泛使用CAN,随着国家对海防的越来越重视,对CAN的需求也会越来越大。这个暑假,通过参加苏州社会实践,去某船舶电气公司实习几周,也借...
  • CAN总线详解

    万次阅读 多人点赞 2019-07-24 09:56:01
    1、简介 CAN是控制器局域网络(Controller Area Network, ...近些年来,CAN控制器价格越来越低。 Ø 低成本:ECUs通过单个CAN接口进行通信,布线成本低。 Ø 高集成:CAN总线系统允许在所有ECUs上进行集中错误诊...
  • can总线与485总线有什么区别?

    万次阅读 2014-03-11 13:38:57
    以往,PC与智能设备通讯多借助RS232、RS485、以太网等方式,主要取决于设备的接口规范。但RS232、RS485只能代表通讯的物理介质层和链路层,如果要实现数据的双向访问,就必须自己编写通讯应用程序,但这种程序多数都...
  • CAN 控制器通讯故障

    千次阅读 2012-11-23 10:13:58
    CAN-bus(Controller Area Network) 即控制器局域网,是国际上应用最广泛的现场总线之一。起先,CAN-bus 被设计作为汽车环境中的微控制器通讯,在车载各电子控制装置ECU 之间交换信息,形成汽车电子控制网络。比如...
  • CAN详解--CAN与com口介绍

    万次阅读 多人点赞 2018-12-26 18:59:31
    通常用于连接鼠标(串口)及通讯设备(如连接外置式调制解调进行数据通讯或一些工厂的数控机接口)等。一般主板外部只有一个串口,机箱后面和并口一起的那个九孔输出端(梯形),就是COM1口,COM...
  • 整车CAN网络介绍

    万次阅读 多人点赞 2018-05-02 22:11:02
    CAN(Controller Area Network)控制器局域网络,CAN网络在早期的整车应用中以BCM(车身控制器)为控制中心,主要是车身零部件(雨刮/大灯/车窗…),智能硬件较少,所以早期的正常CAN网络把所有其他的ECU全部放在Other ...
  • CAN芯片选型

    千次阅读 2009-12-21 19:50:00
    在进行CAN总线开发前,首先要选择好CAN总线控制器。下面就比较一些控制器的特点。 一些主要的CAN总线器件产品 制造商产品型号器件功能及特点Intel82526825278XC196CA/CBCAN通信控制器,符合CAN2.0ACAN通信控制器,...
  • TJA1050T CAN总线通信硬件原理

    万次阅读 2016-06-14 14:54:43
    为提高系统的驱动能力,增大通信距离,实际应用中多采用Philips公司的82C250作为CAN控制器与物理总线间的接口,即CAN收发器,以增强对总线的差动发送能力和对CAN控制器的差动接收能力。为进一步增强抗干扰能力,往往...
  • 使用CANoe搭建CAN网关

    万次阅读 多人点赞 2016-07-18 11:01:07
    Vector公司的CANoe是一款强大的总线仿真工具,通过CANoe搭建出来的总线...这样不仅能够模拟总线上的报文发送,还可以模拟ECU的内部逻辑,理论上可以完全模拟出CAN总线系统。这里介绍一下如何通过CANoe搭建一个CAN网关。
  • 汽车控制器CAN通信DBC文件工具:EXCEL生成DBC和生成代码汽车控制器CAN通信DBC文件工具:从EXCEL生成DBC和生成代码AutoCANdbAutoCANdb限制效果图 汽车控制器CAN通信DBC文件工具:从EXCEL生成DBC和生成代码 目前汽车...
1 2 3 4 5 ... 20
收藏数 166,322
精华内容 66,528
关键字:

can控制器