stm32f407之CAN控制器(操作寄存器)

发布者:DataExplorer最新更新时间:2018-09-20 来源: eefocus关键字:stm32f407  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的位对应的接收到的帧的标识符的位与对应的放标识符的寄存器的位一致,就能通过。

 

  

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

 

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


程序:

/************************************  

    标题:操作CAN的练习  

    软件平台:IAR for ARM6.21  

    硬件平台:stm32f4-discovery  

    主频:168M  

      

    描述:通过硬件收发器连接CAN1,CAN2  

          组成一个两个端点的网络  

  

          CAN1循环发出数据帧  

  

          CAN2接收过滤数据帧  

  

          用uart把CAN2接收到  

          的数据帧发到超级终端  

  

    author:小船  

    data:2012-08-14  

*************************************/  

  

#include   

#include "MyDebugger.h"  

  

#define RECEIVE_BUFFER_SIZE 20  

  

u32 CAN2_receive_buffer[RECEIVE_BUFFER_SIZE][4];  

u8 UART_send_buffer[1800];  

u8 Consumer = 0;  

u8 Producer = 0;  

  

u32 Gb_TimingDelay;  

void Delay(uint32_t nTime);  

void TIM7_init();//定时1s  

u32 get_rece_data();  

void CAN_GPIO_config();  

  

void main ()  

{     

  

  u32 empty_box;  

  SysTick_Config(SystemCoreClock / 1000); //设置systemtick一毫秒中断  

  SCB->AIRCR = 0x05FA0000 | 0x400;  //中断优先级分组 抢占:响应=3:1  

   

  MyDebugger_Init();  

  TIM7_init();  

  MyDebugger_Message( "\n\rtesting......\n\r" ,   

                     sizeof("\n\rtesting......\n\r")/sizeof(char) );  

    

  CAN_GPIO_config();  

    

  RCC->APB1ENR |= ((1<<25)|(1<<26));//使能CAN1、CAN2时钟  

    

  CAN1->MCR = 0x00000000;  

  /*  

  请求进入初始化模式  

  禁止报文自动重传  

  自动唤醒模式  

  */  

  CAN1->MCR |= ((1<<0)|(1<<4)|(1<<5));  

  CAN1->MCR &= ~(1<<16);//在调试时,CAN照常工作  

    

  while(!(CAN1->MSR & 0xfffffffe))  //等待进入初始化模式  

  {  

    MyDebugger_LEDs(orange, on);  

  }  

  MyDebugger_LEDs(orange, off);  

    

  /*  

  正常模式  

  重新同步跳跃宽度(1+1)tq  

  TS2[2:0]=3  

  TS1[3:0]=8  

  BRP[9:0]=2  

    

  ps:  

  tq = (BRP[9:0] + 1) x tPCLK,  

  tBS2 = tq x (TS2[2:0] + 1),  

  tBS1 = tq x (TS1[3:0] + 1),  

  NominalBitTime = 1 × tq+tBS1+tBS2,  

  BaudRate = 1 / NominalBitTime  

    

  波特率设为1M  

  */  

  CAN1->BTR = ((0<<30)|(0x01<<24)|(3<<20)|(8<<16)|(2<<0));  

    

  CAN1->MCR &= ~(0x00000001);//正常工作模式  

    

  CAN2->MCR = 0x00000000;  

  /*  

  请求进入初始化模式  

  禁止报文自动重传  

  自动唤醒模式  

  */  

  CAN2->MCR |= ((1<<0)|(1<<4)|(1<<5));  

  CAN2->MCR &= ~(1<<16);//在调试时,CAN照常工作  

    

  while(!(CAN2->MSR & 0xfffffffe))  //等待进入初始化模式  

  {  

    MyDebugger_LEDs(orange, on);  

  }  

  MyDebugger_LEDs(orange, off);  

    

  /*  

  正常模式  

  重新同步跳跃宽度(1+1)tq  

  TS2[2:0]=3  

  TS1[3:0]=8  

  BRP[9:0]=2  

    

  ps:  

  tq = (BRP[9:0] + 1) x tPCLK,  

  tBS2 = tq x (TS2[2:0] + 1),  

  tBS1 = tq x (TS1[3:0] + 1),  

  NominalBitTime = 1 × tq+tBS1+tBS2,  

  BaudRate = 1 / NominalBitTime  

    

  波特率设为1M  

  */  

  CAN2->BTR = ((0<<30)|(0x01<<24)|(3<<20)|(8<<16)|(2<<0));  

    

  CAN2->IER &= 0x00000000;  

  /*  

  FIFO1消息挂号中断使能  

  FIFO1满中断使能  

  FIFO1溢出中断使能  

  */  

  CAN2->IER |= ((1<<4)|(1<<5)|(1<<6));  

    

    

  NVIC->IP[65] = 0xa0;   //抢占优先级101,响应优先级0   

  NVIC->ISER[2] |= (1<<1);  //使能中断线65,也就是can2_rx1中断  

    

  CAN2->MCR &= ~(0x00000001);//正常工作模式  

    

    

  //总共有28组过滤器  

  CAN1->FMR |= 1; //过滤器组工作在初始化模式  

    

  CAN1->FMR &= 0xffffc0ff;//CAN2的过滤器组从14开始  

  CAN1->FMR |= (14<<8);  

    

  CAN1->FM1R |= (1<<14);//过滤器组14的寄存器工作在标识符列表模式  

                         

                        //位宽为16位,2个32位分为四个16位寄存器,过滤四个标识符  

    

  //CAN1->FS1R |= (1<<15);//过滤器组15为单个32位寄存器,用于扩展标识符  

    

  CAN1->FFA1R = 0x0fffc000;//0~13号过滤器组关联到fifo0,14~27号过滤器组关联到fifo1  

    

  CAN1->FA1R &= ~(1<<14);//禁用过滤器组14  

    

   /*  

  过滤器组0寄存器分为4个十六位过滤器:  

  标识符列表:  

  过滤器编号        匹配标准标识符             RTR       IDE           EXID[17:15]  

     0              0x7cb(111 1100 1011b)    数据帧    标准标识符     000b  

     1              0x4ab(100 1010 1011b)    数据帧    标准标识符     000b  

     2              0x7ab(111 1010 1011b)    数据帧    标准标识符     000b    

     3              0x40b(100 0000 1011b)    数据帧    标准标识符     000b    

  */  

  CAN1->sFilterRegister[14].FR1 &= 0x00000000;  

  CAN1->sFilterRegister[14].FR2 &= 0x00000000;  

  CAN1->sFilterRegister[14].FR1 |= ((0x7cb<<5)|(0<<4)|(0<<3));  

  CAN1->sFilterRegister[14].FR1 |= ((0x4ab<<21)|(0<<20)|(0<<19));  

  CAN1->sFilterRegister[14].FR2 |= ((0x7ab<<5)|(0<<4)|(0<<3));  

  CAN1->sFilterRegister[14].FR2 |= ((0x40b<<21)|(0<<20)|(0<<19));  

    

  CAN1->FA1R |= (1<<14);//使能过滤器组14  

     

  CAN1->FMR &= ~1; //过滤器组正常工作  

    

  while(1)  

  {  

    /*  

    选择空的发送邮箱:  

    标准标识符0x7ab(111 1010 1011b)  

    数据帧  

    不使用扩展标识符  

    */  

    if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )  

    {  

      empty_box = ((CAN1->TSR>>24) & 0x00000003);   

      CAN1->sTxMailBox[empty_box].TIR = (0x7ab<<21);    

        

      CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;  

      CAN1->sTxMailBox[empty_box].TDTR |= 0x00000008;//发送数据长度为8  

        

      CAN1->sTxMailBox[empty_box].TDLR = 0x12345678;  

        

      CAN1->sTxMailBox[empty_box].TDHR = 0x9abcdef0;  

        

      CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送  

    }  

    else  

    {  

      MyDebugger_LEDs(orange, on);  

    }  

    Delay(100);  

      

     /*  

    选择空的发送邮箱:  

    标准标识符0x4ab(100 1010 1011b)  

    数据帧  

    不使用扩展标识符  

    */  

    if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )  

    {  

      empty_box = ((CAN1->TSR>>24) & 0x00000003);   

      CAN1->sTxMailBox[empty_box].TIR = (0x4ab<<21);    

        

      CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;  

      CAN1->sTxMailBox[empty_box].TDTR |= 0x00000008;//发送数据长度为8  

        

      CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;  

        

      CAN1->sTxMailBox[empty_box].TDHR = 0x9abcdef0;  

        

      CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送  

    }  

    else  

    {  

      MyDebugger_LEDs(orange, on);  

    }  

    Delay(100);  

      

     /*  

    选择空的发送邮箱:  

    标准标识符0x7cb(100 1010 1011b)  

    数据帧  

    不使用扩展标识符  

    */  

    if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )  

    {  

      empty_box = ((CAN1->TSR>>24) & 0x00000003);   

      CAN1->sTxMailBox[empty_box].TIR = (0x7cb<<21);    

        

      CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;  

      CAN1->sTxMailBox[empty_box].TDTR |= 0x00000006;//发送数据长度为6  

        

      CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;  

        

      CAN1->sTxMailBox[empty_box].TDHR = 0x00009abc;  

        

      CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送  

    }  

    else  

    {  

      MyDebugger_LEDs(orange, on);  

    }  

    Delay(100);  

      

     /*  

    选择空的发送邮箱:  

    标准标识符0x40b(100 0000 1011b)  

    数据帧  

    不使用扩展标识符  

    */  

    if( CAN1->TSR & ((1<<26)|(1<<27)|(1<<28)) )  

    {  

      empty_box = ((CAN1->TSR>>24) & 0x00000003);   

      CAN1->sTxMailBox[empty_box].TIR = (0x40b<<21);    

        

      CAN1->sTxMailBox[empty_box].TDTR &= 0xfffffff0;  

      CAN1->sTxMailBox[empty_box].TDTR |= 0x00000004;//发送数据长度为4  

        

      CAN1->sTxMailBox[empty_box].TDLR = 0x56781234;  

        

      CAN1->sTxMailBox[empty_box].TDHR = 0x00000000;  

        

      CAN1->sTxMailBox[empty_box].TIR |= (1<<0);//请求发送  

    }  

    else  

    {  

      MyDebugger_LEDs(orange, on);  

    }  

    Delay(100);  

      

   }  

}  

  

/****************************************  

  函数名:CAN_GPIO_config  

  参数:无  

  返回值:无  

  功能:设置CAN1,2控制器用到IO口  

  CAN1_TX---------PD1  

  CAN1_RX---------PB8  

  CAN2_TX---------PB13  

  CAN2_RX---------PB5  

****************************************/  

void CAN_GPIO_config()  

{  

  RCC->AHB1ENR |= ((1<<1) | (1<<3));//使能GPIOB、D时钟  

  GPIOB->AFR[0] |= 0x00900000;      //AF9  

  GPIOB->AFR[1] |= 0x00900009;  

  GPIOD->AFR[0] |= 0x00000090;  

      

  GPIOB->MODER &= 0xF3FCF3FF; //第二功能  

  GPIOB->MODER |= 0x08020800;  

  GPIOD->MODER &= 0xFFFFFFF3;   

  GPIOD->MODER |= 0x00000008;  

    

  GPIOB->OSPEEDR &= 0xF3FCF3FF; //50M  

  GPIOB->OSPEEDR |= 0x08020800;  

  GPIOD->OSPEEDR &= 0xFFFFFFF3;   

  GPIOD->OSPEEDR |= 0x00000008;  

    

  GPIOB->PUPDR &= 0xF3FCF3FF;   //上拉  

  GPIOB->PUPDR |= 0x04010400;  

  GPIOD->PUPDR &= 0xFFFFFFF3;   

  GPIOD->PUPDR |= 0x00000004;   

}  

  

/****************************************  

  函数名:CAN2_RX1_IRQHandler  

  参数:无  

  返回值:无  

  功能:CAN2fifo1接收中断处理  

        把信息存进循环队列  

****************************************/  

void CAN2_RX1_IRQHandler()  

{  

  if(CAN2->RF1R & (0x00000003))//接收到新的消息,fifo1非空  

  {  

    Producer++;  

    if(Producer == RECEIVE_BUFFER_SIZE)Producer = 0;  

    if(Producer != Consumer)  

    {  

      CAN2_receive_buffer[Producer][0] = CAN2->sFIFOMailBox[1].RIR;  

      CAN2_receive_buffer[Producer][1] = CAN2->sFIFOMailBox[1].RDTR;  

      CAN2_receive_buffer[Producer][2] = CAN2->sFIFOMailBox[1].RDLR;  

      CAN2_receive_buffer[Producer][3] = CAN2->sFIFOMailBox[1].RDHR;  

    }  

    else  

    {  

      if(Producer == 0)Producer = RECEIVE_BUFFER_SIZE;  

      Producer--;  

      MyDebugger_LEDs(blue, on);  

    }     

    CAN2->RF1R |= (1<<5);//释放邮箱  

  }  

    

  if(CAN2->RF1R & (1<<3))//fifo0满  

  {  

    MyDebugger_LEDs(red, on);  

    CAN2->RF1R &= ~(1<<3);  

  }  

    

  if(CAN2->RF1R & (1<<4))//fifo0溢出  

  {  

    MyDebugger_LEDs(red, on);  

    CAN2->RF1R &= ~(1<<4);  

  }  

}  

  

/****************************************  

  函数名:TIM7_init  

  参数:无  

  返回值:无  

  功能:初始化定时器7  

        作1s定时用  

****************************************/  

void TIM7_init()  

{  

  RCC->APB1ENR |= (1<<5); //打开TIM7时钟  

  TIM7->PSC = 8399; //对时钟84M进行8400分频,使得计数频率为10k  

  TIM7->ARR = 10000;  //定时一秒  

  TIM7->CNT = 0;  //清空计数器  

  TIM7->CR1 |= (1<<7); //自动重装载预装载使能  

  TIM7->DIER |= 1; //使能中断  

    

  NVIC->IP[55] = 0xe0;  

  NVIC->ISER[1] |= (1<<(55-32));  

    

  TIM7->CR1 |= 1; //开始计时  

}  

  

/****************************************  

  函数名:TIM7_IRQHandler  

  参数:无  

  返回值:无  

  功能:定时器7中断处理  

        1s定时到  

        把can2收到的信息转换格式  

        用usrt发送到超级终端显示  

****************************************/  

void TIM7_IRQHandler(void)  

{  

  u32 length;  

  if(TIM7->SR)  

  {  

    length = get_rece_data();  

    MyDebugger_Message( UART_send_buffer, length );  

    TIM7->SR &= ~(0x0001);   

  }  

}  

  

/****************************************  

  函数名:get_rece_data  

  参数:无  

  返回值:length 整理后要发送数据的长度  

  功能:把循环队列的信息取出  

        进行格式转换  

        把信息存到uart发送缓冲区  

****************************************/  

u32 get_rece_data()  

{  

  u8 filter_No;  

  u8 Data_length;   

  char i;  

  u32 length = 0;  

  const char ascii[16] = {'0', '1', '2', '3', '4', '5', '6', '7',  

                          '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};  

  while(1)  

  {  

    if(Producer != Consumer)  

      {  

        Consumer++;  

        if(Consumer == RECEIVE_BUFFER_SIZE)Consumer=0;  

          

        UART_send_buffer[length++] = '\n';  

        UART_send_buffer[length++] = '\r';  

        //Filter No.xx  

        UART_send_buffer[length++] = 'F';  

        UART_send_buffer[length++] = 'i';   

        UART_send_buffer[length++] = 'l';  

        UART_send_buffer[length++] = 't';  

        UART_send_buffer[length++] = 'e';  

        UART_send_buffer[length++] = 'r';   

        UART_send_buffer[length++] = ' ';  

        UART_send_buffer[length++] = 'N';   

        UART_send_buffer[length++] = 'o';  

        UART_send_buffer[length++] = '.';  

     

        filter_No = (CAN2_receive_buffer[Consumer][1]>>8) & 0x000000ff;  

        UART_send_buffer[length++] = filter_No%100/10 + '0';  

        UART_send_buffer[length++] = filter_No%10 + '0';  

        UART_send_buffer[length++] = '\n';  

        UART_send_buffer[length++] = '\r';  

          

        //DataLength:x  

        UART_send_buffer[length++] = 'D';   

        UART_send_buffer[length++] = 'a';  

        UART_send_buffer[length++] = 't';   

        UART_send_buffer[length++] = 'a';  

        UART_send_buffer[length++] = 'L';  

        UART_send_buffer[length++] = 'e';   

        UART_send_buffer[length++] = 'n';  

        UART_send_buffer[length++] = 'g';   

        UART_send_buffer[length++] = 't';  

        UART_send_buffer[length++] = 'h';  

        UART_send_buffer[length++] = ':';  

        Data_length = CAN2_receive_buffer[Consumer][1] & 0x0000000f;  

        UART_send_buffer[length++] = Data_length % 10 + '0';  

        UART_send_buffer[length++] = '\n';  

        UART_send_buffer[length++] = '\r';  

          

          

        if(CAN2_receive_buffer[Consumer][0] & (1<<1))  

        {  

          UART_send_buffer[length++] = 'R';   

          UART_send_buffer[length++] = 'e';  

          UART_send_buffer[length++] = 'm';   

          UART_send_buffer[length++] = 'o';  

          UART_send_buffer[length++] = 't';  

          UART_send_buffer[length++] = 'e';   

          UART_send_buffer[length++] = 'F';  

          UART_send_buffer[length++] = 'r';   

          UART_send_buffer[length++] = 'a';  

          UART_send_buffer[length++] = 'm';  

          UART_send_buffer[length++] = 'e';  

        }  

        else  

        {  

          UART_send_buffer[length++] = 'D';   

          UART_send_buffer[length++] = 'a';  

          UART_send_buffer[length++] = 't';   

          UART_send_buffer[length++] = 'a';   

          UART_send_buffer[length++] = 'F';  

          UART_send_buffer[length++] = 'r';   

          UART_send_buffer[length++] = 'a';  

          UART_send_buffer[length++] = 'm';  

          UART_send_buffer[length++] = 'e';  

        }  

        UART_send_buffer[length++] = '\n';  

        UART_send_buffer[length++] = '\r';          

          

          

        if(CAN2_receive_buffer[Consumer][0] & (1<<2))  

        {  

          UART_send_buffer[length++] = 'e';   

          UART_send_buffer[length++] = 'x';  

          UART_send_buffer[length++] = 't';   

          UART_send_buffer[length++] = ' ';  

          UART_send_buffer[length++] = 'I';  

          UART_send_buffer[length++] = 'D';  

          UART_send_buffer[length++] = ':';  

            

          UART_send_buffer[length++] =   

            ascii[CAN2_receive_buffer[Consumer][0] >> 31];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 27)& 0x0000000f];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 23)& 0x0000000f];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 19)& 0x0000000f];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 15)& 0x0000000f];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 11)& 0x0000000f];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 7)& 0x0000000f];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 3)& 0x0000000f];  

        }  

        else  

        {  

          UART_send_buffer[length++] = 's';   

          UART_send_buffer[length++] = 't';  

          UART_send_buffer[length++] = 'd';   

          UART_send_buffer[length++] = ' ';  

          UART_send_buffer[length++] = 'I';  

          UART_send_buffer[length++] = 'D';  

          UART_send_buffer[length++] = ':';  

            

          UART_send_buffer[length++] =   

            ascii[CAN2_receive_buffer[Consumer][0] >> 29];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 25)& 0x0000000f];  

          UART_send_buffer[length++] =   

            ascii[(CAN2_receive_buffer[Consumer][0] >> 21)& 0x0000000f];          

        }  

        UART_send_buffer[length++] = '\n';  

        UART_send_buffer[length++] = '\r';  

          

        UART_send_buffer[length++] = 'D';   

        UART_send_buffer[length++] = 'a';  

        UART_send_buffer[length++] = 't';  

        UART_send_buffer[length++] = 'a';  

        UART_send_buffer[length++] = ':';  

        if(Data_length > 4)  

        {  

          for(i = 2*Data_length - 8; i > 0; i--)  

            UART_send_buffer[length++] =   

              ascii[(CAN2_receive_buffer[Consumer][3] >> ((i-1)*4))& 0x0000000f];  

            

          for(i = 8; i > 0; i--)  

            UART_send_buffer[length++] =   

              ascii[(CAN2_receive_buffer[Consumer][2] >> ((i-1)*4))& 0x0000000f];  

        }  

        else  

        {  

          for(i = 2*Data_length; i > 0; i--)  

            UART_send_buffer[length++] =   

              ascii[(CAN2_receive_buffer[Consumer][2] >> ((i-1)*4))& 0x0000000f];           

        }  

        UART_send_buffer[length++] = '\n';  

        UART_send_buffer[length++] = '\r';  

      }  

    else  

      break;  

  }  

  return length;  

}  

  

  

void Delay(uint32_t nTime)  

{   

  Gb_TimingDelay = nTime;  

  

  while(Gb_TimingDelay != 0);  

}  

  

void SysTick_Handler(void)  

{  

  if (Gb_TimingDelay != 0x00)  

  {   

    Gb_TimingDelay--;  

  }  

}  

运行结果:


关键字:stm32f407  CAN控制器  操作寄存器 引用地址:stm32f407之CAN控制器(操作寄存器)

上一篇:stm32f407之DAC(操作寄存器)
下一篇:stm32f407之数字滤波(操作寄存器)

推荐阅读最新更新时间:2024-03-16 16:14

stm32f407】外部中断实现按键中断方式
一.外部中断 STM32F4的每个IO都可以作为外部中断的中断输入口,这点也是STM32F4的强大之处。STM32F407的中断控制器支持22个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。 STM32F407的22个外部中断为: EXTI线0~15:对应外部IO口的输入中断。 EXTI线16:连接到PVD输出。 EXTI线17:连接到RTC闹钟事件。 EXTI线18:连接到USB OTG FS唤醒事件。 EXTI线19:连接到以太网唤醒事件。 EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件。 EXTI线21:连接到RTC入侵和时间戳事件。 EXTI线22:连接到RTC唤醒事件
[单片机]
STM32F407的UDP发送数据
探究WaveShare的F407的板子好几天了,这两天一直止步于网卡模块的udp发包,因为截包工具总是收不到我代码里面发出去的数据包,我的要求是只发特定数据,不管收到的数据包 记录下整个测试过程,以便以后翻阅 使用开发板自带的例程,udp_echo_server的例子,在此基础上修改,main函数是 int main(void) {   /*! At this stage the microcontroller clock setting is already configured to         168 MHz, this is done through SystemInit() function which
[单片机]
stm32f207/stm32f407擦除内部flash讲解
STM32F4Discovery开发包使用的STM32F407VGT6芯片,内部FLASH有1M之多。平时写的代码,烧写完之后还有大量的剩余。有效利用这剩余的FLASH能存储不少数据。因此研究了一下STM32F4读写内部FLASH的一些操作。 【STM32F4 内部Flash的一些信息】 STM32F407VG的内部FLASH的地址是:0x08000000,大小是0x00100000。 写FLASH的时候,如果发现写入地址的FLASH没有被擦除,数据将不会写入。FLASH的擦除操作,只能按Sector进行。不能单独擦除一个地址上的数据。因此在写数据之前需要将地址所在Sector的所有数据擦除。 在STM32F4的编程手册上可找到F
[单片机]
stm32f207/<font color='red'>stm32f407</font>擦除内部flash讲解
STM32F407 RTC 配置理解与总结
RTC: Real time clock 相比较而言,STM32F407的RTC比STM32F1的更加容易配置。当然,F4的资源相对也就更加丰富很多了。具体的资源可查看官方参考手册,通过下面的图表也可以了解其大致功能 1、开始的时候对于 ALRAM A/B的功能没有怎么理解,后面再来看时发现其很简单,举个简单的例子,就比如,定的闹钟,当然,这个也是可以实现闹钟的功能。只是通过这个简单的例子来说明,ALARM A/B的用途或者功能吧 2、自动唤醒与时间戳及时间篡改事件,与1的差不多,细细体会就知道 3、RTC_AFO 与 RTC_AFI 就是对外输出及检测外部时间事件 4、 RTC
[单片机]
<font color='red'>STM32F407</font> RTC 配置理解与总结
stm32F407-RDA5820N模块的使用
RDA5820N是一款广播FM接受或发射模块,支持50M~115M频段FM和RDS/RBDS接收和发射,支持电源范围为1.8-5.5V。更多详细介绍请看数据手册。 RDA5820N模块是在做2018年电赛无线话筒扩音系统时使用的发射模块,接收模块用的使TEA5767,当然RDA5820N也是可以的,但是当时考虑到价格,所以用了TEA5767,本篇文章主要分享RDA5820N的.c和.h文件。 rda5820.h #ifndef __RDA5820_H #define __RDA5820_H #include sys.h #include myiic.h #define RDA5820_R00 0X0
[单片机]
stm32F407-RDA5820N模块的使用
STM32F407】第1章 ThreadX USBX初学准备工作
1.1 初学者重要提示 学会ThreadX USBX相关资源的获取方法,做到心中有数,否则心里老是没底。 1.2 开发环境(MDK,IAR和GCC) 1、 IDE:MDK,IAR和GCC三大平台齐聚。 MDK要使用5.30及其以上版本(务必是5.30及其以上版本)。 下载地址: http://www. armbbs.cn/forum.php? mod=viewthread&tid=96992 。 IAR要使用8.30及其以上版本。 下载地址: http://www. armbbs.cn/forum.php? mod=viewthread&tid=87220 。 Embedded Studio要使用5.10及
[单片机]
【<font color='red'>STM32F407</font>】第1章 ThreadX USBX初学准备工作
STM32F4 内部flash驱动(寄存器操作
stm32f4_flash.c /************************************************************************************************************* * 文件名: stm32f4_flash.c * 功能: STM32F4 内部FLASH编程驱动函数 * 作者: cp1300@139.com * 创建时间: 2013-10-20 * 最后修改时间: 2018-01-13 * 详细: 用于STM32F4内部flash读写驱动 2018-01-13:初始版本,默认位宽为32位,写入的数据必须32位对齐,供
[单片机]
基于STM32F105微控制器的双CAN冗余设计方案
  控制器局域网( Contro llerA reaN etwo rk, CAN)是一种多主方式的串行通讯总线。CAN 总线具有较高的位速率, 很强的抗电磁干扰性, 完善的错误检测机制, 在汽车、制造业以及航空工业领域中得到广泛应用 。由于船舶机舱环境极为恶劣, 且船舶航行过程中维修条件不如陆上, 对CAN 通信的可靠性要求很高, 采取双CAN 冗余总线提高通信可靠性。本文提出一种基于STM32F105微控制器的双CAN 冗余设计方案。   1 硬件平台组成   STM32F105是STM icroe lectron ics公司推出的一款基于ARM Co rtex- M3内核的32位微控制器, 其内核是专门设计于满足高性能
[单片机]
基于STM32F105微<font color='red'>控制器</font>的双<font color='red'>CAN</font>冗余设计方案
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多精选电路图
换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved