CAN与上位机通信详细教程

CAN与上位机通信详细教程

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
本文使用32版HAL库与上位机进行通信,使用按键按一次则发送一次数据给上位机,上位机发送一次数据给32板则使用串口打印出来



提示:本文借鉴多个博文大佬的参考 1.对于can过滤器配置请大家参考https://blog.csdn.net/flydream0/article/details/52317532这位博主的,写的非常通俗易懂。
2.对于CSDN上很多作者的通信都是32发一个数据,则上位机把这个数据传输并打印出来,对于我做的一个项目感觉不太相似,就直接捣鼓出来发送、接收数据不一样的形式。好了,下面开始正文。


一、HAL库配置

1.我使用的是正点原子精英板(板子不一样也没关系)原理图
在这里插入图片描述
2.开始CubeMX配置
1.GPIO(按键和LED的配置)
在这里插入图片描述
2.RCC配置
在这里插入图片描述在这里插入图片描述

3.can配置
在这里插入图片描述
波特率:36MHZ/(9+5+2)=500
配置中断:在这里插入图片描述
3.串口
在这里插入图片描述

二、CAN—发送内容

1.定义发送结构体

在这里插入图片描述

2.定义发送函数(记得在can.h头文件也定义一下、在CAN.c里面)

CAN_TxHeaderTypeDef CAN_TX;
void CAN_Send(void)
{
	uint32_t TxMailbox;
	uint8_t Tdata[8]={0x00,0x04,0x93,0xE0,0x00,0x00,0x27,0x10};
	CAN_TX.StdId=0x123;
	CAN_TX.ExtId=0x028900F0;
	CAN_TX.IDE=CAN_ID_EXT;
	CAN_TX.RTR=CAN_RTR_DATA;
	CAN_TX.TransmitGlobalTime=DISABLE;
	CAN_TX.DLC=8;
	
	if(HAL_CAN_AddTxMessage(&hcan,&CAN_TX,Tdata,&TxMailbox)!=HAL_OK)
	{
		Error_Handler();
	}
}

3.man函数设置一下

下面代码放在main.c文件的while(1)里面

 /* USER CODE END WHILE */
		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)//当按键按下
		{
			while(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
			{
				HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,0);//LED灯亮
				
				CAN_Send();//数据发送
				HAL_Delay(1000);
				HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,1);//LED灯灭
				HAL_Delay(500);
			}
			
		}

二、CAN—接收函数

1.定义接收滤波(在can.c里面)

void CAN_Filter_Config(void)
{
	uint32_t EXRID=0x029BF03F;
	CAN_FilterTypeDef CAN_FilterInitStructure;
	CAN_FilterInitStructure.FilterBank=0;//使用那个筛选器
	CAN_FilterInitStructure.FilterMode=CAN_FILTERMODE_IDMASK;//设置掩码模式
	CAN_FilterInitStructure.FilterScale=CAN_FILTERSCALE_32BIT;//筛选器32位宽
	CAN_FilterInitStructure.FilterIdHigh=((EXRID<<3)&0xFFFF0000)>>16;//(((((uint32_t )0X1314)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;//筛选高id高位
	CAN_FilterInitStructure.FilterIdLow=((EXRID<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;//((((uint32_t )0X1314)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000;//筛选高id高位
	CAN_FilterInitStructure.FilterMaskIdHigh=0xFF00;
	CAN_FilterInitStructure.FilterMaskIdLow=0x0000;//设置筛选器每一位匹配
	
	CAN_FilterInitStructure.FilterFIFOAssignment=CAN_FilterFIFO0;//关联到f0
	CAN_FilterInitStructure.FilterActivation=ENABLE;//使能筛选器
	
	HAL_CAN_ConfigFilter(&hcan,&CAN_FilterInitStructure);
	
	
}

2.设置中断函数(写在main.c的int main前面)

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	CAN_RxHeaderTypeDef CAN_RX;
	uint8_t aData[8]; 
	if(hcan->Instance ==CAN1)
	{
		HAL_CAN_GetRxMessage(hcan,CAN_FilterFIFO0,&CAN_RX,aData);//从上位机获取数据
		HAL_UART_Transmit(&huart1,aData,CAN_RX.DLC,HAL_MAX_DELAY);//把获取的数据通过串口打印出来
		
	}

}

3.main函数中配置

下面代码放在int main(void)里面,放在while(1)上面

HAL_CAN_Start(&hcan);
	CAN_Filter_Config();
	HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);//fifo0中断

实现结果

1.发送结果
在这里插入图片描述
2.接收结果
在这里插入图片描述
以上程序是完全可以实现的,当然如果还想要文件的我后续把文件上传一下。还要不了解的可以私信我,我看到会回复。
有需要下载项目程序的小伙伴可以点这个链接下载一下
https://download.csdn.net/download/weixin_51499713/85143920?spm=1001.2014.3001.5503

  • 7
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要实现Qt上位机与CAN通信,需要使用Qt的串口通信库和CAN通信库。下面是一些基本步骤: 1. 确定使用的CAN通信库,例如socketCAN或者PCAN。 2. 在Qt项目中添加CAN通信库的头文件和库文件。 3. 打开CAN通信端口。 4. 设置CAN通信参数,例如波特率、滤波、模式等。 5. 编写接收CAN数据的槽函数。 6. 编写发送CAN数据的槽函数。 7. 在Qt界面中添加控件,例如按钮、文本框和列表框等。 8. 将控件的信号与槽函数连接起来。 9. 在槽函数中使用CAN通信库进行数据的收发。 10. 在界面中显示CAN数据。 下面是一个简单的示例代码: ```cpp #include <QtSerialPort/QSerialPort> #include <QtCore/QDebug> class CanBus : public QObject { Q_OBJECT public: CanBus(QObject *parent = nullptr) : QObject(parent) { // 打开CAN通信端口 m_canPort = new QSerialPort(this); m_canPort->setPortName("/dev/ttyACM0"); m_canPort->setBaudRate(QSerialPort::Baud9600); m_canPort->setDataBits(QSerialPort::Data8); m_canPort->setParity(QSerialPort::NoParity); m_canPort->setStopBits(QSerialPort::OneStop); m_canPort->setFlowControl(QSerialPort::NoFlowControl); m_canPort->open(QIODevice::ReadWrite); // 设置接收CAN数据的槽函数 connect(m_canPort, SIGNAL(readyRead()), this, SLOT(readData())); } ~CanBus() { m_canPort->close(); delete m_canPort; } public slots: void sendData(const QByteArray &data) { // 发送CAN数据 m_canPort->write(data); } void readData() { // 接收CAN数据 QByteArray data = m_canPort->readAll(); // 在界面中显示CAN数据 qDebug() << "Receive data: " << data.toHex(); } private: QSerialPort *m_canPort; }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); CanBus can; // 连接按钮的信号和发送数据的槽函数 QPushButton *sendButton = new QPushButton("Send"); QLineEdit *sendLineEdit = new QLineEdit(); QObject::connect(sendButton, &QPushButton::clicked, [&]() { QByteArray data = sendLineEdit->text().toUtf8(); can.sendData(data); }); // 显示接收到的CAN数据 QListWidget *receiveListWidget = new QListWidget(); QObject::connect(&can, &CanBus::receiveData, [&](const QByteArray &data) { receiveListWidget->addItem(data.toHex()); }); // 显示界面 QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(sendLineEdit); layout->addWidget(sendButton); layout->addWidget(receiveListWidget); QWidget *widget = new QWidget(); widget->setLayout(layout); widget->show(); return a.exec(); } ``` 请注意,上述示例代码仅供参考,实际应用中需要根据具体的CAN通信库和项目需求进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值