N32G430芯片CAN通信中断接收驱动程序,CAN引脚PA11,PA12,PA8是CAN芯片SIT1044T/3引脚STB控制,其他CAN芯片若不需要可以不用,另外CAN数据处理是WS2812灯带控制,实际应用移植时可以直接屏蔽,加入自己的控制程序,代码前面是头文件部分,后面是应用代码(已实测)。
#ifndef __CAN_H__
#define __CAN_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#define CAN_FILTER_STDID(STDID) ((STDID&0x7FF)<<5)
#define CAN_STD_ID_H_MASK_DONT_CARE 0x0000
#define CAN_STD_ID_L_MASK_DONT_CARE 0x0000
enum CMD__ //CAN通信命令字
{
CMD_POSITON = 0X01, //查询灯板位置信息
CMD_ALARM, //报警
CMD_RGB_LED_ALL = 0X80, //打开所有RGB LED.
CMD_SET_RGB_LED, //设置单个RGB LED 工作
CMD_SET_PARM, //设置灯板参数
CMD_INQUIRE_PARM, //查询灯板参数
CMD_SET_LUMINANCE, //设置灯板参亮度
CMD_RESET, //重启单个灯板灯板ID为0是重启所有灯板,1-255时重启单个灯板
CMD_TEST = 0XFF, //测试
CMD_REV //:备用
};
struct CAN1__DATA_
{
CanRxMessage RxMsg;
CanTxMessage TxMsg;
u8 rxOk;//接收状态标记
u8 ack;
u16 rxLen;
u8 rxDebug;
u8 txDebug;
u8 debug;
};
#define CAN_EN(n) (n?GPIO_Pins_Reset(GPIOA, GPIO_PIN_8):GPIO_Pins_Set(GPIOA, GPIO_PIN_8))
extern struct CAN1__DATA_ Can1; //can数据处理结构体
void can1Init(void); //can1 初始化
void can1DataDeal(void); //can 通信数据处理
#ifdef __cplusplus
}
#endif
#endif
#include "can.h"
struct CAN1__DATA_ Can1; //can数据处理结构体
void can1Init(void) //can1 初始化
{
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_CAN);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
GPIO_InitType GPIO_InitStructure;
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_8; //CAN_CE
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Current = GPIO_DS_4MA;
GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_11; //CAN RX
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_CAN;
GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_12; // CAN TX
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_CAN;
GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
CAN_Reset(CAN);
CAN_InitType CAN_InitStructure;
CAN_Structure_Initializes(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.TTCM = DISABLE;
CAN_InitStructure.ABOM = ENABLE;
CAN_InitStructure.AWKUM = ENABLE;
CAN_InitStructure.NART = DISABLE;
CAN_InitStructure.RFLM = DISABLE;
CAN_InitStructure.TXFP = ENABLE;
CAN_InitStructure.OperatingMode = CAN_NORMAL_MODE;
//Baud rate calculation = CAN clock/(BaudRatePrescaler*(TBS1+TBS2+1)) RCC_APB1_PERIPH_CAN = 18Mhz can波特率=18/1(1+9+2)=0.5Mhz=500Khz
CAN_InitStructure.RSJW = CAN_RSJW_1TQ;
CAN_InitStructure.TBS1 = CAN_TBS1_9TQ;
CAN_InitStructure.TBS2 = CAN_TBS2_2TQ;
CAN_InitStructure.BaudRatePrescaler = 3;
/*Initializes the CAN */
CAN_Initializes(CAN, &CAN_InitStructure);
// CAN_NVIC_Config();
NVIC_InitType NVIC_InitStructure; //CAN中断设置。
NVIC_Priority_Group_Set(NVIC_PER1_SUB3_PRIORITYGROUP);
NVIC_InitStructure.NVIC_IRQChannel=CAN_RX0_IRQn; //开这个中断对应FIFO1
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
CAN_FilterInitType CAN_FilterInitStructure;
CAN_FilterInitStructure.Filter_Num = 2;
CAN_FilterInitStructure.Filter_Mode = CAN_FILTER_IDLISTMODE;
CAN_FilterInitStructure.Filter_Scale = CAN_FILTER_16BITSCALE;
CAN_FilterInitStructure.Filter_HighId = CAN_FILTER_STDID(Parm.id);
CAN_FilterInitStructure.Filter_LowId = CAN_FILTER_STDID(Parm.id);
CAN_FilterInitStructure.FilterMask_HighId = CAN_STD_ID_H_MASK_DONT_CARE;
CAN_FilterInitStructure.FilterMask_LowId = CAN_STD_ID_L_MASK_DONT_CARE;
CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0; // CAN_FIFO0不行,原因未知。
CAN_FilterInitStructure.Filter_Act = ENABLE;
CAN_Filter_Initializes(&CAN_FilterInitStructure);
/* IT Configuration for CAN */
CAN_Config_Interrupt_Enable(CAN, CAN_INT_FMP0);
CAN_EN(true);
// LED_GPIO_init(); //C13 LED工作灯控制。
Can1.rxDebug = true;
// Can1.rxDebug = false;
}
void CAN_RX0_IRQHandler(void)
{
CanRxMessage RxMsg; //CAN 接收缓存.
CAN_Message_Receive(CAN,CAN_FIFO0, &RxMsg);
// CAN_ReleaseFIFO(CAN,CAN_FIFO1);
Can1.RxMsg.StdId = RxMsg.StdId;
// if ((RxMsg.StdId ==Parm.id)||(RxMsg.StdId ==0x0000))
{
Can1.RxMsg.StdId = RxMsg.StdId;
Can1.RxMsg.ExtId = RxMsg.ExtId;
Can1.RxMsg.IDE = RxMsg.IDE;
Can1.RxMsg.RTR = RxMsg.RTR;
Can1.RxMsg.DLC = RxMsg.DLC;
Can1.RxMsg.Data[0] = RxMsg.Data[0];
Can1.RxMsg.Data[1] = RxMsg.Data[1];
Can1.RxMsg.Data[2] = RxMsg.Data[2];
Can1.RxMsg.Data[3] = RxMsg.Data[3];
Can1.RxMsg.Data[4] = RxMsg.Data[4];
Can1.RxMsg.Data[5] = RxMsg.Data[5];
Can1.RxMsg.Data[6] = RxMsg.Data[6];
Can1.RxMsg.Data[7] = RxMsg.Data[7];
Can1.RxMsg.FMI = RxMsg.FMI;
Can1.rxOk = true;
}
}
void can1DataDeal(void) //can 通信数据处理
{
if (Can1.rxOk == true)
{
Can1.rxOk = false;
if(Can1.rxDebug)printf("CAN RX:ID:%04X,data:%02x %02x %02x %02x %02x %02x %02x %02x.\r\n",
Can1.RxMsg.StdId,Can1.RxMsg.Data[0],Can1.RxMsg.Data[1],Can1.RxMsg.Data[2],Can1.RxMsg.Data[3],Can1.RxMsg.Data[4],Can1.RxMsg.Data[5],Can1.RxMsg.Data[6],Can1.RxMsg.Data[7]);
switch (Can1.RxMsg.Data[0]) //根据命令处理CAN数据
{
case CMD_POSITON: //位置查询
{
Can1.TxMsg.StdId = Parm.id; //
Can1.TxMsg.ExtId = 0; /* Extended ID(LSBs) */
Can1.TxMsg.IDE = CAN_STANDARD_ID; /* 标准格式和扩展格式*/
Can1.TxMsg.RTR = CAN_RTRQ_DATA; /* 远程帧或数据帧 */
Can1.TxMsg.DLC = 8; /* 0 to 8 */
for (u8 i = 0; i < 8; i++)
{
Can1.TxMsg.Data[i] = Position.bitBuf[i]; //位置信息bit
}
Can1.TxMsg.Data[0] = CMD_POSITON; //赋值命令字
CAN_Transmit_Message_initializes(CAN, &Can1.TxMsg); //发送CAN数据.
break;
}
case CMD_ALARM: //报警
{
break;
}
case CMD_RGB_LED_ALL: //打开所有RGB LED.
{
u32 colour = 0; //灯珠颜色
Can1.TxMsg.StdId = Parm.id; //
Can1.TxMsg.ExtId = 0; /* Extended ID(LSBs) */
Can1.TxMsg.IDE = CAN_STANDARD_ID; /* 标准格式和扩展格式*/
Can1.TxMsg.RTR = CAN_RTRQ_DATA; /* 远程帧或数据帧 */
Can1.TxMsg.DLC = 8; /* 0 to 8 */
for (u8 i = 0; i < 8; i++)
{
Can1.TxMsg.Data[i] = Position.bitBuf[i]; //位置信息bit
}
Can1.TxMsg.Data[0] = CMD_SET_RGB_LED; //赋值命令字
CAN_Transmit_Message_initializes(CAN, &Can1.TxMsg); //发送CAN数据.
colour |= Can1.RxMsg.Data[1]<<16;
colour |= Can1.RxMsg.Data[2]<<8;
colour |= Can1.RxMsg.Data[3];
// colour = 0XFF00; //This code just for test.
for (u8 i = 0; i < RGB_LED_NUM; i++)
{
setLedCorlor(i,colour,0xff,0xffff);
}
break;
}
case CMD_SET_RGB_LED: //设置单个RGB LED 工作
{
u8 serialNum = 0; //灯珠序号
u32 colour = 0; //灯珠颜色
u8 times = 0; //灯珠闪烁次数0:灭 1-244闪烁次数,255:持续闪烁
u16 period = 0; //闪烁频率
serialNum = Can1.RxMsg.Data[1]; //灯珠序号
colour |= Can1.RxMsg.Data[2]<<16; //灯珠颜色
colour |= Can1.RxMsg.Data[3]<<8;
colour |= Can1.RxMsg.Data[4];
times = Can1.RxMsg.Data[5]; //灯珠闪烁次数0:灭 1-244闪烁次数,255:持续闪烁
period |= Can1.RxMsg.Data[6]<<8; //闪烁频率
period |= Can1.RxMsg.Data[7];
setLedCorlor(serialNum,colour,times,period);
break;
}
case CMD_SET_PARM: //设置灯板参数,灯板ID 灯珠数目
{
u32 id = 0; //灯板ID。
u8 num = 0; //灯珠数目
id = Can1.RxMsg.Data[1]; //灯板ID
num = Can1.RxMsg.Data[2]; //灯珠数目
u8 * parmP = (u8 *)(&Parm); //获取参数结构体地址。
w25qxxRead(parmP,PARAMETER_ADDR,sizeof(Parm)); //read back the flash parameter.
Parm.id = id;
Parm.rgbLedNum = num;
w25qxxWrite(parmP,PARAMETER_ADDR,sizeof(Parm)); //Write system parameters to FLASH.
break;
}
case CMD_SET_LUMINANCE: //设置灯板参亮度
{
RgbLed.luminance = Can1.RxMsg.Data[1]; //灯板亮度
RgbLed.refresh = true; //刷新显示。
break;
}
case CMD_RESET: //
{
printf("CAN通信重启:id=%d.\r\n",Can1.RxMsg.StdId); //
delay_ms(1000); //
NVIC_SystemReset();
break;
}
case CMD_REV: //
{
break;
}
default:break;
}
}
}