您的位置:首页 > 其它

CAN总线

2018-09-02 11:03 148 查看

一、编程要点
1、初始化相关外设时钟及GPIO
2、CAN模式初始化
3、筛选器配置
4、配置接收中断和写中断服务函数
5、CAN收发函数
二、CAN基础知识
1、物理层
采用差分信号,理论上无节点限制
2、协议层
一个完整的数据位由 8~25 个 Tq 组成,高低电平直接代表信号逻辑 0(显性) 或逻辑 1(隐性)信号的采样点位于 PBS1 段与 PBS2 段之间,通过控制各段的长度,可以对采样点的位置进行偏移,以便准确地采样

3、CAN的报文及结构

4、STM32 CAN外设
1. 四种工作模式(正常、静默、回环、静默回环)
2. 波特率设置方法

3. 发送及接收邮箱
3个发送邮箱,2个接收一共6个接收邮箱
4. 验收筛选器
4种工作模式

工作在掩码模式时

三、结构体&库函数
1、CAN初始化结构体

typedef struct
{
uint16_t CAN_Prescaler;   /*!<CAN时钟预分频 1M为4  */

uint8_t CAN_Mode;         /*!< 四种工作模式 */

uint8_t CAN_SJW;          /*!< SWJ的极限值 用于再同步 */

uint8_t CAN_BS1;          /*!< 见上图 */

uint8_t CAN_BS2;          /*!< */

FunctionalState CAN_TTCM; /*!< 是否使能时间触发功能 */

FunctionalState CAN_ABOM;  /*!< 自动离线 */

FunctionalState CAN_AWUM;  /*!< 自动唤醒 */

FunctionalState CAN_NART;  /*!< 自动重传*/

FunctionalState CAN_RFLM;  /*!< 是否使能锁定FIFO 不使能按先后顺序 */

FunctionalState CAN_TXFP;  /*!< 报文优先级判定enable(先后顺序)disable(ID优先级) */
} CAN_InitTypeDef;

2、过滤器结构体

typedef struct
{
uint16_t CAN_FilterIdHigh;         /*!< CAN_FxR1 */

uint16_t CAN_FilterIdLow;          /*!< CAN_FxR1 */

uint16_t CAN_FilterMaskIdHigh;     /*!< CAN_FxR1 */

uint16_t CAN_FilterMaskIdLow;      /*!< CAN_FxR1 见上图 */

uint16_t CAN_FilterFIFOAssignment; /*!< 选择报文储存在哪个FOFI */

uint8_t CAN_FilterNumber;          /*!< 筛选器编号 0—13 */

uint8_t CAN_FilterMode;            /*!< CAN筛选器工作模式 */

uint8_t CAN_FilterScale;           /*!< 配置筛选器尺度 16/32位 */

FunctionalState CAN_FilterActivation; /*!< 是否使能该筛选器 */
} CAN_FilterInitTypeDef;

3、中断配置及服务函数

void NVIC_Configuration(void)                   //配置中断向量控制器
{
NVIC_InitTypeDef NVIC_InitStructure;                    //

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);         //选择中断控制器组
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;      //选择中断源
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;              //使能中段
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;           //子优先级
NVIC_Init(&NVIC_InitStructure);                 //初始化结构体将值写入

}

void USB_LP_CAN1_RX0_IRQHandler(void)
{
CAN_Receive(CAN1,CAN_FIFO0, &CanRxData);
flag=1;
}

4、接收发送结构体

typedef struct
{
uint32_t StdId;  /*!< 标准ID 0 to 0x7FF. */

uint32_t ExtId;  /*!< 扩展ID 0 to 0x1FFFFFFF. */

uint8_t IDE;     /*!< 扩展标志 标准CAN_Id_Standard  扩展CAN_Id_Extended */

uint8_t RTR;     /*!< 远程帧标志 数据CAN_RTR_Data  远程CAN_RTR_Remote */

uint8_t DLC;     /*!< 报文数据帧长度   0 to 8 */

uint8_t Data[8]; /*!< 报文数据内容 */

uint8_t FMI; /*接收特有 存储了 本报文是由经过筛选器存储进 FIFO 的, 0-0xFF */
26 } CanRxMsg;

5、数据发送及接收函数
uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)

box = CAN_Transmit(CAN1,&CanTxData)

@brief :CAN数据发送
@param1:CAN号
@param2:要发送的数据地址 &CanTxData
@retval:发送邮箱号
CAN_Receive(CAN1,CAN_FIFO0, &CanRxData);

@brief :CAN数据接收
@param1:CAN号
@param2:接收FIFO号
@param3:接收的数据储存地址

6、消息传输状态检查函数

uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox)
while(CAN_TransmitStatus(CAN1,box) == CAN_TxStatus_Failed);

@brief :传输状态检查
@param1:CAN号
@param2:发送邮箱号
@retval:发送结果

四、其他注意事项
1、CAN引脚模式
TX GPIO_Mode_AF_PP
RX GPIO_Mode_IPU/GPIO_Mode_IN_FLOATING
2、引脚复用功能开启
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE)
五、程序源码
1、bsp_can.h

#ifndef __bsp_can_H
#define __bsp_can_H

#include "stm32f10x.h"

#define CAN_CLK                             RCC_APB1Periph_CAN1

#define CAN_RX_GPIO_CLK         (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)
#define CAN_RX_GPIO_PORT                    GPIOB
#define CAN_RX_GPIO_PIN                     GPIO_Pin_8

#define CAN_TX_GPIO_CLK                     RCC_APB2Periph_GPIOB
#define CAN_TX_GPIO_PORT                    GPIOB
#define CAN_TX_GPIO_PIN                     GPIO_Pin_9

#define PASS_ID             ((uint32_t)0X1314)

void CAN_config(void);

#endif      //__bsp_can_H

2、bsp_can.c

#include "bsp_can.h"

extern CanTxMsg CanTxData;
extern CanRxMsg CanRxData;

void CAN_GPIO_config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(CAN_RX_GPIO_CLK,ENABLE);
RCC_APB2PeriphClockCmd(CAN_TX_GPIO_CLK,ENABLE);         //相关时钟

GPIO_InitStructure.GPIO_Pin = CAN_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;           //上拉输入/浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = CAN_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CAN_TX_GPIO_PORT, &GPIO_InitStructure);

}

void CAN_Init_config(void)
{
CAN_InitTypeDef CAN_InitStructure;
RCC_APB1PeriphClockCmd (RCC_APB1Periph_CAN1 , ENABLE );         //can时钟

CAN_InitStructure.CAN_Prescaler = 4;                //can时钟分频
CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;     //工作模式

CAN_InitStructure.CAN_BS1 = CAN_BS1_5tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;
CAN_InitStructure.CAN_SJW   = CAN_SJW_2tq;

CAN_InitStructure.CAN_TTCM = DISABLE;               //时间触发
CAN_InitStructure.CAN_ABOM = ENABLE;                //自动离线
CAN_InitStructure.CAN_AWUM = ENABLE;                //自动唤醒
CAN_InitStructure.CAN_NART = ENABLE;                //自动重传
CAN_InitStructure.CAN_TXFP = DISABLE;               //报文优先级判定enable(先后顺序)disable(ID优先级)
CAN_InitStructure.CAN_RFLM = ENABLE;                //是否使能锁定FIFO 不使能按先后顺序
CAN_Init(CAN1,&CAN_InitStructure);

}

void CAN_CAN_FilterInit(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;

CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;          //筛选器模式
CAN_FilterInitStructure.CAN_FilterNumber = 0;           //筛选器组号 0-13
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;        //存储FIFO
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;                //配置筛选器尺度 16/32位
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;                                  //使能该筛选器

CAN_FilterInitStructure.CAN_FilterIdHigh = ((PASS_ID<<3 |CAN_Id_Extended |CAN_RTR_Data)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = ((PASS_ID<<3 |CAN_Id_Extended |CAN_RTR_Data)&0xFFFF);
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0XFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0XFFFF;
CAN_FilterInit(&CAN_FilterInitStructure);

CAN_ITConfig (CAN1,CAN_IT_FMP0,ENABLE);         //使能CAN接收中断

}

void NVIC_Configuration(void)                   //配置中断向量控制器
{
NVIC_InitTypeDef NVIC_InitStructure;                                //

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);             //选择中断控制器组
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;      //选择中断源
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;              //使能中段
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;    //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;           //子优先级
NVIC_Init(&NVIC_InitStructure);                     //初始化结构体将值写入

}

void CAN_config(void)
{
CAN_GPIO_config();      //GPIO配置
CAN_Init_config();      //初始化结构体
CAN_CAN_FilterInit();   //筛选器配置
NVIC_Configuration();   //中断
}

3.main.c

#include "stm32f10x.h"   // 相当于51单片机中的  #include <reg51.h>
#include "bsp_led.h"
#include "usart.h"
#include "bsp_can.h"
#include "bsp_key.h"

#define GPIOB_ODR_Addr      (GPIOB_BASE+0X0C)
#define PBout(n)   *(unsigned int *)((GPIOB_ODR_Addr & 0xF0000000)+0x02000000+((GPIOB_ODR_Addr&0x00FFFFFF)<<5)+(n<<2))

extern CanTxMsg CanTxData;
extern CanRxMsg CanRxData;
extern u8 flag;

void delay(uint32_t i)
{
while(i--);
}

int main(void)
{
uint8_t box=5;
flag=0;

LED_GPIO_Config();
KEY_GPIO_Config();
USART_config();
CAN_config();

PBout(0)=1;
printf("\r\n 串口初始化完成\r\n");
while(1)
{

if(key_san(GPIOA, GPIO_Pin_0))
{

CanTxData.StdId = 0;                    //标准ID
CanTxData.ExtId = PASS_ID;              //扩展ID
CanTxData.IDE = CAN_Id_Extended;    //扩展标志 标准CAN_Id_Standard  扩展CAN_Id_Extended
CanTxData.DLC = 1;                  //数据位长度
CanTxData.Data[0] = 10;             //数据内容
CanTxData.RTR = CAN_RTR_Data;   //远程帧标志 数据CAN_RTR_Data  远程CAN_RTR_Remote
box = CAN_Transmit(CAN1,&CanTxData);

while(CAN_TransmitStatus(CAN1,box) == CAN_TxStatus_Failed);
//检测报文是否发送完成
//printf("\r\n 发送结果:%d\r\n",CAN_TransmitStatus(CAN1,box));

printf("\r\n 数据包发送完成\r\n");
PBout(0)=0;

}
if(flag==1)
{
printf("\r\n接收到的数据:%d\r\n",CanRxData.Data[0]);
flag = 0;
}
}
}
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: