配置底层
1、按照之前讲的,根据硬件设计配置引脚
2、添加CAN模块。在模块库中将flexcan模块添加到【Components】中。
3、双击该模块配置相关属性
4、更改一下CAN的时钟,和module clock匹配
5、配置好了,按照之前讲的在【Project】选项卡中选择生成PE代码,这样CAN的底层就配置好了。
代码实现
1、回调函数。回调函数的定义要在初始化之前,不然初始化创建回调函数的时候找不到源
flexcan_msgbuff_t gCan0RxBuff[CAN0_RX_NUM]; //CAN0
uint8_t ucCan0Rxstate[CAN0_RX_NUM] = {0,0};
uint8_t ucCan0Txstate[CAN0_TX_NUM] = {0,0,0,0,0};
static void CAN0_CallBack(uint8_t instance, flexcan_event_type_t eventType, uint32_t buffIdx, struct FlexCANState *driverState)
{
if (eventType == FLEXCAN_EVENT_TX_COMPLETE)
{
if (buffIdx < CAN0_TX_NUM)
{
ucCan0Txstate[buffIdx] = 0;
}
}
else if (eventType == FLEXCAN_EVENT_RX_COMPLETE)
{
ucCan0Rxstate[buffIdx] = 1;
FLEXCAN_DRV_Receive(INST_CANCOM0, buffIdx, &gCan0RxBuff[buffIdx]);
}
}
2、初始化函数
void vCan0Init(void)
{
uint8_t i = 0;
flexcan_data_info_t stCanData;
stCanData.data_length = 0x08;
stCanData.is_remote = 0;
FLEXCAN_DRV_Init(INST_CANCOM0, &canCom0_State, &canCom0_InitConfig0); //初始化
FLEXCAN_DRV_InstallEventCallback(INST_CANCOM0, CAN0_CallBack, NULL);//创建回调函数
//can0接收初始化 每个通道接收固定的ID。
stCanData.msg_id_type = FLEXCAN_MSG_ID_STD; //ID为标准ID
FLEXCAN_DRV_ConfigRxMb(INST_CANCOM0, 0, &stCanData, 0x110); //设置接收通道0,接收ID为0x110的CAN信息
FLEXCAN_DRV_Receive(INST_CANCOM0, 0, &gCan0RxBuff[0]); //0通道的数据存在这里
ucCan0Rxstate[0] = 0; //非0为接收到数据
stCanData.msg_id_type = FLEXCAN_MSG_ID_STD; //ID为标准ID
FLEXCAN_DRV_ConfigRxMb(INST_CANCOM0, 1, &stCanData, 0x120); //设置接收通道1,接收ID为0x110的CAN信息
FLEXCAN_DRV_Receive(INST_CANCOM0, 1, &gCan0RxBuff[1]); //1通道的数据存在这里
ucCan0Rxstate[1] = 0; //非0为接收到数据
//发送初始化 发送的通道可以重复,只要不和接收通道重复就行
for (i = 0;i < CAN0_TX_NUM;i++)
{
ucCan0Txstate[i] = 0;
}
}
3、CAN线程处理函数
uint16_t usCnt=0;
void vCanHandle(void)
{
uint8_t ucTxData[8]={0};
uint8_t ucI=0;
static uint16_t ucIndex=2;
flexcan_data_info_t stTxDataInf;
stTxDataInf.data_length = 8;
stTxDataInf.is_remote = 0x00;
stTxDataInf.msg_id_type = FLEXCAN_MSG_ID_STD;
//接收报文 再回复 注意发送通道不可以和接收通道重复
if(ucCan0Rxstate[0] == 1) //ID 0x110
{
ucCan0Rxstate[0] = 0;
for(ucI=0; ucI<8; ucI++)
{
ucTxData[ucI] = ucI;
}
FLEXCAN_DRV_Send(INST_CANCOM0, 4, &stTxDataInf, 0x110, ucTxData);
ucCan0Txstate[0]=1;
}
if(ucCan0Rxstate[1] == 1) //ID 0x120
{
ucCan0Rxstate[1] = 0;
for(ucI=0; ucI<8; ucI++)
{
ucTxData[ucI] = ucI+0x10;
}
FLEXCAN_DRV_Send(INST_CANCOM0, 5, &stTxDataInf, 0x120, ucTxData);
ucCan0Txstate[1]=1;
}
//定时自动上传 发送报文的通道随便设置,只要不占用接收通道的就行
if(usCnt++ %150 ==0)
{
usCnt=0;
if(ucCan0Txstate[ucIndex] == 0)
{
for(ucI=0; ucI<8; ucI++)
{
ucTxData[ucI] = ucI+(0x10*ucIndex);
}
FLEXCAN_DRV_Send(INST_CANCOM0, ucIndex, &stTxDataInf, 0x120+ucIndex, ucTxData);
ucCan0Txstate[ucIndex]=1;
if(++ucIndex > 4)
{
ucIndex=2;
}
}
}
}
4、初始化和主函数
void vSysInit(void)
{
CLOCK_DRV_Init(g_clockManConfigsArr[0]); //初始化时钟
PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr); //初始化引脚
PINS_DRV_WritePin(PTF,0x08,1); //开电源模块
vADCInit();
vUartInit();
vCan0Init();
PIT_DRV_Init(INST_PIT, &pit_InitConfig); // PIT initialize, system tick
//通道0
PIT_DRV_ConfigChannel(INST_PIT, pit_ChnConfig0.hwChannel, pit_ChnConfig0.period, pit_ChnConfig0.periodUnit);
PIT_DRV_EnableChannelInterrupt(INST_PIT, pit_ChnConfig0.hwChannel);
PIT_DRV_StartChannel(INST_PIT, pit_ChnConfig0.hwChannel);
INT_SYS_EnableIRQ(PIT_Ch0_IRQn);
INT_SYS_SetPriority(PIT_Ch0_IRQn,1);
}
int main(void)
{
vSysInit();
while(1)
{
vRS485Handle();
AdcSampleTask();
vCanHandle();
}
}