历史上的今天
返回首页

历史上的今天

今天是:2024年09月20日(星期五)

正在发生

2018年09月20日 | stm32f407之CAN控制器(操作寄存器)

2018-09-20 来源:eefocus

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--;  

  }  

}  

运行结果:


推荐阅读

史海拾趣

Akros[台湾超硕股份有限公司]公司的发展小趣事

面对日益激烈的市场竞争,Akros公司积极寻求市场拓展的机会。公司开始参加国际电子展会,与全球各地的客户建立联系。通过展示其独特的技术优势和高质量的产品,Akros逐渐赢得了国际市场的认可。同时,公司还加强了与全球供应链的合作,实现了原材料的全球化采购,降低了生产成本,提高了产品的竞争力。

AMOTECH(阿莫泰克)公司的发展小趣事

进入21世纪,AMOTECH继续深耕电子领域,特别是在压敏电阻技术上取得了重大突破。2003年,公司的压敏电阻产品被产业资源部评为世界一流产品,这一成就不仅提升了AMOTECH在全球电子行业中的地位,也为其后续发展奠定了坚实基础。同年,公司还成功在韩国安全商协会自动报价首次公开募股,为公司的进一步扩张提供了资金支持。

益升华(Essentra)公司的发展小趣事

随着公司业务的不断发展,益升华(Essentra)公司意识到海外市场的重要性。于是,公司开始积极拓展海外市场,通过设立海外分公司、与当地企业合作等方式,将产品推向全球。在拓展海外市场的过程中,益升华(Essentra)公司始终坚持品质第一的原则,赢得了海外客户的信赖和好评。如今,公司的工业零部件全球网络已覆盖23个国家或地区,成为国际知名的塑料及金属零部件生产商和销售商。

Eurosil Electronics Ltd公司的发展小趣事

作为一家有社会责任感的企业,Eurosil始终关注社会公益事业。公司积极参与各种公益活动,如捐赠教育设施、支持贫困地区发展等。通过这些活动,Eurosil不仅回馈了社会,也提升了企业的社会形象和品牌价值。同时,公司还鼓励员工参与志愿服务活动,培养员工的公益意识和社会责任感。

3D PLUS公司的发展小趣事

随着技术的不断发展和市场的不断扩大,3D PLUS公司开始将目光投向国际市场。公司积极参加国际电子行业的展会和交流活动,与国际同行进行技术合作和交流,不断提升自身的技术水平和国际影响力。同时,公司还积极拓展海外销售渠道,将3D技术和产品推向全球市场,为全球客户提供高效、便捷的3D解决方案。这些努力不仅提升了公司在国际市场的知名度,也为公司的长期发展奠定了坚实的基础。

以上五个故事均基于3D PLUS公司在电子行业中的实际发展情况编写,旨在客观描述公司在3D技术领域的成长与进步。

CONTRINEX公司的发展小趣事

在数控加工领域,Contrinex的数字测量智能传感器带来了革命性的变革。这些先进的传感器能够精确实时地测量拉杆位置,通过智能决策,确保加工精度,防止潜在损坏。其卓越的性能和稳定性,使得Contrinex在这一领域取得了显著的成绩,并赢得了众多客户的赞誉。

问答坊 | AI 解惑

我自己的DSP开发板

系统简介 SHX-DSP2812开发板是基于TMS320F2812的学习开发平台,它将TMS320F2812的功能发挥的淋漓尽致,而且本板所配的用户手册详实易懂,是初学者学习2812 的首选之品。 系统资源 DSP 处理器TMS320F2812 ,最高工作频率150MHz; ...…

查看全部问答>

RF技术交流帖

可以聊RF的器件、RF的技术、RF的前景,希望大家的参与支持; 有做无线的朋友大家都来聊聊自己的心得,包括有什么解决不了的困惑也提出来,我想各位潜水的高手到时候一定要站出来,不吝赐教哦!本人做RF也有些时间了,有些问题还要向各位大虾赐教或 ...…

查看全部问答>

delphi串口通信与工程实践

一本找了很长时间的电子书,免费下载…

查看全部问答>

WINCE4.0上网页的发布

请教各位高手: 我想在WINCE4.0上发布一个可供远程浏览的交互式网页,网页上的数据从ARM9的ISA总线上过来并存在内存中,希望在网页中能浏览并修改。 我看了“成都英创网页上有相关调用COM组件进行远程控制的例子”,那个例子中网页(用ASP实现) ...…

查看全部问答>

单片机课程设计指导

求 :楼然苗 北京航空航天大学出版社 的光盘..... 下载地址,或者通过邮件(puyo730@126.com)和QQ(137861176) 谢谢.…

查看全部问答>

迷茫了,到底是linux 还是 wince????

感觉linux在嵌入式方面被吵的很火,wince就差点了,不知道实际应用上究竟那个更流行,更使用,wince 和 linux各自的优势,(linux是免费开源的就不用强调了,请按行业方面介绍一下)。wince下的开发,是不是主要在应用层啊。底层用的多吗? …

查看全部问答>

关于wince5.0下虚拟串口的问题!

我的开发板的cpu是s3c2410的,操作系统是wince5.0。买了一个gps接收器和一个蓝牙棒(板子上不带蓝牙),将蓝牙棒和板子的usb连接,wince下的一个蓝牙管理程序可以找到gps,但是我用OZi for ppc的软件只支持com口的数据传输,在笔记本上蓝牙口可以自 ...…

查看全部问答>

有谁知道为什么我的libc库中的sprintf函数输出不正确呢

我的开发板是epson的c33,编译工具是由epson提供的gnu33。…

查看全部问答>

PROTEL 中,新建一元器件时,引脚定义是否一定要和实际的封装引脚一直?

PROTEL 中,新建一元器件时,引脚定义是否一定要和实际的封装引脚一致? …

查看全部问答>