本次通讯试用到硬件开发板STM32F103C8T6(数据发送),STM32F103C6T6(数据接收),CAN收发器VP230。硬件连接如下图所示:
由于我使用的开发板不自带CAN收发器,所以只有外接CAN收发器才能保证两个开发板的正常通讯。
数据发送端(STM32F103C8T6)代码部分
/********************can.c**********************/
#include "can.h"
u8 CAN_RX_BUF[8];
unsigned char CAN_RX_FLAG = 0;
void CAN_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitSturcture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//CAN_RX PB8
GPIO_InitSturcture.GPIO_Pin = CAN_RX_Pin;
GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
//CAN_TX PB9
GPIO_InitSturcture.GPIO_Pin =CAN_TX_Pin;
GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(CAN_GPIO_PORT,&GPIO_InitSturcture);
}
void CAN_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void CAN_Mode_Init(u32 tsjw,u32 tbs1,u32 tbs2,u16 brp,u32 mode)
{
CAN_InitTypeDef CAN_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE);
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
CAN_InitStructure.CAN_SJW = tsjw;
CAN_InitStructure.CAN_BS1 = tbs1;
CAN_InitStructure.CAN_BS2 = tbs2;
CAN_InitStructure.CAN_Mode = mode;
CAN_InitStructure.CAN_Prescaler = brp;
CAN_InitStructure.CAN_NART =ENABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_RFLM = ENABLE;
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_Init(CAN1,&CAN_InitStructure);
}
/********数据发送端可不配置过滤器,设置默认值即可***********/
void CAN_Filter_Init(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
CAN_FilterInit(&CAN_FilterInitStructure);
}
void Can_Init(void)
{
CAN_GPIO_Config();
CAN_NVIC_Config();
CAN_Mode_Init(CAN_SJW_1tq,CAN_BS1_3tq,CAN_BS2_2tq,12,CAN_Mode_Normal);
//CAN_Mode_Normal CAN_Mode_LoopBack
CAN_Filter_Init();
}
u8 CAN_Send_Msg(u8* msg,u8 len)
{
CanTxMsg TxMessage;
u8 i,mbox;
u16 cunt = 0;
//TxMessage.StdId = 0x0000;
TxMessage.ExtId = 0x1001; //设置发送扩展ID
TxMessage.IDE = CAN_ID_EXT;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.DLC = len;
for(i = 0;i < len;i ++)
{
TxMessage.Data[i] = msg[i];
}
mbox = CAN_Transmit(CAN1,&TxMessage);
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(cunt<0XFFF))
cunt++;
if(cunt >= 0xFFF)
return 0;
return 1;
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
uint8_t i;
if(CAN_GetITStatus(CAN1,CAN_IT_FMP0) != RESET)
{
CAN_RX_FLAG = 1;
CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);
for(i = 0;i < 8;i ++)
CAN_RX_BUF[i] = RxMessage.Data[i];
CAN_FIFORelease(CAN1,CAN_FIFO0);
CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
}
}
主函数部分
#include "main.h"
int main(void)
{
u8 send_buf[8] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
u8 i = 0x00;
NVIC_Configuration();
LED_Init();
Delay_Init();
Usart1_Init(9600);
Can_Init();
printf("这里是CAN的测试程序\r\n");
LED0 = 1;
while(1) //主循环
{
i++;
send_buf[0] = i;
CAN_Send_Msg(send_buf,8);
Delay_Ms(100);
LED0 = !LED0;
}
}
/分割线//
以下是CAN通讯数据接收端(STM32F103C6T6)代码:
接收端的中断、GPIO和CAN_Mode配置都跟发送设置的一样,直接复制粘贴即可。下面是配置接收端的过滤器,接收扩展ID为1001设备的数据。其他数据一律过滤不接收,当然如果想不过滤ID,接收端过滤器配置全部设置成更发送端一样即可。
void CAN_Filter_Init(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
//只接受ID为1001的设备
CAN_FilterInitStructure.CAN_FilterIdHigh = (((u32)0x1001<<3)&0xFFFF0000)>>16;
CAN_FilterInitStructure.CAN_FilterIdLow = (((u32)0x1001<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0xFFFF;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
CAN_FilterInit(&CAN_FilterInitStructure);
}
中断接收函数
void USB_LP_CAN1_RX0_IRQHandler(void)
{
CanRxMsg RxMessage;
uint8_t i;
if(CAN_GetITStatus(CAN1,CAN_IT_FMP0) != RESET)
{
CAN_RX_FLAG = 1;
CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);
for(i = 0;i < 8;i ++)
CAN_RX_BUF[i] = RxMessage.Data[i];
CAN_FIFORelease(CAN1,CAN_FIFO0);
CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
}
}
主函数部分
#include "main.h"
int main(void)
{
NVIC_Configuration();
LED_Init();
Delay_Init();
Usart1_Init(9600);
Can_Init();
printf("这里是CAN的测试程序\r\n");
LED0 = 1;
while(1) //主循环
{
if(CAN_RX_FLAG == 1)
{
CAN_RX_FLAG = 0;
USART1TxData_hex(CAN_RX_BUF,8);
}
Delay_Ms(100);
LED0 = !LED0;
}
}
通过串口调试助手打印出接收端接收到数据。