首先是关于CubeMx的使用,他只是帮助你完善一些初始化的问题,也可以的让你去避开对于底层的触碰。
我是基于F103的,其实F4等等,大同小异。
我默认你会使用CubeMx,如果你不会可以看看这个博主的教程: http://t.csdn.cn/eKcbZ
讲的很细致,估计聪明的你几个小时就学会了。
这里我们配置的是使用外部时钟,我的外部时钟是8M的:
这里主要是为了后期你可以使用stlink, 或者别的工具去Debug:
下面我们可以配置一下时钟树:
我标记的位置都是很重要的,比如PCLK1是用于can通信的,所以计算波特率的时候可能会有影响。(倘若觉得后面的你在配置波特率的时候,觉得自己没问题,或许问题会出在时钟初始化,那么就要好好看看了。我碰到过,不赘述了)
现在配置一下can的参数:
我建议加上中断,因为我试了不加中断的can接收,没有成功。最后只能在中断里进行了。
我这里配置的是250K的波特率,倘若你要配置500K ,则是9,5,2;配置这个波特率首先要知道原理,这个自行百度,其次我的经验是就在这里实验,看看能不能用。软件中试触法完全可以。之后生成就可以了。我觉得我的步骤是不健全的,但是太全了你会不会没有思考的地方呢?我依旧认为你是个聪明的人。
初始化代码:
uint8_t CAN1_Mode_Init(u32 tsjw,u32 tbs2,u32 tbs1,u16 brp,u32 mode)
{
CAN_InitTypeDef CAN1_InitConf;
hcan.Instance=CAN1;
hcan.Init = CAN1_InitConf;
hcan.Init.Prescaler=brp; //分频系数(Fdiv)为brp+1
hcan.Init.Mode=mode; //模式设置
hcan.Init.SyncJumpWidth=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位
//CAN_SJW_1TQ~CAN_SJW_4TQ
hcan.Init.TimeSeg1=tbs1; //tbs1范围CAN_BS1_1TQ~CAN_BS1_16TQ
hcan.Init.TimeSeg2=tbs2; //tbs2范围CAN_BS2_1TQ~CAN_BS2_8TQ
hcan.Init.TimeTriggeredMode=DISABLE; //非时间触发通信模式
hcan.Init.AutoBusOff=DISABLE; //软件自动离线管理
hcan.Init.AutoWakeUp=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
hcan.Init.AutoRetransmission=ENABLE; //禁止报文自动传送
hcan.Init.ReceiveFifoLocked=DISABLE; //报文不锁定,新的覆盖旧的
hcan.Init.TransmitFifoPriority=DISABLE; //优先级由报文标识符决定
if(HAL_CAN_Init(&hcan)!=HAL_OK) //初始化
return 1;
return 0;
}
特别提醒,CubeMx是不帮你配置过滤器,邮箱的,这需要你自己亲历亲为:
void CAN_Config(void)
{
CAN_FilterTypeDef sFilterConfig;
/*配置CAN过滤器*/
sFilterConfig.FilterBank = 0; //过滤器0
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000; //32位ID
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000; //32位MASK
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;//过滤器0关联到FIFO0
sFilterConfig.FilterActivation = ENABLE; //激活滤波器0
sFilterConfig.SlaveStartFilterBank = 14;
if(HAL_CAN_ConfigFilter(&hcan,&sFilterConfig) != HAL_OK)//初始化过滤器
{
Error_Handler();
}
if(HAL_CAN_Start(&hcan) != HAL_OK)//打开can
{
Error_Handler();
}
if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)//开启接受邮箱
//0挂起中断
{
Error_Handler();
}
}
发送的函数:
void CAN_senddata(CAN_HandleTypeDef *hcan,uint32_t can_id)
{
TXHeader.StdId=can_id ;
TXHeader.ExtId=0x12345000;//0x12345000
TXHeader.DLC=8;
TXHeader.IDE=CAN_ID_EXT;
TXHeader.RTR=CAN_RTR_DATA;
TXHeader.TransmitGlobalTime = DISABLE;
if(KEY == 0)
HAL_CAN_AddTxMessage(hcan,&TXHeader,TXmessage,&pTxMailbox);//发送
else if(KEY == 1)
{
HAL_CAN_AddTxMessage(hcan,&TXHeader,RXmessage,&pTxMailbox);把接收的再次发送
KEY = 0;
}
}
接收函数(非中断版本),这个是我是失败的,如果你会你可以在评论中补充:
uint32_t CAN1_Receive_Msg(u8 *buf)
{
u32 i;
u8 RxData[8];
if(HAL_CAN_GetRxFifoFillLevel(&hcan, CAN_RX_FIFO0) != 1)//没有接收到数据,直接退出
{
return 0xF1;
}
if(HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &RXHeader, RxData) != HAL_OK)
{
return 0xF2;
}
for(i=0;i
中断版本的接收函数:
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance==CAN1)
{
KEY = 1;
HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&RXHeader,RXmessage);//获取数据
}
}
貌似就这些了。我主要碰到的问题是,配置波特率,接收不可以用在whlie中,只能用中断。
我已经将完整的代码上传,如果有需要可以下载,1个积分,不做伸手党。