本帖最后由 changweilin 于 2024-3-24 23:39 编辑
HC32F4A0开发板CAN通讯测试
1概述
1.1开发板接口
该开发板有2个CAN接口,支持CAN2.0B,最高支持CAN FD,使用的接口芯片型号为:MCP2542,CAN2.0B控制器中应用程序可通过1个PTB和3 STB将发送数据送至总线,由发送调度器决定邮箱发送顺序。通过8个接收缓冲器获取总线数据。3个STB以及8个RB可以理解为一个3级FIFO和一个8级FIFO,FIFO完全由硬件控制;本次测试主要测试经典CAN的收发并将收发数据显示在屏幕上。
1.2开发板原理图
CAN芯片的接口及外围电路如图1所示。
图1 CAN接口外围电路示意图
1.3测试设备
本次测试所用设备如表1所示,开发板和CAN盒之间使用屏蔽双绞线连接,在CAN盒连接端跨接120Ω的匹配电阻防止信号反射,设备实物图连接图如图2所示:
测试设备 |
单位 |
数量 |
EV_F4A0_LQ176_REV1.0开发板 |
块 |
壹 |
ARM仿真器 |
个 |
壹 |
5V电源适配器 |
个 |
壹 |
ZLG USBCANFD-200U |
个 |
壹 |
ALIENTEK 4.3’TFTLCD |
块 |
壹 |
RIGOL DHO804示波器 |
台 |
壹 |
表1 测试设备
图2 开发板实物连接图
2代码编写
产生发送数据
static void LoadData()
{
uint8_t i;
for (i = 0U; i < CAN_TX_DATA_SIZE; i++) {
stcTx1.au8Data[i] = i + 0x0AU;
stcTx2.au8Data[i] = i + 0x3aU;
}
stcTx1.u32Ctrl = 0x0UL;
stcTx1.u32ID = CAN_TX_ID1;
stcTx1.IDE = CAN_TX_ID1_IDE;
stcTx1.DLC = CAN_TX_DLC;
stcTx2.u32Ctrl = 0x0UL;
stcTx2.u32ID = CAN_TX_ID2;
stcTx2.IDE = CAN_TX_ID2_IDE;
stcTx2.DLC = CAN_TX_DLC;
}
发送数据并显示
static void CanTx(uint16_t u16Width,uint16_t u16Height)
{
uint8_t i;
if (BSP_KEY_GetStatus(BSP_KEY_1) == SET) {
if (m_u8TxStart == 0U) {
m_u8TxProcess++;
if (m_u8TxProcess > CAN_TX_PROCESS_STB) {
m_u8TxProcess = CAN_TX_PROCESS_PTB;
}
switch (m_u8TxProcess) {
case CAN_TX_PROCESS_PTB:
/* Transmit one frame via PTB */
(void)CAN_FillTxFrame(CAN_UNIT, CAN_TX_BUF_PTB, &stcTx1);
CAN_StartTx(CAN_UNIT, CAN_TX_REQ_PTB);
//lcd_show_xnum(140,20,m_astRxFrame[0].u32ID,4,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(120,100,stcTx1.au8Data[0],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(150,100,stcTx1.au8Data[1],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(180,100,stcTx1.au8Data[2],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(210,100,stcTx1.au8Data[3],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(240,100,stcTx1.au8Data[4],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(270,100,stcTx1.au8Data[5],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(300,100,stcTx1.au8Data[6],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(330,100,stcTx1.au8Data[7],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
break;
case CAN_TX_PROCESS_STB:
/* Transmit one frame via STB */
(void)CAN_FillTxFrame(CAN_UNIT, CAN_TX_BUF_STB, &stcTx2);
CAN_StartTx(CAN_UNIT, CAN_TX_REQ_STB_ONE);
lcd_show_xnum(120,100,stcTx2.au8Data[0],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(150,100,stcTx2.au8Data[1],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(180,100,stcTx2.au8Data[2],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(210,100,stcTx2.au8Data[3],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(240,100,stcTx2.au8Data[4],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(270,100,stcTx2.au8Data[5],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(300,100,stcTx2.au8Data[6],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(330,100,stcTx2.au8Data[7],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
break;
}
m_u32TxTick = CAN_TX_TIMEOUT_MS;
m_u8TxStart = 1U;
} else {
}
}
}
接收数据并显示
static void CanRx(uint16_t u16Width,uint16_t u16Height)
{
uint8_t i;
uint8_t j;
uint8_t u8RxFrameNum = 0U;
int32_t i32Ret;
/* Get all received frames. */
do {
i32Ret = CAN_GetRxFrame(CAN_UNIT, &m_astRxFrame[u8RxFrameNum]);
if (i32Ret == LL_OK) {
u8RxFrameNum++;
}
} while (i32Ret == LL_OK);
lcd_show_xnum(140,20,m_astRxFrame[0].u32ID,4,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(120,60,m_astRxFrame[0].au8Data[0],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(150,60,m_astRxFrame[0].au8Data[1],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(180,60,m_astRxFrame[0].au8Data[2],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(210,60,m_astRxFrame[0].au8Data[3],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(240,60,m_astRxFrame[0].au8Data[4],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(270,60,m_astRxFrame[0].au8Data[5],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(300,60,m_astRxFrame[0].au8Data[6],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_xnum(330,60,m_astRxFrame[0].au8Data[7],2,24,0,LCD_COLOR_BLACK,u16Width,u16Height);
/* Handle received frames. */
for (i = 0U; i < u8RxFrameNum; i++) {
for (j = 0; j < (uint8_t)m_astRxFrame[i].DLC; j++) {
m_astRxFrame[i].au8Data[j] = 2U;
}
}
}
过滤器设置
#define CAN_FILTER1_ID (0x101UL)
#define CAN_FILTER1_ID_MASK (0x0UL)
#define CAN_FILTER1_ID_TYPE (CAN_ID_STD)
主函数
int32_t main(void)
{
uint16_t u16Width;
uint16_t u16Height;
/* MCU Peripheral registers write unprotected */
LL_PERIPH_WE(LL_PERIPH_ALL);
/* Initialize system clock: */
BSP_CLK_Init();
CLK_SetClockDiv(CLK_BUS_EXCLK, CLK_EXCLK_DIV8);
BSP_IO_Init();
//BSP_LED_Init();
BSP_LCD_IO_Init();
BSP_KEY_Init();
BSP_LCD_RSTCmd(EIO_PIN_RESET); /* RST# to low */
DDL_DelayMS(50UL);
BSP_LCD_RSTCmd(EIO_PIN_SET); /* RST# to high */
DDL_DelayMS(50UL);
BSP_NT35510_Init();
BSP_NT35510_Clear(LCD_COLOR_WHITE);
BSP_LCD_BKLCmd(EIO_PIN_SET);
/* Set LCD cursor */
BSP_NT35510_SetCursor(0U, 0U);
/* Turn on LCD backlight */
BSP_LCD_BKLCmd(EIO_PIN_SET);
CanCommClockConfig();
CanPinConfig();
CanInitConfig();
CanIrqConfig();
CanPhyEnable();
(void)SysTick_Init(1000U);
/* Clear LCD screen */
/* MCU Peripheral registers write protected */
LL_PERIPH_WP(LL_PERIPH_ALL);
u16Width = BSP_NT35510_GetPixelWidth();
u16Height = BSP_NT35510_GetPixelHeight();
LoadData();
lcd_show_string(20,20,u16Width,u16Height,24,"CAN_RX_ID:",LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_string(20,60,u16Width,u16Height,24,"RX_DATA:",LCD_COLOR_BLACK,u16Width,u16Height);
lcd_show_string(20,100,u16Width,u16Height,24,"TX_DATA:",LCD_COLOR_BLACK,u16Width,u16Height);
for (;;) {
if (m_u8RxFlag != 0U) {
/* Read frames here or in CAN_IrqCallback */
CanRx(u16Width,u16Height);
m_u8RxFlag = 0U;
}
CanTx(u16Width,u16Height);
}
}
3实验现象
3.1实验现象分析
本实验通过按键来触发CAN数据的发送,每次按下按键会以不同的方式发送不同的数据,发送的数据会在LCD显示屏上实时更新,同时使用ZLG CANpro显示接收到的数据,并且给开发板发送数据,开发板会将收到的数据和CANID显示在显示屏上。
3.2CAN发送
首次按下按键K1发送的数据如图3所示,CAN盒接收到的数据如图4所示,再次按下按键K1,发送的数据如图5所示,CAN盒接收到的数据如图6所示。使用示波器抓取发送的数据如图7、8所示;实验现象和编写代码的预期一致。
图3 第一次按下按键数据显示
图4 第一次按下按键CAN盒接收数据显示
图5 第二次按下按键数据显示
图6 第二次按下按键CAN盒接收数据显示
图7 第一次发送波形
图8 第二次发送波形
3.3CAN接收
使用CANPRO软件发送数据,设置如图9所示,LCD显示屏会将接收到的CANID和CAN数据显示在屏幕上,如图10所示,程序中设置了过滤器仅能接接收ID为101的数据,因此当修改CANID为102时显示屏上的ID并不更新,证明过滤器正常工作。
图9 CAN发送设置
图10 开发板接收到的CAN数据
图11 修改ID和数据后设置
图12 数据发送成功
如图11、12所示修改CANID和数据后发送成功,但显示屏未更新数据和ID,证明过滤器正常工作。
4实验过程
can盒发送过程:
can发送
can盒接收过程
can接收
5总结
开发板CAN接口的相关例程十分详细,进行一定修改后配合前期的LCD相关函数即可进行使用,能够满足接口快速开发的需求。