① MCU:MCU通过APB总线访问CAN外设。② CAN外设:挂载在MCU的APB总线上,实现基本协议CAN2.0A、扩展协议CAN2.0B、接收滤波器、发送优先级及对CAN FD的支持等,并留出外设访问接口给MCU,以便MCU控制。③ CAN收发器:看其收发器框图,因仅包含CANH、CANL总线,所以TXD发出的CANH、CANL与RXD读出的CANH、CANL是连接在一起的,因此CAN收发器TXD发送出来的总线信号会立即被转换从RXD输出给CAN接口(LBME环回模式使用此特性)
MCU通过APB总线访问CAN外设,通过配置相关寄存器配置CAN的运行环境,通过写BUF及相关配置位发送CAN帧;通过轮询某些状态位或者中断,读取收到的BUF或者CAN外设目前处于的状态,并依据部分状态作出相应的动作;CAN收发器将CAN外设的CAN_TX高低电平信号转换为CANH、CANL总线信号,并将接收到的CANH、CANL总线信号转换为CAN外设的CAN_RX高低电平信号,该信号输送给CAN外设,CAN外设根据CAN接收滤波器的设置判断是否接收该数据帧等等。
1、查看原理图,看使用哪一个CAN接口。STB使用的引脚
#define CAN1_TX (GPIO_PC15) //pin 75
#define CAN1_RX (GPIO_PC14) //pin 74
#define CAN1_STB (GPIO_PD5) // pin9
2、进行初始化操作
CAN_InitHardwr();
定义两个结构体变量,CAN_Config和CAN_BaudrateConfig
- 初始化硬件接口
GPIO_SetFunc(CAN1_TX, GPIO_FUNC_1);//设置CAN1引脚复用功能 GPIO_SetFunc(CAN1_RX, GPIO_FUNC_1); GPIO_SetDir(CAN1_STB, GPIO_OUTPUT);//设置CAN1收发器控制为IO控制 //GPIO_FUNC_1 参考数据手册中“信号多路复用和引脚分配”,使用function 1功能
- 使能CAN收发器
CAN1_TRASCVER_NML;//使能CAN收发器 //#define CAN1_TRASCVER_NML do{GPIO_ResetPinBits(CAN1_STB);}while(0)
- 设置波特率和采样点进行配置
/*
设置波特率为500K,采样点为81.25%.
tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
BandRate = (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1)))
SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
在已经知道波特率与采样点的情况下,经过计算后:tSeg1 = 13,tSeg2 = 3.
*/
canBandrateConfig.S_PRESC = 5;//分频后时钟为8M.
canBandrateConfig.S_SEG_1 = 11;
canBandrateConfig.S_SEG_2 = 2;
canBandrateConfig.S_SJW = 2;//满足S_SJW <= tSeg2即可.
- 过滤器设置:选择哪一个过滤器、指定过滤模式、过滤的ID类型
16个过滤器中,可随意选择使用哪个,并制定其过滤模式,制定其过滤ID的类型. 如果一个过滤器只需要接收一个ID,直接可将其设置CODE模式,然后根据ID类型设置过滤类型. 如果一个过滤器需要接收多个ID,将其设置为MASK模式,并根据这几个ID的实际类型设置过滤ID类型,如果既有STD又有EXT,则应选择FILTER_IDE_STD_EXT_BOTH. 此处加宏是为了更清楚的说明各种设置是否有效,在实际应用中,可将各种组合放在一起使用. #if (RECV_FRM_KIND_SEL == ONLY_RECV_STD_FRM) CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD帧 CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID2);//使用CODE模式只接收STD帧 #endif #if (RECV_FRM_KIND_SEL == ONLY_RECV_EXT_FRM) CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID11);//使用CODE模式只接收EXT帧 CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID12);//使用CODE模式只接收EXT帧 #endif #if (RECV_FRM_KIND_SEL == RECV_STD_EXT_BOTH_FRM) CAN_SetFilterParam( 0, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID1 & CAN1_RECV_DATA_ID11));//使用MASK模式接收两种帧 CAN_SetFilterParam( 1, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID2 & CAN1_RECV_DATA_ID12));//使用MASK模式接收两种帧 #endif
- CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD帧
* @prototype CAN_SetFilterParam(uint8_t filterNum, uint8_t filterEn, CAN_FilterMode_TypeDef filterMode, CAN_FilterMask_TypeDef filterMask, uint32_t ID)
*
* @param[in] filterNum:过滤器编码,0到15可用.
* @param[in] filterEn:过滤器使能状态,1使能,0禁能
* @param[in] filterMode:CAN_FilterMode_TypeDef已定义.
* @param[in] filterMask:参考CAN_FilterMask_TypeDef.
* @param[in] ID
* @return void
参数说明:0:选用的过滤器编码
1:1标识使能,0为禁止
CAN_FILTER_CODE_MODE:分code模式和mask模式,code只能接收一个ID,mask可以接收多个ID
FILTER_IDE_STD_ONLY:分标准帧、扩展帧、混合帧
ID:需要过滤的ID,表示这个ID可以通过,单片机可以接收到数据。
- 设置can配置
canConfig.interruptEnable = TRUE;//使能中断 canConfig.TSSS = TRUE;//使用次发送缓冲区发送 canConfig.canMode = CAN_MODE_NORMAL; canConfig.autoReset = TRUE;//CAN BUSOFF后,自动恢复 canConfig.filterList = g_canFilterTab;//赋值过滤器设置list
- 设置回调函数CAN_SetEventCallBack(CAN1, CAN1_IRQnCallBack);
/** * @prototype CAN1_IRQnCallBack(uint32_t event, uint32_t wparam, uint32_t lparam) * * @param[in] ... * @return ... * * @brief CAN1 module interrupt handler. * CAN1中断处理函数. */ int32_t CAN1_IRQnCallBack(uint32_t event, uint32_t wparam, uint32_t lparam) { if (event & CAN_EVENT_RECVMSG) { if (CAN_IsMsgInReceiveBuf((CAN_Type*)lparam)) { CAN_MessageRead((CAN_Type*)lparam, &g_recvCANMsgInfo); g_recvedCANDataRdy = TRUE; } } return 1; }
- 调用库函数CAN_Initialize()。
CAN_Initialize(CAN1, &canConfig, &canBandrateConfig);//程序引用
CAN_Initialize(CAN_Type *CANx, CAN_Config *config, const CAN_BaudrateConfig *baudrate)//函数原型
参数说明:
- @param[in] CANx: CAN type pointer
- @param[in] config: CAN config
- @param[in] baudrate: CAN baud rate
- @return 0: no error, 1: Initialize error
void CAN_InitHardwr(void)
{
CAN_Config canConfig = {0};
CAN_BaudrateConfig canBandrateConfig = {0};
GPIO_SetFunc(CAN1_TX, GPIO_FUNC_1);//设置CAN1引脚复用功能
GPIO_SetFunc(CAN1_RX, GPIO_FUNC_1);
GPIO_SetDir(CAN1_STB, GPIO_OUTPUT);//设置CAN1收发器控制为IO控制
CAN1_TRASCVER_NML;//使能CAN收发器
/*
设置波特率为500K,采样点为81.25%.
tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
BandRate = (48M / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1)))
SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
在已经知道波特率与采样点的情况下,经过计算后:tSeg1 = 13,tSeg2 = 3.
*/
canBandrateConfig.S_PRESC = 5;//分频后时钟为8M.
canBandrateConfig.S_SEG_1 = 11;
canBandrateConfig.S_SEG_2 = 2;
canBandrateConfig.S_SJW = 2;//满足S_SJW <= tSeg2即可.
/*
16个过滤器中,可随意选择使用哪个,并制定其过滤模式,制定其过滤ID的类型.
如果一个过滤器只需要接收一个ID,直接可将其设置CODE模式,然后根据ID类型设置过滤类型.
如果一个过滤器需要接收多个ID,将其设置为MASK模式,并根据这几个ID的实际类型设置过滤ID类型,如果既有STD又有EXT,则应选择FILTER_IDE_STD_EXT_BOTH.
此处加宏是为了更清楚的说明各种设置是否有效,在实际应用中,可将各种组合放在一起使用.
*/
#if (RECV_FRM_KIND_SEL == ONLY_RECV_STD_FRM)
CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID1);//使用CODE模式只接收STD帧
CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_STD_ONLY, CAN1_RECV_DATA_ID2);//使用CODE模式只接收STD帧
#endif
#if (RECV_FRM_KIND_SEL == ONLY_RECV_EXT_FRM)
CAN_SetFilterParam( 0, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID11);//使用CODE模式只接收EXT帧
CAN_SetFilterParam( 1, 1, CAN_FILTER_CODE_MODE, FILTER_IDE_EXT_ONLY, CAN1_RECV_DATA_ID12);//使用CODE模式只接收EXT帧
#endif
#if (RECV_FRM_KIND_SEL == RECV_STD_EXT_BOTH_FRM)
CAN_SetFilterParam( 0, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID1 & CAN1_RECV_DATA_ID11));//使用MASK模式接收两种帧
CAN_SetFilterParam( 1, 1, CAN_FILTER_MASK_MODE, FILTER_IDE_STD_EXT_BOTH, (CAN1_RECV_DATA_ID2 & CAN1_RECV_DATA_ID12));//使用MASK模式接收两种帧
#endif
canConfig.interruptEnable = TRUE;//使能中断
canConfig.TSSS = TRUE;//使用次发送缓冲区发送
canConfig.canMode = CAN_MODE_NORMAL;
canConfig.autoReset = TRUE;//CAN BUSOFF后,自动恢复
canConfig.filterList = g_canFilterTab;//赋值过滤器设置list
CAN_SetEventCallBack(CAN1, CAN1_IRQnCallBack);
CAN_Initialize(CAN1, &canConfig, &canBandrateConfig);
}
-
滤波器
+关注
关注
158文章
7332浏览量
174793 -
AMBA
+关注
关注
0文章
67浏览量
14812 -
CAN收发器
+关注
关注
2文章
149浏览量
25332 -
串口中断
+关注
关注
0文章
63浏览量
13614 -
MCU控制器
+关注
关注
0文章
27浏览量
6820
发布评论请先 登录
相关推荐
评论