RT-Thread studio配置can hal库 驱动GM6020
最近由裸机系统转战rt-thread,在刚入手RT-Thread的过程中记录一些东西吧,可能是刚做的原因,软件还不是那么完整好用,希望以后可以越来越好。手头正好有一个大疆的GM6020电机,想用can做一个驱动来试一下。
提前说明一下,由于我按照官方的教程调用函数没有成功,而且响应的文件也没自动加载,不知道是我的原因还是软件不支持,现在我是直接用hal库的函数驱动,效果一样,也是在studio里面直接操作,希望有懂的大神可以指出正确的操作。
1、新建工程
这里我用的是stm32f103vet6芯片,板子是自己做的。
2、CubeMx配置
先新建一个工程
打开下载接口,否则芯片烧写一次后就会被锁死
外部时钟
时钟配置!!这里很重要!!!!我就是因为这里没配置好!不同的芯片根据自己的芯片手册配就行了,或者找野火的资料hal库开发指南里面有一些芯片的说明!
使能can 打开接收中断
接下来是配置can 我这里用的是1Mbps 设置BS1 BS2的时候可以先把数调大一个再调回来,这个报错不影响使用
project配置
这里选中可以将驱动代码单独生成一个.c .h文件
生成工程
3、RT-Thread studio代码移植
首先打开setting里的can模块
打开宏
时钟函数,注意只需要将大括号内的代码覆盖掉drv_clk.c中的函数代码,函数名不要改
如下
然后将生成的can.c can.h复制到studio工程下的drivers文件夹下
编译一下studio工程 左侧会自动显示添加的文件
由于cubemx生成的代码中没有can的过滤器配置,这里需要自己添加,在can.c中
HAL_StatusTypeDef CAN_Filter_Init(CAN_HandleTypeDef *h_can)
{
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0; //chenal 0
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = ((((uint32_t)0x205<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;
sFilterConfig.FilterIdLow = (((uint32_t)0x205<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
//MASK bit 0 means don't care,bit 1 means match
sFilterConfig.FilterMaskIdHigh = 0x0000; //无需匹配
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; //FIFO0
sFilterConfig.FilterActivation = CAN_FILTER_ENABLE; //enable filter
sFilterConfig.SlaveStartFilterBank = 0;
if (HAL_CAN_ConfigFilter(h_can, &sFilterConfig) != HAL_OK)
{
rt_kprintf("rt_can_filter_error!!\r\n");
Error_Handler();
return HAL_ERROR;
}
//regist RX_IT
if (HAL_CAN_ActivateNotification(h_can, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) //??CAN_IT_RX_FIFO0_MSG_PENDING ?????????
{
rt_kprintf("rt_an_error!!\r\n");
Error_Handler();
return HAL_ERROR;
}
return HAL_OK;
}
自己写一个发送函数,调用的库函数发送HAL_CAN_AddTxMessage() can.c中
uint8_t HAL_CAN_SendTxMessage(CAN_TxHeaderTypeDef *TxHeader,uint32_t std_id, uint8_t aData[],uint16_t lengh)
{
uint32_t TxMailBox;
uint8_t FreeTxMailBoxNum;
TxHeader->StdId = std_id;
TxHeader->DLC = lengh;
TxHeader->IDE = CAN_ID_STD;
TxHeader->RTR = CAN_RTR_DATA;
TxHeader->TransmitGlobalTime = DISABLE;
while(0 == FreeTxMailBoxNum)
{
FreeTxMailBoxNum = HAL_CAN_GetTxMailboxesFreeLevel(&hcan);
}
if (HAL_CAN_AddTxMessage(&hcan, TxHeader, aData, &TxMailBox) != HAL_OK)
{
/* Transmission request Error */
Error_Handler();
return 0;
}
return 1;
}
can.c 里添加收发结构体
can.h将#include <main.h>改#include <board.h>
并且声明一下结构体
can.c 添加GM6020的数据包发送程序,并将函数添加到.h文件中声明
uint8_t txdata[8] ;
void can_6020()
{
txdata[0] = 5000>>8;
txdata[1] = 5000&0x00ff;
MX_CAN_Init();
CAN_Filter_Init(&hcan);
HAL_CAN_Start(&hcan);
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
while(1)
{
HAL_CAN_SendTxMessage(&TxHeader,0x1FF, txdata,8);
rt_thread_mdelay(100);
}
}
在drv_common.c里添加中断服务函数
void USB_LP_CAN1_RX0_IRQHandler(void)
{
HAL_CAN_IRQHandler(&hcan);
}
*该函数会自动调用void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef hcan)
因此我们在can.c里添加这个函数
简单写一下测试用,实际可根据自己的需要加筛选器,以及具体的中断接收函数,这里只给出介绍
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t aRxData[8];
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, aRxData) == HAL_OK)
{
//rt_kprintf("can 6020 receive message !!!\r\n");
}
}
到这基本配置完成,接下来就是添加一个线程来验证一下程序。
4、添加线程
main.c
#include <rtthread.h>
#define DBG_TAG "main"
#include "can.h"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
static rt_thread_t can6020_thread = RT_NULL;
int main(void)
{
can6020_thread =
rt_thread_create("can6020_thread",
can_6020,
RT_NULL,
512,
5,
20);
if(can6020_thread!=RT_NULL)
{
rt_thread_startup(can6020_thread);
}else
{
return -1;
}
}
编译–>烧录,电机轻松起转!中断成功进入!
注意:添加的函数需要声明,相关的头文件需要引用,跟keil用法一样。
更新一下,刚看到有人用正规做法驱动的can