STM32F407之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的位对应的接收到的帧的标识符的位与对应的放标识符的寄存器的位一致,就能通过。

 

  

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

 

         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收发器 


程序:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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. }  




运行结果:

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要使用STM32F407控制3508电机,需要进行以下步骤: 1. 首先,需要了解3508电机的通信协议。通常情况下,3508电机使用CAN总线进行通信。因此,需要在STM32F407上配置CAN总线。 2. 配置CAN总线后,需要编写代码来控制3508电机。可以使用STM32F407的CAN库来发送CAN消息到3508电机,以控制其速度和方向。 3. 在编写代码时,需要注意3508电机的控制方式。通常情况下,可以使用PID控制器来控制电机的速度和位置。 4. 最后,需要将STM32F407和3508电机连接起来。可以使用CAN总线连接它们,也可以使用其他通信方式,如UART或SPI。 总之,要控制3508电机,需要了解其通信协议和控制方式,并编写相应的代码来实现控制。同时,需要将STM32F407和3508电机连接起来,以便它们可以进行通信。 ### 回答2: 要控制3508电机,首先需要了解STM32F407的CAN总线模块和3508电机的控制方式。 STM32F407的CAN总线模块支持CAN2.0A和CAN2.0B协议。通过CAN总线,可以进行多个设备之间的通信。要控制3508电机,可以通过CAN总线发送控制指令。 而3508电机是一种智能型直流无刷电机,可以通过CAN总线进行控制。在3508电机中,使用和STM32F407类似的MCU控制器,可以通过CAN通信接收外部的指令并执行相应的动作。控制器还会检测电机的状态,如电机转速、电机温度等,并将它们反馈给主控制器。 具体控制过程如下: 1. 编写STM32F407的CAN总线发送程序,将控制指令打包成CAN帧,通过CAN总线发送到3508电机。 2. 在3508电机中,使用MCU控制器接收CAN帧,解析出控制指令,并执行相应的动作。例如,如果接收到的控制指令为电机转速值,则控制器会将电机转速设定为指定值。 3. 控制器会通过CAN总线发送状态反馈信息,例如电机转速、电机温度等,反馈给STM32F407STM32F407通过CAN总线接收反馈信息,可以进行相应的处理,例如根据反馈信息调整控制指令,以达到更精确的控制效果。 需要注意的是,在确定3508电机的控制方式及其CAN通信协议之前,需要先了解具体的硬件和软件架构和技术要求,以确保控制器能够正确控制电机。 总的来说,STM32F407通过CAN总线与3508电机进行通信,可以实现精准的控制。相信在应用场景中,这种控制方法必将会具有广泛的应用前景。 ### 回答3: 首先,stm32f407可以通过CAN总线控制3508电机。CAN总线是一种高速、可靠的通信协议,广泛应用于工业领域,特别适合各种高速控制场合。 其次,为了控制3508电机,需要了解它的工作原理。3508电机是一种直流无刷电机,具有高转速和高功率的特点,需要使用PWM信号来控制转速。同时,需要使用差分驱动方式,即需要使用四个PWM信号来分别控制电机的四个线圈。 最后,通过stm32f407和3508电机进行连接,需要在硬件上实现CAN模块与3508电机的连接,并在软件上通过编程实现CAN总线的控制和PWM信号的产生。 在程序开发过程中,可以使用STM32CubeMX作为开发工具,在其生成的初始化代码基础上进行修改和调试。在代码中需要包括CAN总线的初始化、CAN报文的发送和接收、PWM的产生和差分驱动方式的实现等功能。需要注意的是,CAN总线的帧格式和3508电机的控制协议需要根据具体情况而定,并进行相应的配置。 总之,通过合理的硬件和软件设计,stm32f407可以成功控制3508电机,实现高速、高精度的控制应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值