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收发器
程序:
- /************************************
- 标题:操作CAN的练习
- 软件平台:IAR for ARM6.21
- 硬件平台:stm32f4-discovery
- 主频:168M
- 描述:通过硬件收发器连接CAN1,CAN2
- 组成一个两个端点的网络
- CAN1循环发出数据帧
- CAN2接收过滤数据帧
- 用uart把CAN2接收到
- 的数据帧发到超级终端
- author:小船
- data:2012-08-14
- *************************************/
- #include <stm32f4xx.h>
- #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--;
- }
- }
运行结果:
CAN控制器-配置过滤器的更多相关文章
- springboot环境下配置过滤器和拦截器
以前我们在配置过滤器和拦截器的时候,都是一个类继承一个接口,然后在xml中配置一下就ok 但是,但是,这是springboot的环境,没有xml的配置.所以我们还要继续学习啊啊啊啊啊~~~~~ 先简单 ...
- springboot 配置过滤器
能配置例外 先写配置文件类 FilterConfig.java package com.ty.tyzxtj.config; import javax.servlet.Filter; import or ...
- springboot配置过滤器和拦截器
import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.Http ...
- Spring Boot配置过滤器的两种方式
过滤器(Filter)是Servlet中常用的技术,可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,常用的场景有登录校验.权限控制.敏感词过滤等,下面介绍下Spring Boot配置过 ...
- 使用SpringBoot的方式配置过滤器
springboot 不存在web.xml 那么如何配置过滤器呢 springboot提供了一种方式 通过spring容器配置 @Bean public FilterRegistrationBean ...
- CAS学习笔记三:SpringBoot自动配置与手动配置过滤器方式集成CAS客户端
本文目标 基于SpringBoot + Maven 分别使用自动配置与手动配置过滤器方式集成CAS客户端. 需要提前搭建 CAS 服务端,参考 https://www.cnblogs.com/hell ...
- angualrjs学习总结二(作用域、控制器、过滤器)
一:Scope简介 Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带.Scope 是一个对象,有可用的方法和属性.Scope 可应用在视图和控制器上. ...
- springboot中配置过滤器以及可能出现的问题
在springboot添加过滤器有两种方式: 1.通过创建FilterRegistrationBean的方式(建议使用此种方式,统一管理,且通过注解的方式若不是本地调试,如果在filter中需要增加c ...
- Cisco无线控制器配置Radius
使用Cisco无线控制器管理AP,配置Radius服务器,用于企业加密wifi的认证. 结合上一篇文档进行操作: http://www.cnblogs.com/helloworldtoyou/p/80 ...
随机推荐
- 所不为人知的Python装饰器
装饰器可以说是Python中非常重要的特性之一.有些人要么从没使用过装饰器,要么就是对装饰器的使用一知半解.也有些人觉得装饰器很简单:"装饰器不就是那些把函数作为参数并输出一个函数的函数&q ...
- Axure的中继器如何实现两个列表之间的交互
Axure RP 8安装包+注册码+中文语言包下载地址如下: 链接: https://pan.baidu.com/s/1nwRnCUl 密码: yy36 将中文语言包下的lang文件夹直接放在安装Ax ...
- 排序算法之low B三人组
排序low B三人组 列表排序:将无序列表变成有充列表 应用场景:各种榜单,各种表格,给二分法排序使用,给其他算法使用 输入无序列表,输出有序列表(升序或降序) 排序low B三人组 1. 冒泡排序 ...
- cookie和session的那些事
对于经常网购的朋友来说,经常会遇到一种情况: 打开淘宝或京东商城的首页,输入个人账号和密码进行登陆,然后进行购物,支付等操作都不需要用户再次输入用户名和密码 但是如果用户换一个浏览器或者等几个小时后再 ...
- iOS-FMDB事务【批量更新数据】
打开数据库(sqlite) ///打开数据库 + (BOOL)openDataBase{ _TYDatabase = [[FMDatabase alloc]initWithPath:[self dat ...
- Android图像处理 - 高斯模糊的原理及实现
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 由 天天P图攻城狮 发布在云+社区 作者简介:damonxia(夏正冬),天天P图Android工程师 前言 高斯模糊是图像处理中几乎每个程序员 ...
- 洛谷 [P1024]一元三次方程求解
一道水题然而坑点很多. #include <iostream> #include <cstdio> #include <algorithm> #include &l ...
- BZOJ 3168: [Heoi2013]钙铁锌硒维生素 [线性基 Hungary 矩阵求逆]
3168: [Heoi2013]钙铁锌硒维生素 题意:给一个线性无关组A,再给一个B,要为A中每个向量在B中选一个可以代替的向量,替换后仍然线性无关.判断可行和求字典序最小的解 PoPoQQQ orz ...
- BZOJ 3622: 已经没有什么好害怕的了 [容斥原理 DP]
3622: 已经没有什么好害怕的了 题意:和我签订契约,成为魔法少女吧 真·题意:零食魔女夏洛特的结界里有糖果a和药片b各n个,两两配对,a>b的配对比b>a的配对多k个学姐就可能获胜,求 ...
- BZOJ 1982: [Spoj 2021]Moving Pebbles [博弈论 对称]
给你N堆Stone,两个人玩游戏. 每次任选一堆,首先拿掉至少一个石头,然后移动任意个石子到任意堆中. 谁不能移动了,谁就输了... 以前在poj做过已经忘记了... 构造对称,选最多的一堆往其他堆分 ...