CAN协议特点

1.多主控制

所有单元都可以发送消息,根据标识符(Identifier简称ID)决定优先级。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作

2.系统的柔软性

与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变

3.通信速度较快,通信距离远

最高 1Mbps(距离小于40M),最远可达10KM(速率低于5Kbps)

4.具有错误检测、错误通知和错误恢复功能

所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制

结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)

5.故障封闭功能

CAN可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去

6. 连接节点多

CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制

总线拓扑

总线电平分为显性电平和隐性电平两种。“显性”具有“优先”的意味,只要有一个单元输出显性电平,总线上即为显性电平。并且,“隐性”具有“包容”的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平

帧的种类

帧的种类及用途



数据帧的构成

帧起始:数据帧开始

仲裁段:该帧优先级

控制段:数据的字节数及保留位

数据段:数据的内容,可发送0~8个字节的数据

CRC段:检查帧的传输错误

ACK段:确认正常接收

帧结束:数据帧结束

遥控帧的构成

遥控帧没有数据帧的数据段



错误帧

错误标志:包括主动错误标志和被动错误标志两种。主动错误标志为6位的显性位;被动错误标志为6位的隐性位

错误界定符:由8位的隐性位构成

过载帧

过载标志:6位的显性位(与主动错误标志的构成相同)

过载界定符:8位的隐性位(与错误界定符的构成相同)

帧间隔

间隔:3位的隐性位

延迟传送:8位的隐性位

总线空闲:隐性电平,无长度限制(0 亦可)

数据帧

帧起始

标准、扩展格式相同。1位的显性位



仲裁段



扩展帧的仲裁段有29位,可以出现229种报文。标准帧的仲裁段是11位,可以出现211种报文。扩展帧能扩展更多的CAN节点,更好地支持上层协议

控制段



数据长度码和字节数的关系:



“D”为显性电平;“R”为隐性电平

数据段

数据段可包含0~8个字节的数据。从MSB(最高位)开始输出



CRC段

由15位的CRC顺序和1位的CRC界定符(用于分隔的位)构成



ACK段

由ACK槽(ACK Slot)和ACK界定符2位构成



帧结束

由7位的隐性位构成

优先级的决定

连续输出显性电平最多的单元可继续发送



数据帧和遥控帧的优先级

具有相同ID 的数据帧和遥控帧在总线上竞争时,仲裁段的最后一位(RTR)为显性位的数据帧具有优先权,可继续发送



标准格式和扩展格式的优先级

标准格式的RTR位为显性位的具有优先权,可继续发送

bxCAN工作模式

bxCAN有3个主要的工作模式:初始化、正常和睡眠模式

初始化模式

设置CAN_MCR寄存器的INRQ位为’1’,请求bxCAN进入初始化模式,然后等待硬件对CAN_MSR寄存器的INAK位置’1’来进行确认

正常模式

软件对CAN_MCR寄存器的INRQ位清’0’,来请求从初始化模式进入正常模式,然后等待硬件对CAN_MSR寄存器的INAK位置’1’的确认

睡眠模式

软件对CAN_MCR寄存器的SLEEP位置’1’,来请求进入这一模式

测试模式

通过对CAN_BTR寄存器的SILM和LBKM配置

静默模式(CAN_Mode_Silent)

通过对CAN_BTR寄存器的SILM位置’1’,来选择静默模式



环回模式(CAN_Mode_LoopBack)

通过对CAN_BTR寄存器的LBKM位置’1’,来选择环回模式



环回静默模式(CAN_Mode_Silent_LoopBack)

通过对CAN_BTR寄存器的LBKM和SILM位同时置’1’,可以选择环回静默模式

超过8字节数据发送

可以采取拆包、组包方法。记录包id和是否为结尾包标识。接收方如果未接收完整个包,直到接收完整包再进行处理

详细参考:uavcan

CAN配置步骤

1.使能CAN时钟

2.使能GPIO端口时钟

3.GPIO端口模式设置

4.配置CAN工作模式、波特率等

5.配置CAN筛选器

6.选择CAN中断类型,开启中断

7.初始化NVIC外设

8.编写CAN中断处理函数

9.CAN发送和接收消息

10.CAN状态获取

硬件设计



举例



typedef struct
{
uint32_t StdId; //标准标识符
uint32_t ExtId; //扩展标识符
uint8_t IDE; //标识符选择
uint8_t RTR; //远程发送请求
uint8_t DLC; //发送数据长度
uint8_t Data[8]; //数据字节
} CanTxMsg; void CAN_transmit(u8 *data, u8 len)
{
u8 i = 0, box;
CanTxMsg msg = {0}; msg.StdId = 0x12;
msg.ExtId = 0x12;
msg.IDE = CAN_Id_Standard; //使用标准标识符
msg.RTR = CAN_RTR_Data; //数据帧
msg.DLC = len; for(i = 0; i < len; i++)
{
msg.Data[i] = data[i];
} box = CAN_Transmit(CAN1, &msg); while(CAN_TransmitStatus(CAN1, box) == CAN_TxStatus_Failed); return;
} u8 CAN_receive(u8 *data)
{
u8 i = 0;
CanRxMsg msg = {0}; if(CAN_MessagePending(CAN1, CAN_FIFO0) == 0)
{
return 0;
} CAN_Receive(CAN1, CAN_FIFO0, &msg); for(i = 0; i < msg.DLC; i++)
{
data[i] = msg.Data[i];
} return msg.DLC;
} #ifdef CAN_IT
void USB_LP_CAN1_RX0_IRQHandler()
{
u8 data[8], len; if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) == SET)
{
len = CAN_receive(data); CAN_transmit(data, len); led1 = ~led1;
} CAN_ClearFlag(CAN1, CAN_IT_FMP0);
}
#endif typedef struct
{
uint16_t CAN_Prescaler; //波特率分频器
uint8_t CAN_Mode; //测试模式
uint8_t CAN_SJW; //重新同步跳跃宽度
uint8_t CAN_BS1; //时间段1
uint8_t CAN_BS2; //时间段2
FunctionalState CAN_TTCM; //时间触发通信模式
FunctionalState CAN_ABOM; //自动离线管理
FunctionalState CAN_AWUM; //自动唤醒模式
FunctionalState CAN_NART; //禁止报文自动重传
FunctionalState CAN_RFLM; //接收FIFO锁定模式
FunctionalState CAN_TXFP; //发送FIFO优先级
} CAN_InitTypeDef; typedef struct
{
uint16_t CAN_FilterIdHigh;
uint16_t CAN_FilterIdLow;
uint16_t CAN_FilterMaskIdHigh;
uint16_t CAN_FilterMaskIdLow;
uint16_t CAN_FilterFIFOAssignment; //过滤器位宽设置
uint8_t CAN_FilterNumber;
uint8_t CAN_FilterMode; //过滤器模式
uint8_t CAN_FilterScale; //过滤器位宽设置
FunctionalState CAN_FilterActivation; //过滤器激活
} CAN_FilterInitTypeDef; void CAN_init()
{
GPIO_InitTypeDef gpio11 =
{
GPIO_Pin_11,
GPIO_Speed_50MHz,
GPIO_Mode_IPU
}; GPIO_InitTypeDef gpio12 =
{
GPIO_Pin_12,
GPIO_Speed_50MHz,
GPIO_Mode_AF_PP
}; CAN_InitTypeDef can = {0};
CAN_FilterInitTypeDef can_filter = {0}; NVIC_InitTypeDef nvic =
{
USB_LP_CAN1_RX0_IRQn,
2,
2,
ENABLE
}; RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_Init(GPIOA, &gpio11);
GPIO_Init(GPIOA, &gpio12); can.CAN_Prescaler = 4;
can.CAN_Mode = CAN_Mode_LoopBack; //环回模式
can.CAN_SJW = CAN_SJW_1tq; //占用1个时间单元
can.CAN_BS1 = CAN_BS1_9tq; //占用9个时间单元
can.CAN_BS2 = CAN_BS2_8tq; //占用8个时间单元
can.CAN_TTCM = DISABLE; //详见上图
can.CAN_ABOM = DISABLE;
can.CAN_AWUM = DISABLE;
can.CAN_NART = ENABLE;
can.CAN_RFLM = DISABLE;
can.CAN_TXFP = DISABLE;
CAN_Init(CAN1, &can); can_filter.CAN_FilterIdHigh = 0;
can_filter.CAN_FilterIdLow = 0;
can_filter.CAN_FilterMaskIdHigh = 0;
can_filter.CAN_FilterMaskIdLow = 0;
can_filter.CAN_FilterFIFOAssignment = CAN_FilterFIFO0; //过滤器被关联到FIFO0
can_filter.CAN_FilterNumber = 0;
can_filter.CAN_FilterMode = CAN_FilterMode_IdMask; //过滤器组x的2个32位寄存器工作在标识符屏蔽位模式
can_filter.CAN_FilterScale = CAN_FilterScale_32bit; //过滤器位宽为单个32位
can_filter.CAN_FilterActivation = ENABLE; //过滤器被激活
CAN_FilterInit(&can_filter); #ifdef CAN_IT
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); NVIC_Init(&nvic);
#endif
} int main(void)
{
CAN_init(); for(i = 0; i < 8; i++)
{
txbuf[i] = i;
}
while(1)
{
led1 = ~led1; CAN_transmit(txbuf, 8); res = CAN_receive(rxbuf);
if(res)
{
for(i = 0; i < 8; i++)
{
rxbuf[i] = rxbuf[i] + 0x30;
}
printf("CAN_receive len %d, %s\n", res, rxbuf);
} delay_ms(1000);
}
}

CAN过滤器组配置:http://blog.csdn.net/zhangxuechao_/article/details/78488603

stm32 CAN通信 TJA1040的更多相关文章

  1. Stm32串口通信(USART)

    Stm32串口通信(UART) 串口通信的分类 串口通信三种传递方式 串口通信的通信方式 串行通信的方式: 异步通信:它用一个起始位表示字符的开始,用停止位表示字符的结束.其每帧的格式如下: 在一帧格 ...

  2. STM32 串口通信使用奇偶校验

    STM32串口通信如果使用奇偶校验,需要设置数据位长度为9bit USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USAR ...

  3. STM32串口通信UART使用

    STM32串口通信UART使用 uart使用的过程为: 1. 使能GPIO口和UART对应的总线时钟 2. 配置GPIO口的输出模式 3. 配置uart口相关的基本信息 4. 使能uart口的相关的中 ...

  4. stm32之通信

    本文提到的内容有以下几个方面: 通信概述 串口通信 I2C通信 CAN通信 SPI通信 I2S通信 USB通信 其他通信 一.通信概述 按照数据传送方式分: 串行通信(一条数据线.适合远距离传输.控制 ...

  5. STM32 USB-HID通信移植步骤

    大家可以使用压缩包中的UsbApp.exe调试本软件idVendor为:0483  idProduct为5750. 今天太晚了,明天还要上半天班,上位机软件找个时间在写一篇文章.请关注我的博客.压缩包 ...

  6. stm32串口通信实验,一点笔记

    第一次深入学习stm32,花了好长时间才看懂代码(主要是C语言学习不够深入),又花了段时间自己敲了一遍,然后比对教程,了解了利用中断来串口通信的设置方法. 板子是探索版f407,本实验工程把正点原子库 ...

  7. STM32 CAN通信

    最近在STM32上开发CAN通信相关内容,转载一篇个人认为不错的文章,看完了基本算明白了,能够实际操作了. 原文地址:  https://blog.csdn.net/ludaoyi88/article ...

  8. STM32串口通信配置(USART1+USART2+USART3+UART4) (转)

    一.串口一的配置(初始化+中断配置+中断接收函数) 1 /*====================================================================== ...

  9. STM32串口通信USART1转USART2问题解决

    使用的是STM32f103ZET6. 1.把文件main.c和usart.c中的所有usart1换成usart2 2.查看手册得知USART2的引脚是Tx->PA2,Rx->PA3,改变u ...

随机推荐

  1. WPF-支持异步操作的ObservableCollection-AsyncObservableCollection

    在进行WPF开发过程中,需要从一个新的线程中操作ObservableCollection,结果程序抛出一个NotSupportedException的错误 public class AsyncObse ...

  2. 使用 evo 工具评测 VI ORB SLAM2 在 EuRoC 上的结果

    http://www.liuxiao.org/2017/11/%E4%BD%BF%E7%94%A8-evo-%E5%B7%A5%E5%85%B7%E8%AF%84%E6%B5%8B-vi-orb-sl ...

  3. ES6深入浅出-4 迭代器与生成器-1.字面量增强

    今天的内容 字面量literal 写出来就是它的值 例如字符串hello.这就是自变量. 一个空对象,也是自变量 写出来就是代表它写出来的那个意思就是自变量. 与其相反的就是构造出来的.例如下面的ne ...

  4. LeetCode_290. Word Pattern

    290. Word Pattern Easy Given a pattern and a string str, find if str follows the same pattern. Here  ...

  5. 给APK签名,修改签名

    简介: 本来是不需要签名的,但是我有个android的专用设备,限制安装,但是售后给我通过了一个证书的验证. 那么我想装什么软件,就需要这个证书验证. 现在记录一下签名的主要过程,还有修改签名的方法. ...

  6. 鼠标滚动事件onscroll在firefox/chrome/Ie中执行次数的问题处理

    需要写一个滚动条滑动加载图片的程序,研究了一下onscroll在不同浏览器里的执行次数,分别如下: var i=0; E.addHandler(window, 'scroll', function() ...

  7. 最新 中细软java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.中细软等10家互联网公司的校招Offer,因为某些自身原因最终选择了 中细软.6.7月主要是做系统复习.项目复盘.LeetC ...

  8. element组件 MessageBox不能显示确认和取消按钮,记录正确使用方法!

    这里是局部引入 调用方式:

  9. sql 查找最晚入职员工

    题目描述 查找最晚入职员工的所有信息CREATE TABLE `employees` (`emp_no` int(11) NOT NULL,`birth_date` date NOT NULL,`fi ...

  10. [转帖]理解k8s 的 Ingress

    理解k8s 的 Ingress https://www.jianshu.com/p/189fab1845c5/ 暴露一个http服务的方式 service 是 k8s 暴露http服务的默认方式, 其 ...