激光测距传感器TOFSense CAN模式的使用

发布时间 2023-08-17 11:36:56作者: Mr_Dai

随笔记-获取TOFSense的数据

之前写了一篇UART的移植以及适用,今天写一篇关于CAN的使用
这里就不多介绍了该模块了

CAN模式

与UART模式一样CAN也是支持主动输出以及查询输出的

协议如下图,基于协议可以看到我们需要Arbitration Field中的ID,也就是CAN标识符也可以认为是地址,以及Data Field中的数据,其他的都不需要管

查询协议

因为CAN需要使用can芯片手里正好有一个F407自带CAN芯片,所以以下代码基于STM32F407编写
编程的话参考官方的例程文件
简单介绍一下CAN与基于stm32cubemx配置can(并不是很精通,能用就行)
这里只简单说一下本人的理解与想法,原理性的问题可以移步其他CAN教程,网上有很多更好的教程

CAN的配置

CAN有比特率也有说波特率的,其实对于CAN来说,比特率和波特率这两个概念是一致的,但并不是说这两个概念永远是一致的,只是在满足某个条件的时候,两个概念才会相同,感兴趣建议大家百度看一下大佬的介绍。
配置CAN相关参数,波特率设定为1M,APB1的时钟频率为42M,
波特率计算公式:42M/6/(4+2+1)=1M.

然后打开中断

OK CAN的硬件配置到此完成

CAN模式与UART不同的是需要先对过滤器进行配置(网上有说可以不配置,但是我实际测试时不配置接收不到数据),这里参考正点原子的例程进行配置

CAN_TxHeaderTypeDef TxHeader;
CAN_RxHeaderTypeDef	RxHeader;

void tof_can_init(void)
{
	CAN_FilterTypeDef  sFilterConfig;
  
	sFilterConfig.FilterActivation = ENABLE;
	sFilterConfig.FilterBank = 0;
	sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
	sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
	sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
	sFilterConfig.FilterIdHigh = 0x0000;
	sFilterConfig.FilterIdLow = 0x0000;
	sFilterConfig.FilterMaskIdHigh = 0x0000;
	sFilterConfig.FilterMaskIdLow = 0x0000;
 
	if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK){while(1){ }}
	if(HAL_CAN_Start(&hcan1) != HAL_OK){while(1){ }}
	if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK){while(1){ }}
	
    //这里是查询模式需要提前配置好stdid
	TxHeader.StdId=0x402;	//查询标准帧ID
	TxHeader.ExtId=0;
	TxHeader.IDE=CAN_ID_STD;
	TxHeader.RTR=CAN_RTR_DATA;
	TxHeader.DLC=8;
}

配置好后,开始编写解析程序,此次的逻辑是通过中断回调函数获取当前帧的StdId来判断,因为TOFSense的StdId是固定的0x200+id

float dis;					//距离数据
uint8_t dis_status;			//距离状态指示
uint16_t signal_strength;	//信号强度

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	uint8_t id;
        int32_t temp = 0;
	if(hcan->Instance==CAN1)
	{
		HAL_CAN_GetRxMessage(&hcan1,CAN_FILTER_FIFO0,&RxHeader,can_rx_buf);//获取数据
                if ((RxHeader.StdId & 0x200) == 0x200 )
                {
	                temp = (int32_t)(can_rx_buf[0] << 8 | can_rx_buf[1] << 16 | can_rx_buf[2] << 24)/256;	//计算此帧数据距离
	                dis = temp/1000.0f;										//除以1000后单位为m

	                dis_status = can_rx_buf[3];								//此帧距离状态指示
	                signal_strength = can_rx_buf[4] | can_rx_buf[5] <<8;	//此帧信号强度
                }
	}
}

查询模式
由于之前我们在tof_can_init中已经配置好了查询标准帧ID所以查询数据可以直接发送指令

uint8_t can_tx_buf[8] = {0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff};	//查询命令

void get_CAN_data(uint8_t id)
{
    can_tx_buf[3] = id;
    HAL_CAN_AddTxMessage(&hcan1, &TxHeader, can_tx_buf, (uint32_t*)CAN_TX_MAILBOX0);

}

需要注意的是如果CAN总线上挂载的有其他设备则需要将查询标准帧ID的初始化放到发送函数内

uint8_t can_tx_buf[8] = {0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff};	//查询命令

void get_CAN_data(uint8_t id)
{
	TxHeader.StdId=0x402;	//查询标准帧ID
	TxHeader.ExtId=0;
	TxHeader.IDE=CAN_ID_STD;
	TxHeader.RTR=CAN_RTR_DATA;
	TxHeader.DLC=8;

    can_tx_buf[3] = id;
    HAL_CAN_AddTxMessage(&hcan1, &TxHeader, can_tx_buf, (uint32_t*)CAN_TX_MAILBOX0);

}