1.FDCAN設(shè)備添加
如下圖所示,使用RT-Thread Setting 添加默認(rèn)的FDCAN1設(shè)備,保存并重新構(gòu)建到工程;
2.修改波特率配置
檢查系統(tǒng)時鐘配置,確認(rèn)can輸入時鐘為80Mhz,如下圖所示:
修改drv_fdcan.c文件,由于本文使用的是500K的波特率,故只改了一小部分。
static const _stm32_fdcan_NTconfig_t st_CanNTconfig[]=
/ baud brp sjw tseg1 tseg2 /
{
{CAN1MBaud, 1,8,63,16},
{CAN800kBaud, 10,8,20,4},
{CAN500kBaud, 2,8,63,16},
{CAN250kBaud, 20,8,35,4},
{CAN125kBaud, 40,8,35,4},
{CAN100kBaud, 40,8,44,5},
{CAN50kBaud, 80,8,44,5},
{CAN20kBaud, 200,8,44,5},
{CAN10kBaud, 400,8,44,5}
};
修改drv_fdcan.c文件下的FDCAN_MODE_INTERNAL_LOOPBACK,改為FDCAN_MODE_EXTERNAL_LOOPBACK;此項改動為防止FDCAN在回環(huán)模式下TX沒有輸出信號;
static rt_err_t _inline_can_config(struct rt_can_device *can, struct can_configure *cfg)
{
_stm32_fdcan_t *pdrv_can;
rt_uint32_t tmp_u32Index;
RT_ASSERT(can);
RT_ASSERT(cfg);
pdrv_can = (_stm32_fdcan_t )can->parent.user_data;
RT_ASSERT(pdrv_can);
pdrv_can->fdcanHandle.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
pdrv_can->fdcanHandle.Init.AutoRetransmission = DISABLE;
pdrv_can->fdcanHandle.Init.TransmitPause = DISABLE;
pdrv_can->fdcanHandle.Init.ProtocolException = DISABLE;
switch (cfg->mode)
{
case RT_CAN_MODE_NORMAL:
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
break;
case RT_CAN_MODE_LISEN:
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_BUS_MONITORING;
break;
case RT_CAN_MODE_LOOPBACK:
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_EXTERNAL_LOOPBACK;
break;
default:
pdrv_can->fdcanHandle.Init.Mode = FDCAN_MODE_NORMAL;
break;
}
/ config baud rate /
tmp_u32Index = _inline_get_NTbaud_index(cfg->baud_rate);
pdrv_can->fdcanHandle.Init.NominalPrescaler = st_CanNTconfig[tmp_u32Index].u16Nbrp;
pdrv_can->fdcanHandle.Init.NominalSyncJumpWidth = st_CanNTconfig[tmp_u32Index].u8Nsjw;
pdrv_can->fdcanHandle.Init.NominalTimeSeg1 = st_CanNTconfig[tmp_u32Index].u8Ntseg1;
pdrv_can->fdcanHandle.Init.NominalTimeSeg2 = st_CanNTconfig[tmp_u32Index].u8Ntseg2;
if(pdrv_can->fdcanHandle.Instance == FDCAN1)
{
pdrv_can->fdcanHandle.Init.MessageRAMOffset = 0;
}
else
{
pdrv_can->fdcanHandle.Init.MessageRAMOffset = 1280;
}
pdrv_can->fdcanHandle.Init.StdFiltersNbr = 2;
pdrv_can->fdcanHandle.Init.ExtFiltersNbr = 2;
pdrv_can->fdcanHandle.Init.RxFifo0ElmtsNbr = 1;
pdrv_can->fdcanHandle.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
pdrv_can->fdcanHandle.Init.RxBuffersNbr = 0;
pdrv_can->fdcanHandle.Init.TxEventsNbr = 0;
pdrv_can->fdcanHandle.Init.TxBuffersNbr = 3;
pdrv_can->fdcanHandle.Init.TxFifoQueueElmtsNbr = 0;
pdrv_can->fdcanHandle.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
pdrv_can->fdcanHandle.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&pdrv_can->fdcanHandle) != HAL_OK)
{
return -RT_ERROR;
}
/ default filter config /
HAL_FDCAN_ConfigFilter(&pdrv_can->fdcanHandle , &pdrv_can->FilterConfig);
/ init fdcan tx header /
_inline_can_tx_header_init(pdrv_can);
/ can start */
HAL_FDCAN_Start(&pdrv_can->fdcanHandle);
return RT_EOK;
}
3.添加外設(shè)軟件包
使用RT-Thread Setting 添加【rtthread設(shè)備驅(qū)動使用示例】軟件包,在搜索框中搜索samples也可以找到,配置如下圖所示;
2.添加完成后,查看can_sample.c文件,如下圖所示;
3.修改can_sample.c文件,代碼如下,主要是將can1設(shè)備改為fdcan1,并增加設(shè)置can波特率語句。
#include
#include
#define CAN_DEV_NAME "fdcan1" /* CAN 設(shè)備名稱 /
static struct rt_semaphore rx_sem; / 用于接收消息的信號量 /
static rt_device_t can_dev; / CAN 設(shè)備句柄 /
/ 接收數(shù)據(jù)回調(diào)函數(shù) /
static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
{
/ CAN 接收到數(shù)據(jù)后產(chǎn)生中斷,調(diào)用此回調(diào)函數(shù),然后發(fā)送接收信號量 */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void can_rx_thread(void parameter)
{
int i;
rt_err_t res;
struct rt_can_msg rxmsg = {0};
/ 設(shè)置接收回調(diào)函數(shù) /
rt_device_set_rx_indicate(can_dev, can_rx_call);
#ifdef RT_CAN_USING_HDR
struct rt_can_filter_item items[5] =
{
RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), / std,match ID:0x1000x1ff,hdr 為 - 1,設(shè)置默認(rèn)過濾表 /0x3ff,hdr 為 - 1 /
RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), / std,match ID:0x300
RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), / std,match ID:0x211,hdr 為 - 1 /
RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL), / std,match ID:0x486,hdr 為 - 1 /
{0x555, 0, 0, 0, 0x7ff, 7,} / std,match ID:0x555,hdr 為 7,指定設(shè)置 7 號過濾表 /
};
struct rt_can_filter_config cfg = {5, 1, items}; / 一共有 5 個過濾表 /
/ 設(shè)置硬件過濾表 /
res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
RT_ASSERT(res == RT_EOK);
#endif
while (1)
{
/ hdr 值為 - 1,表示直接從 uselist 鏈表讀取數(shù)據(jù) /
rxmsg.hdr = -1;
/ 阻塞等待接收信號量 /
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
/ 從 CAN 讀取一幀數(shù)據(jù) /
rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
/ 打印數(shù)據(jù) ID 及內(nèi)容 /
rt_kprintf("ID:%x", rxmsg.id);
for (i = 0; i < 8; i++)
{
rt_kprintf("%2x", rxmsg.data[i]);
}
rt_kprintf("n");
}
}
int mycan_sample(int argc, char argv[])
{
struct rt_can_msg msg = {0};
rt_err_t res;
rt_size_t size;
rt_thread_t thread;
char can_name[RT_NAME_MAX];
if (argc == 2)
{
rt_strncpy(can_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
}
/ 查找 CAN 設(shè)備 /
can_dev = rt_device_find(can_name);
if (!can_dev)
{
rt_kprintf("find %s failed!n", can_name);
return RT_ERROR;
}
/ 初始化 CAN 接收信號量 /
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/ 以中斷接收及發(fā)送方式打開 CAN 設(shè)備 /
res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
RT_ASSERT(res == RT_EOK);
/ 設(shè)置 CAN 通信的波特率為 500kbit/s /
res = rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void )CAN500kBaud);
RT_ASSERT(res == RT_EOK);
/ 創(chuàng)建數(shù)據(jù)接收線程 /
thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
rt_kprintf("create can_rx thread failed!n");
}
msg.id = 0x78; / ID 為 0x78 /
msg.ide = RT_CAN_STDID; / 標(biāo)準(zhǔn)格式 /
msg.rtr = RT_CAN_DTR; / 數(shù)據(jù)幀 /
msg.len = 8; / 數(shù)據(jù)長度為 8 /
/ 待發(fā)送的 8 字節(jié)數(shù)據(jù) /
msg.data[0] = 0x00;
msg.data[1] = 0x11;
msg.data[2] = 0x22;
msg.data[3] = 0x33;
msg.data[4] = 0x44;
msg.data[5] = 0x55;
msg.data[6] = 0x66;
msg.data[7] = 0x77;
/ 發(fā)送一幀 CAN 數(shù)據(jù) /
size = rt_device_write(can_dev, 0, &msg, sizeof(msg));
if (size == 0)
{
rt_kprintf("can dev write data failed!n");
}
return res;
}
/ 導(dǎo)出到 msh 命令列表中 */
MSH_CMD_EXPORT(mycan_sample, can device sample);
4.測試結(jié)果
注意:再次使用命令啟動該示例會有以下提示:
-
CAN總線
+關(guān)注
關(guān)注
145文章
1946瀏覽量
130726 -
STM32
+關(guān)注
關(guān)注
2270文章
10895瀏覽量
355729 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1285瀏覽量
40081 -
系統(tǒng)時鐘
+關(guān)注
關(guān)注
1文章
30瀏覽量
9306 -
HAL庫
+關(guān)注
關(guān)注
1文章
121瀏覽量
6216
發(fā)布評論請先 登錄
相關(guān)推薦
評論