本程序调试完毕,并且制作了PCB电路板,程序运行正常。
以下是有关CAN通讯部分的源程序设置:
#include "can.h"
extern CanTxMsg TxMessage;
void CAN_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; //CAN1 RX0中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void CAN_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*外设时钟设置*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化IO
}
void CAN_Mode_Config(void)
{
CAN_InitTypeDef CAN_InitStructure;
/************************CAN1通讯参数设置**********************************/
/*CAN寄存器初始化*/
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
/*CAN单元初始化*/
CAN_InitStructure.CAN_TTCM=DISABLE; //MCR-TTCM 关闭时间触发通讯模式
CAN_InitStructure.CAN_ABOM=ENABLE; //MCR-ABOM 自动离线管理
CAN_InitStructure.CAN_AWUM=ENABLE; //MCR-AWUM 使用自动唤醒模式
CAN_InitStructure.CAN_NART=DISABLE; //MCR-NART 非自动报文重传模式,DISABLE表示报文重传?
CAN_InitStructure.CAN_RFLM=DISABLE; //MCR-RFLM 接收FIFO锁定模式, DISABLE-溢出时新的报文覆盖原来的报文
CAN_InitStructure.CAN_TXFP=DISABLE; //MCR-TXFP 使能FIFO发送优先级 DISABLE-发送时,优先级取决于报文的标识符
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; //正常工作模式
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //BTR-SJW 同步跳跃1个时间单元
CAN_InitStructure.CAN_BS1=CAN_BS1_6tq; //BTR-TS1 时间段1 占用6个时间单元
CAN_InitStructure.CAN_BS2=CAN_BS2_1tq; //BTR-TS1 时间段2 占用1个时间单元
CAN_InitStructure.CAN_Prescaler =225; ////BTR-BRP 波特率分频器,定义了时间单元的长度 36M/(1+6+1)/225=20 Kbps
CAN_Init(CAN1, &CAN_InitStructure);
}
void CAN_Filter_Config(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/*CAN滤波器初始化*/
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器组0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //标识符屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //过滤器位宽是:单个32位
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //需要过滤的ID高位
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; //需要过滤的ID低位,标准帧,数据帧
CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0x0000; //需要过滤的ID高位不必须匹配
CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0x0000; //需要过滤的ID低位,必须匹配是:标准帧,数据帧
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ; //过滤器和FIFO0配套使用
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //使能过滤器
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); //FIFO0的消息挂号中断使能
}
void Can_Send_Msg(u16 Sff_Id,u8* msg,u8 len)
{
u16 send_i=0;
TxMessage.StdId=Sff_Id; // 标准标识符为Sff_Id,标准标识符是11位的,设置范围在0~0X7FF
TxMessage.ExtId=0x12; // 设置扩展标示符,后面使用标准标识符发送,这里只是设置,实际没有用到?
TxMessage.IDE=CAN_ID_STD; // 使用标准标识符
TxMessage.RTR=CAN_RTR_DATA; // 消息类型为数据帧
TxMessage.DLC=len; // 发送两帧信息
for(send_i=0;send_i<len;send_i++)
{TxMessage.Data[send_i]=msg[send_i];} // 第一帧信息
CAN_Transmit(CAN1, &TxMessage);
GPIO_WriteBit(GPIOA,GPIO_Pin_6, (BitAction)(1-(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_6))));
}
以下是中断部分设置:
// can1中断服务函数USB_LP_CAN1_RX0_IRQHandler
void USB_LP_CAN1_RX0_IRQHandler(void)
{
can1_Receive_flag=0xff; //接收中断标志位置位
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
}
主程序部分就不列出了,因为每个工程师编写程序的功能差异很大。
可以技术交流,qq:531706356;13106551527
|