使用型号:F407VET6、F103C8T6
注意:这里F407使用的是CAN1,使用CAN2的话,也要开启CAN1的外设时钟,因为它们共用筛选器,且由于存储访问控制器由CAN1控制,所以要使用CAN2的时候 必须要使能CAN1的时钟
显示数据:F407使用的是串口来显示数据。F103的话是使用0.96寸OLED来显示数据
波特率:F4和F1波特率都是500KHZ。
1、f407的CAN初始化和FIFO0接收中断函数
CanTxMsg txMsg; //发送 数据帧 结构体
CanRxMsg rxMsg; //接收 数据帧 结构体
void Mycan_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
NVIC_InitTypeDef NVIC_InitStrcture;
/* 开启CAN1和GPIOA外设的时钟 */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* PA11和PA12复用为CAN1引脚 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1);
/* GPIO初始化 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* CAN外设初始化 */
CAN_InitStructure.CAN_ABOM = ENABLE; /* 是否使能ABOM自动离线管理功能 */
CAN_InitStructure.CAN_TXFP = DISABLE; /* 配置TXFP报文优先级的判定方法 */
CAN_InitStructure.CAN_AWUM = ENABLE; /* 是否使能AWUM自动唤醒功能 */
CAN_InitStructure.CAN_NART = ENABLE; /* 是否使用NART自动重传功能 */
CAN_InitStructure.CAN_RFLM = DISABLE; /* 是否使能RELM锁定FIFO功能 */
CAN_InitStructure.CAN_TTCM = DISABLE; /* 是否使能TTCM时间触发功能 */
CAN_InitStructure.CAN_SJW = CAN_SJW_2tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq; // 42MHZ/(ss+b1+bs2)/psc = 42000000/(1+8+5)/6 = 500khz
CAN_InitStructure.CAN_BS2 = CAN_BS1_5tq;
CAN_InitStructure.CAN_Prescaler = 6;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_Init(CAN1, &CAN_InitStructure);
/* CAN过滤器初始化 */
CAN_FilterInitStructure.CAN_FilterNumber = 1; /* 过滤器编号 */
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; /* 使能过滤器 */
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; /* 掩码模式还是列表模式 */
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; /* 使用哪个FIFO去接收数据 */
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; /* 过滤器的尺度16位还是32位*/
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; //不过滤ID
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInit(&CAN_FilterInitStructure);
/* CAN1 FIFO1 接收中断 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStrcture.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStrcture.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStrcture.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStrcture.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStrcture);
/* 使用FIFO0接收, 开启FIFO0接收中断 */
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}
extern uint8_t can_Rx0_bit; //CAN1的FIFO0接收中断标志位
void CAN1_RX0_IRQHandler(void)
{
if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) == SET)
{
can_Rx0_bit = 1;
CAN_Receive(CAN1, CAN_FIFO0, &rxMsg);
//不需要手动清除中断标志位,CAN_Receive()时会硬件清除
}
}
2、f407的main.c
uint8_t can_Rx0_bit = 0; //CAN1的FIFO0接收中断标志位
#define CAN_ID 0x03FF
int main(void)
{
delay_init(168);
led_Init();
key_Init();
MyUsart1_Init(115200);
Mycan_Config();
MyUsart1_SendString("------------这是一个CAN回环测试-----------\r\n");
uint8_t keynum = 0;
uint8_t value = 0, mailbox;
while(1)
{
keynum = Key_GetNum();
if(keynum == key0)
{
for(uint8_t i = 0; i < 8; i++)
{
txMsg.Data[i] = value;
value += 1;
}
txMsg.StdId = CAN_ID ; /* 标准ID */
txMsg.ExtId = 0x0000; /* 拓展ID */
txMsg.IDE = CAN_Id_Standard; /* 是否为拓展ID */
txMsg.RTR = CAN_RTR_Data; /* 数据帧还是遥控帧 */
txMsg.DLC = 8; /* 数据长度 */
MyUsart1_SendString("准备发送数据\r\n");
mailbox = CAN_Transmit(CAN1, &txMsg); //返回发送的数据存入邮箱的编号
if(mailbox != CAN_TxStatus_NoMailBox)
{
//等待直至发送成功
while(CAN_TransmitStatus(CAN1, mailbox) != CAN_TxStatus_Ok);
//给一定时间等待can收发器把数据发送到总线上
delay_ms(2);
MyUsart1_SendString("成功发送数据\r\n");
}
else
{
MyUsart1_SendString("没有空邮箱\r\n");
}
}
if(can_Rx0_bit == 1)
{
printf("接收到的数据为:\r\n");
printf("StdId:0x%x\r\n",rxMsg.StdId);
printf("ExtId:0x%x\r\n",rxMsg.ExtId);
printf("IDE:0x%x\r\n",rxMsg.IDE);
printf("RTR:0x%x\r\n",rxMsg.RTR);
printf("FMI:%d\r\n",rxMsg.FMI);
printf("DLC:%d\r\n",rxMsg.DLC);
printf("Data:");
for(uint8_t i = 0; i < 8; i++)
{
printf("0x%02x ",rxMsg.Data[i]);
}
printf("\r\n");
can_Rx0_bit = 0;
}
}
}
3、f103的CAN初始化和FIFO0接收中断函数
void CAN1_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
//can_rx PA11
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//推缓输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//can_tx PA12
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//推缓输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
CAN_InitTypeDef CAN_InitStructure;
CAN_InitStructure.CAN_ABOM = DISABLE; /* 是否使能ABOM自动离线管理功能 */
CAN_InitStructure.CAN_TXFP = DISABLE; /* 配置TXFP报文优先级的判定方法 */
CAN_InitStructure.CAN_AWUM = DISABLE; /* 是否使能AWUM自动唤醒功能 */
CAN_InitStructure.CAN_NART = DISABLE; /* 是否使用NART自动重传功能 */
CAN_InitStructure.CAN_RFLM = DISABLE; /* 是否使能RELM锁定FIFO功能 */
CAN_InitStructure.CAN_TTCM = DISABLE; /* 是否使能TTCM时间触发功能 */
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq ; /* 配置SJW(再同步补偿宽度)极限值 */
CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq; /* 配置BS1段长度 */
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq; /* 配置BS2段长度 */
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; /* 配置CAN的工作模式,回环或正常模式 */
CAN_InitStructure.CAN_Prescaler = 4; /* 配置CAN外设的时钟分频,可以设置为1-1024 */
CAN_Init(CAN1, &CAN_InitStructure); //36000000/(1+9+8)/4 = 500KHZ
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x00ff<<5; /* CAN_FxR1寄存器的高16位 */
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000; /* CAN_FxR1寄存器的低16位 */
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x00ff << 5; /* CAN_FxR2寄存器的高16位 */
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000; /* CAN_FxR2寄存器的低16位 */
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; /* 筛选器模式 */
CAN_FilterInitStructure.CAN_FilterNumber = 1; /* 筛选器编号 */
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; /* 设置筛选器的尺度 16位还是32位 */
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; /* 是否使能本筛选器 */
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;/* 设置经过筛选后数据存储到哪个接收FIFO */
CAN_FilterInit(&CAN_FilterInitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStrcture;
NVIC_InitStrcture.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStrcture.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStrcture.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStrcture.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStrcture);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) == SET)
{
CanRxMsg RxMsg;
RxMsg.Data[0] = 0;
RxMsg.Data[1] = 0;
RxMsg.DLC = 0;
RxMsg.ExtId = 0;
RxMsg.FMI = 0;
RxMsg.IDE = 0;
RxMsg.RTR = 0;
RxMsg.StdId = 0;
CAN_Receive(CAN1, CAN_FIFO0, &RxMsg);
OLED_ShowString(2,1,"RxID:");
OLED_ShowHexNum(2,6, RxMsg.StdId, 4);
OLED_ShowNum(3,1,RxMsg.Data[0], 4);
OLED_ShowNum(3,6,RxMsg.Data[1], 4);
CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
}
}
4、f103的main.c
#define CAN_ID1 0x01FF
int main(void)
{
//按键初始化
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//推缓输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推缓输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
OLED_Init();
CAN1_Config();
uint8_t data1 = 1, data2 = 102;
OLED_ShowString(1,1,"This_ID:");
OLED_ShowHexNum(1,9, CAN_ID1,4);
while(1)
{
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0)
{
Delay_ms(10);
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0){};
data1 += 2;
data2 += 2;
CAN_Send_2Byte(data1, data2, CAN_ID1); //这个函数在下面
}
}
}
void CAN_Send_2Byte(uint8_t data1, uint8_t data2, uint32_t CAN_id)
{
CanTxMsg TxMsg;
//测试 只发了两个数据
TxMsg.Data[0] = data1;
TxMsg.Data[1] = data2;
TxMsg.DLC = 2;
TxMsg.ExtId = 0x0000;
TxMsg.IDE = CAN_Id_Standard;
TxMsg.RTR = CAN_RTR_Data; //数据帧
TxMsg.StdId = CAN_id;
uint8_t mbox = CAN_Transmit(CAN1, &TxMsg);
}
5、实验效果
f4发f1收 效果如下(数据随便发的)
f407发f103收CAN
f1发f4收 效果如下(数据随便发的)
f103发f407收CAN
以上代码本人试过可以正常使用
(有什么不对,请指正,谢谢)

2万+

被折叠的 条评论
为什么被折叠?



