1,因为自己目前只有一块板子有CAN模块,所以先做CAN的回环测试。
主要参考http://www.stm32cube.com/question/33
下面的代码测试可以使用
1-1,在CAN的编程中,主要是注意四大结构体,这几个都是自动生成的,
1、CAN_HandleTypeDef hcan1;// CAN handle Structure definition首先定义CAN的处理结构体,hcan1内部包括了
3、CanTxMsgTypeDef; 4、CanRxMsgTypeDef;的头地址
2、CAN_FilterConfTypeDef sFilterConfig;// CAN filter configuration structure definition需要学会怎么配置配置过滤器
3、CanTxMsgTypeDef;//CAN Tx message structure definition //can的发送配置,主要是Stdld标准标识符,Extld标准扩展标识符,IDE标准帧与扩展帧的区别,RTR数据帧或遥控帧,DLC数据帧的长度,data[]要发送的数据段的内容,最大8个字节
4、CanRxMsgTypeDef; //CAN Rx message structure definition//除了发送CAN中的参数,还包括FMI过滤器的编号,FIFONumber的编号。
1-2,CAN的发送与接收模式与以前的串口,I2C,FLASH都有区别。
can的发送是HAL_CAN_Transmit(&hcan1, 10),在字面上并不指定发送数据的数组,而是发送的是一个结构体,包含的信息更多,如stdld,IDE,DLC,data[]等等。
但hcan1->Data中实际就是包含的数组值.
同理可以看到can 的接收函数(HAL_CAN_Receive(&hcan, CAN_FIFO0,10),也是一样的分析
1-3,简单的发送可以封装函数
1-4,注释
1-5,hal_can.h常用函数
/** @addtogroup CAN_Exported_Functions_Group1
* @brief Initialization and Configuration functions
* @{
*/
/* Initialization and de-initialization functions *****************************/
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan);
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig);
HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef* hcan);
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan);
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group2
* @brief I/O operation functions
* @{
*/
/* I/O operation functions *****************************************************/
HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout);
HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef *hcan, uint8_t FIFONumber, uint32_t Timeout);
HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef *hcan, uint8_t FIFONumber);
HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan);
void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan);
void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan);
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan);
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan);
/**
1-6 测试函数
/* USER CODE BEGIN 1 */
HAL_StatusTypeDef CAN_Polling(void)
{
CAN_FilterConfTypeDef sFilterConfig;
static CanTxMsgTypeDef TxMessage;
static CanRxMsgTypeDef RxMessage;
hcan.pTxMsg = &TxMessage;//²é¿´CAN_HandleTypeDefµÄ¶¨Ò壬pTxMsgÊÇÒ»¸ö½á¹¹ÌåÖ¸Õë
hcan.pRxMsg = &RxMessage;
//Configure the CAN Filter
sFilterConfig.FilterNumber = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = 0;//???????FIFO?,0??1,??????FIFO0
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
{
//[i] Filter configuration Error [/i]/
Error_Handler();
}
//3- Start the Transmission process
hcan.pTxMsg->StdId = 0x11; //Ö¸¶¨±ê×¼±êʶ·û£¬0-0X7FF
hcan.pTxMsg->RTR = CAN_RTR_DATA; //RTR,Çø·ÖÊý¾ÝÖ¡»¹ÊÇÒ£¿ØÖ¡£¬´Ë´¦ÎªÊý¾ÝÖ¡
hcan.pTxMsg->IDE = CAN_ID_STD;//Çø±ð±ê×¼Ö¡ºÍÀ©Õ¹Ö¡£¬#define CAN_ID_EXT 0x00000004U /*!< Extended Id */
hcan.pTxMsg->DLC = 2;//ÉèÖÃÊý¾ÝÖ¡Êý¾Ý³¤¶È£¬·¶Î§0-8
hcan.pTxMsg->Data[0] = 0xCA;//µÚÒ»¸ö×Ö½ÚÊý¾Ý
hcan.pTxMsg->Data[1] = 0xFE;//µÚ¶þ¸ö×Ö½ÚÊý¾Ý
if(HAL_CAN_Transmit(&hcan, 10) != HAL_OK)//timeout 10ms
{
//²é¿´´«ÊäÊÇ·ñ³¬Ê±£¬³¬Ê±µãÁÁºìÉ«LED
HAL_GPIO_WritePin (GPIOB,GPIO_PIN_5,GPIO_PIN_RESET );
while(1);
}
if(HAL_CAN_GetState(&hcan) != HAL_CAN_STATE_READY)
{
return HAL_ERROR;
}
//4- Start the Reception process
if(HAL_CAN_Receive(&hcan, CAN_FIFO0,10) != HAL_OK)//ÉÏÃ涨ÒåÁËFIFO0
{
//Reception Error
HAL_GPIO_WritePin (GPIOB,GPIO_PIN_5,GPIO_PIN_RESET );
while(1);
}
if(HAL_CAN_GetState(&hcan) != HAL_CAN_STATE_READY)
{
return HAL_ERROR;
}
if (hcan.pRxMsg->StdId != 0x11)//½ÓÊÕµ½µÄÊý¾Ý±êʶ·û
{
printf ("CAN1 Loopback fause !/r/n");
return HAL_ERROR;
}
if (hcan.pRxMsg->IDE != CAN_ID_STD)//??????????
{
return HAL_ERROR;
}
if (hcan.pRxMsg->DLC != 2)//????????
{
return HAL_ERROR;
}
if ((RxMessage.Data[0]<<8|RxMessage.Data[1]) != 0xCAFE)
{
return HAL_ERROR;
}
return HAL_OK; //[i] Test Passed [/i]/
}
/* USER CODE END 1 */
1-7,过滤器的匹配设置
https://blog.csdn.net/houqi02/article/details/51545967
https://blog.csdn.net/bonson2004/article/details/68942442
1-8,FIFO与过滤器的关联
http://www.openedv.com/posts/list/43984.htm