CAN.C
#include "stm32f0xx.h"
#include "stm32f0xx_can.h"
#include "can.h"
void can_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
//初始化GPIO PB8(CANRX) PB9(CANTX)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_4);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_4);
//配置GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;//RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//中断优先级
NVIC_InitStructure.NVIC_IRQChannel = CEC_CAN_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//初始化CAN:设置波特率1Mbps
CAN_DeInit(CAN);
CAN_StructInit(&CAN_InitStructure);
/*< 时间触发通信模式 DISABLE:禁止时间触发通信模式 ENABLE:使能时间触发通信模式*/
CAN_InitStructure.CAN_TTCM = DISABLE;
/*< 自动的总线关闭管理 此位控制 CAN 硬件在退出总线关闭状态时的行为
DISABLE: 在软件发出请求后,一旦监测到 128 次连续 11 个隐性位,
并且软件将 CAN_MCR 寄存器的 INRQ 位先置 1 再清零,即退出总线关闭状态
ENABLE: 一旦监测到 128 次连续 11 个隐性位,即通过硬件自动退出总线关闭状态 */
CAN_InitStructure.CAN_ABOM = ENABLE;
/*< 自动唤醒模式 此位控制 CAN 硬件在睡眠模式下接收到消息时的行为
DISABLE: 在软件通过将 CAN_MCR 寄存器的 SLEEP 位清零发出请求后,退出睡眠模式
ENABLE: 一旦监测到 CAN 消息,即通过硬件自动退出睡眠模式 */
CAN_InitStructure.CAN_AWUM = ENABLE;
/*< 自动重发送
DISABLE: 无论发送结果如何(成功、错误或仲裁丢失),消息均只发送一次
ENABLE: CAN 硬件将自动重发送消息,直到根据 CAN 标准消息发送成功 */
CAN_InitStructure.CAN_NART = ENABLE;//DISABLE;
/*< 接收 FIFO 锁定模式
DISABLE: 接收 FIFO 上溢后不锁定。接收 FIFO 装满后,下一条传入消息将覆盖前一条消息
ENABLE: 接收 FIFO 上溢后锁定。接收 FIFO 装满后,下一条传入消息将被丢弃*/
CAN_InitStructure.CAN_RFLM = DISABLE;
/*< 发送 FIFO 优先级
DISABLE: 优先级由消息标识符确定
ENABLE: 优先级由请求顺序(时间顺序)确定*/
CAN_InitStructure.CAN_TXFP = DISABLE;
/*< CAN工作模式 CAN_Mode_Normal:正常模式 CAN_Mode_LoopBack:回环模式
CAN_Mode_Silent:静默模式 CAN_Mode_Silent_LoopBack:静默回环模式*/
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
//APB1时钟48M,预分频16,CAN时钟3M,500K
CAN_InitStructure.CAN_Prescaler = 16;//设置CAN波特率分频系数
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//重新同步跳跃宽度
CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;//时间段1占用时间单元
CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;//时间段2占用时间单元
CAN_Init(CAN, &CAN_InitStructure);
//使用筛选器组0,32位掩码模式,即可过滤一个ID
//ID号存放在CAN_F0R1中,即CAN_FilterIdHigh和CAN_FilterIdLow分别存高低16位
//掩码存放在CAN_F0R2中,即CAN_FilterMaskIdHigh和CAN_FilterMaskIdLow分别存高低16位
//掩码全都为0时,则表明不过滤任何ID,接收总线上的所有报文
//初始化筛选器
CAN_FilterInitStructure.CAN_FilterNumber = 0;//过滤器0
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//32位宽
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;//屏蔽位(掩码)模式
//32位掩码标准ID模式:筛选器只筛选接收标准ID为0x1的报文
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x000 << 5;//(((uint32_t)0X01<<21|CAN_Id_Standard|CAN_RTR_Data)&0xFFFF0000)>>16;//筛选ID
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;//((uint32_t)0X01<<21|CAN_Id_Standard|CAN_RTR_Data)&0x0000FFFF;//筛选ID
//(想要发送远程帧 修改对应掩码位为0)
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;//掩码
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;//掩码
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//选中过滤器FIFO0
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;//激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);
//在CAN_FilterInit函数体中:
/*在初始化之前,会设置 CAN_FMR 寄存器的 INRQ 为 INIT 让其进入初始化模式,
然后初始化 CAN 滤波器相关的寄存器之后,会设置 CAN_FMR 寄存器的 FINIT 为 0 让其退出
初始化模式。*/
/* CAN FIFO0 接收中断使能 */
CAN_ITConfig(CAN, CAN_IT_FMP0, ENABLE);
CAN_ClearFlag(CAN,CAN_FLAG_RQCP0);
}
void CAN_SendData(uint8_t* data,uint8_t length)
{
uint8_t mailbox;
uint16_t i=0;
CanTxMsg tx_msg;
tx_msg.StdId=0x12; // 标准标识符
tx_msg.ExtId=0x12; // 设置扩展标识符
tx_msg.IDE=CAN_Id_Extended; // 扩展帧
tx_msg.RTR=CAN_RTR_Data; // 数据帧
tx_msg.DLC = length;
for(i=0;i<length;i++)
{
tx_msg.Data[i] = data[i];
}
//CAN_Transmit(CAN1, &tx_msg);
mailbox = CAN_Transmit(CAN,&tx_msg);
i=0;
while (CAN_TransmitStatus(CAN, mailbox) ==CAN_TxStatus_Failed && (i < 0xFFF));
// while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF)); //等待发送结束
// while( ( CAN_TransmitStatus( CAN1, mbox ) != CAN_TxStatus_Ok ) && (i < 0xFFF) )
}
uint8_t buf1[8];
void CAN1_Receive(void)
{
CanRxMsg can_rx_msg;
// 检查是否有CAN消息接收
if (CAN_MessagePending(CAN,CAN_FIFO0) > 0)
{
// 接收CAN消息
CAN_Receive(CAN,CAN_FIFO0,&can_rx_msg);
/* 处理接收到的CAN消息 */
for(int i=0;i<can_rx_msg.DLC;i++)
{
buf1[i]=can_rx_msg.Data[i];
}
// CAN_SendData(buf1,8);//发送CAN接收到的数据
// can_rx_msg.DLC=0;
}
}
CAN.h
#ifndef __CAN_H_
#define __CAN_H_
#include "stm32f0xx.h"
#define CAN_RX0_INT_ENABLE 0 //不使用中断
void can_init(void);
void CAN_SendData(uint8_t* data, uint8_t length);
void CAN1_Receive(void);
void CAN_SendMessage(uint8_t data);
#endif