[活动专区] 【杰发科技AC7840x测评】+ CAN收发测试

[复制链接]
5708|0
 楼主| tlled 发表于 2023-12-26 23:47 | 显示全部楼层 |阅读模式
测试下开发板的CAN收发功能。

一、硬件部分

1.1、CAN收发器电路
001.jpg

1.2、CAN接口
CAN接口连接到PE4和PE5端口
002.jpg

1.3、芯片端口映射
PE4和PE5映射到CAN0
003.jpg

二、程序部分

2.1、can.c
  1. #include "ac7840x.h"
  2. #include "gpio_drv.h"
  3. #include "can_drv.h"
  4. #include "can/can.h"
  5. #include "osif.h"
  6. #include "clock_config.h"

  7. /* ============================================  Define  ============================================ */
  8. #define CAN_SOURCE_CLOCK             (60UL)         /* 时钟源选择60M */
  9. #define CAN_MSG_HANDLE_DIRECT        (1UL)          /* 是否处理消息, 1 是, 0 否 */
  10. #define CAN_TIME_STAMP_ENABLE        (0UL)          /* 使能/失能CAN时间戳, 1 使能, 0 失能 */

  11. /* ===========================================  Typedef  ============================================ */
  12. typedef struct
  13. {
  14.     uint32_t recvCount;                              /* 接收消息计数 */
  15.     uint32_t sendCount;                              /* 发送消息计数*/
  16. } can_cur_node_t;

  17. /* ==========================================  Variables  =========================================== */
  18. /*  
  19. *  波特率和采样点计算公式:
  20. *  tSeg1 = (S_SEG_1 + 2); tSeg2 = (S_SEG_2 + 1).
  21. *  BandRate = (SRC_CLK / (S_PRESC + 1) / ((S_SEG_1 + 2) + (S_SEG_2 + 1))), SRC_CLK 为CAN模块时钟源
  22. *  SamplePoint = (tSeg1 / (tSeg1 + tSeg2)).
  23. */
  24. #if (CAN_SOURCE_CLOCK == 80UL)  /*时钟源为80M*/
  25. static const can_time_segment_t s_canBitrate[CAN_BITRATE_NUM] =
  26. {
  27.     {0x1C, 0x09, 0x09, 0x01},  /*   1M, 75% */
  28.     {0x26, 0x09, 0x09, 0x01},  /* 800K, 80% */
  29.     {0x1C, 0x09, 0x09, 0x03},  /* 500K, 75% */
  30.     {0x1C, 0x09, 0x09, 0x07},  /* 250K, 75% */
  31.     {0x1C, 0x09, 0x09, 0x0F},  /* 125K, 75% */
  32.     {0x1C, 0x09, 0x09, 0x13},  /* 100K, 75% */
  33.     {0x1C, 0x09, 0x09, 0x27},  /*  50K, 75% */
  34. };

  35. #elif (CAN_SOURCE_CLOCK == 60UL) /*时钟源为60M*/
  36. static const can_time_segment_t s_canBitrate[CAN_BITRATE_NUM] =
  37. {
  38.     {0x0D, 0x04, 0x04, 0x02},  /*   1M, 75% */
  39.     {0x12, 0x04, 0x04, 0x02},  /* 800K, 80% */
  40.     {0x1C, 0x09, 0x09, 0x02},  /* 500K, 75% */
  41.     {0x1C, 0x09, 0x09, 0x05},  /* 250K, 75% */
  42.     {0x1C, 0x09, 0x09, 0x0B},  /* 125K, 75% */
  43.     {0x1C, 0x09, 0x09, 0x0E},  /* 100K, 75% */
  44.     {0x1C, 0x09, 0x09, 0x1D},  /*  50K, 75% */
  45. };

  46. #elif (CAN_SOURCE_CLOCK == 48UL) /* 时钟源为48M*/
  47. static const can_time_segment_t s_canBitrate[CAN_BITRATE_NUM] =
  48. {
  49.     {0x22, 0x0B, 0x0B, 0x00},  /*   1M, 75% */
  50.     {0x16, 0x05, 0x05, 0x01},  /* 800K, 80% */
  51.     {0x22, 0x0B, 0x0B, 0x01},  /* 500K, 75%*/
  52.     {0x22, 0x0B, 0x0B, 0x03},  /* 250K, 75% */
  53.     {0x22, 0x0B, 0x0B, 0x07},  /* 125K, 75% */
  54.     {0x22, 0x0B, 0x0B, 0x09},  /* 100K, 75% */
  55.     {0x22, 0x0B, 0x0B, 0x13},  /*  50K, 75% */
  56. };

  57. #elif (CAN_SOURCE_CLOCK == 24UL) /* 时钟源为24M*/
  58. static const can_time_segment_t s_canBitrate[CAN_BITRATE_NUM] =
  59. {
  60.     {0x10, 0x05, 0x05, 0x00},  /*   1M, 75% */
  61.     {0x16, 0x05, 0x05, 0x00},  /* 800K, 80% */
  62.     {0x10, 0x05, 0x05, 0x01},  /* 500K, 75% */
  63.     {0x10, 0x05, 0x05, 0x03},  /* 250K, 75% */
  64.     {0x10, 0x05, 0x05, 0x07},  /* 125K, 75% */
  65.     {0x10, 0x05, 0x05, 0x09},  /* 100K, 75% */
  66.     {0x10, 0x05, 0x05, 0x13},  /*  50K, 75% */
  67. };

  68. #elif (CAN_SOURCE_CLOCK == 8UL) /*时钟源为8M*/
  69. static const can_time_segment_t s_canBitrate[CAN_BITRATE_NUM] =
  70. {
  71.     {0x04, 0x01, 0x01, 0x00},  /*   1M,75% */
  72.     {0x06, 0x01, 0x01, 0x00},  /* 800K, 80% */
  73.     {0x0A, 0x03, 0x03, 0x00},  /* 500K,75% */
  74.     {0x0A, 0x03, 0x03, 0x01},  /* 250K,75% */
  75.     {0x0A, 0x03, 0x03, 0x03},  /* 125K,75% */
  76.     {0x0D, 0x04, 0x03, 0x03},  /* 100K,75% */
  77.     {0x0D, 0x04, 0x03, 0x07},  /*  50K,75% */
  78. };
  79. #endif

  80. static const can_filter_config_t s_canFilterList[16] =  /* 过滤器配置*/
  81. {
  82.     {0x00000001, 0x00000000, CAN_MSG_ID_BOTH},         /* 只接收ID 0x0000_0001和0x001的数据 */
  83.     {0x00000002, 0x00000000, CAN_MSG_ID_STD},          /* 只接收ID 0x002的标准帧数据 */
  84.     {0x00000013, 0x00000000, CAN_MSG_ID_EXT},          /* 只接收ID 0x0000_0013的扩展帧数据 */
  85.     {0x00000124, 0x00000000, CAN_MSG_ID_BOTH},         /* 只接收ID 0x0000_0124和0x124的数据 */
  86.     {0x00000050, 0x1FFFFF0F, CAN_MSG_ID_BOTH},         /* 可接收ID 0xXXXX_XX5X 或 0xX5X的数据,X为任意值 */
  87.     {0x00000060, 0x1FFFFF0F, CAN_MSG_ID_BOTH},         /* 可接收ID 0xXXXX_XX6X 或 0xX6X的数据,X为任意值 */
  88.     {0x00000007, 0x1FFFFFF0, CAN_MSG_ID_BOTH},         /* 可接收ID 0xXXXX_XXX7 或 0xXX7的数据,X为任意值 */
  89.     {0x00000008, 0x1FFFFFF0, CAN_MSG_ID_BOTH},         /* 可接收ID 0xXXXX_XXX8 或 0xXX8的数据,X为任意值 */

  90.     {0x00000009, 0x1FFFFFF0, CAN_MSG_ID_STD},          /* 可接收ID 0xXX9的标准帧数据,X为任意值 */
  91.     {0x0000000a, 0x1FFFFFF0, CAN_MSG_ID_EXT},          /* 可接收ID 0xXXXX_XXXa的扩展帧数据,X为任意值 */
  92.     {0x00000700, 0x1FFFF0FF, CAN_MSG_ID_BOTH},         /* 可接收ID 0xXXXX_X7XX 或 0x7XX的数据,X为任意值 */
  93.     {0x0000c000, 0x1FFF0FFF, CAN_MSG_ID_EXT},          /* 可接收ID 0xXXXX_CXXX 的扩展帧数据,X为任意值 */
  94.     {0x000d0000, 0x1FF0FFFF, CAN_MSG_ID_EXT},          /* 可接收ID 0xXXXX_DXXX 的扩展帧数据,X为任意值 */
  95.     {0x00e00000, 0x1F0FFFFF, CAN_MSG_ID_EXT},          /* 可接收ID 0xXXEX_XXXX 的扩展帧数据,X为任意值 */
  96.     {0x0f000000, 0x10FFFFFF, CAN_MSG_ID_EXT},          /* 可接收ID 0xXXXX_XXXX 的扩展帧数据,X为任意值 */
  97.     {0x10000000, 0x0FFFFFFF, CAN_MSG_ID_EXT},          /* 可接收ID 0xXXXX_XXXX 的扩展帧数据,X为任意值 */
  98. };

  99. static can_cur_node_t s_canCurNode[CAN_INSTANCE_MAX] = {0}; /* 接收信息*/

  100. /*!
  101. * [url=home.php?mod=space&uid=247401]@brief[/url] GPIO 初始化
  102. *
  103. * @param[in] instance: CAN 模块通道
  104. * [url=home.php?mod=space&uid=266161]@return[/url] none
  105. */
  106. void CAN_InitGPIO(uint8_t instance)
  107. {
  108.     if (0U == instance)
  109.     {
  110.         GPIO_DRV_SetMuxModeSel(PORTE, 4U, PORT_MUX_ALT5);           /* CAN0_RX */
  111.         GPIO_DRV_SetMuxModeSel(PORTE, 5U, PORT_MUX_ALT5);           /* CAN0_TX */
  112.         GPIO_DRV_SetMuxModeSel(PORTE, 10U, PORT_MUX_ALT5);          /* 配置收发器standby功能*/
  113.     }
  114.     else if (1U == instance)
  115.     {
  116.         GPIO_DRV_SetMuxModeSel(PORTC, 6U, PORT_MUX_ALT3);           /* CAN1_RX */
  117.         GPIO_DRV_SetMuxModeSel(PORTC, 7U, PORT_MUX_ALT3);           /* CAN1_TX */
  118.         GPIO_DRV_SetMuxModeSel(PORTE, 6U, PORT_MUX_ALT5);           /* 配置收发器standby功能*/
  119.     }
  120.     else if (2U == instance)
  121.     {
  122.         GPIO_DRV_SetMuxModeSel(PORTC, 16U, PORT_MUX_ALT3);          /* CAN2_RX */
  123.         GPIO_DRV_SetMuxModeSel(PORTC, 17U, PORT_MUX_ALT3);          /* CAN2_TX */
  124.         GPIO_DRV_SetMuxModeSel(PORTC, 15U, PORT_MUX_ALT5);          /* 配置收发器standby功能 */
  125.     }
  126.     else if (3U == instance)
  127.     {
  128.         GPIO_DRV_SetMuxModeSel(PORTC, 12U, PORT_MUX_ALT5);          /* CAN3_RX */
  129.         GPIO_DRV_SetMuxModeSel(PORTC, 13U, PORT_MUX_ALT5);          /* CAN3_TX */
  130.         GPIO_DRV_SetMuxModeSel(PORTC, 11U, PORT_MUX_ALT5);          /* 配置收发器standby功能 */
  131.     }
  132. }

  133. /*!
  134. * @brief CAN_GetNormalBitrate 获取波特率
  135. *
  136. * @param[in] index: 波特率索引
  137. * @return 波特率配置
  138. */
  139. static can_time_segment_t CAN_GetNormalBitrate(can_bitrate_t index)
  140. {
  141.     can_time_segment_t bitrate = {0};

  142.     if (index < CAN_BITRATE_NUM)
  143.     {
  144.         bitrate = s_canBitrate[index];
  145.     }

  146.     return bitrate;
  147. }

  148. /*!
  149. * @brief CAN_HandleMsg 接收数据处理
  150. *
  151. * @param[in] instance: CAN 模块通道
  152. * @param[in] msgInfo: 接收数据
  153. * @return none
  154. */
  155. static void CAN_HandleMsg(uint8_t instance, const can_msg_info_t *msgInfo)
  156. {
  157.     uint8_t i = 0;

  158.     s_canCurNode[instance].recvCount++;             /* 节点信息更新 */
  159. #if CAN_MSG_HANDLE_DIRECT                           /* 处理数据*/
  160.     if (msgInfo->IDE)
  161.     {
  162.         printf("CAN[%d] RecvCount:%06d ID:%08x DLC:%d", instance, s_canCurNode[instance].recvCount, msgInfo->ID, msgInfo->DLC);
  163.     }
  164.     else
  165.     {
  166.         printf("CAN[%d] RecvCount:%06d  ID:%03x DLC:%d", instance, s_canCurNode[instance].recvCount, msgInfo->ID, msgInfo->DLC);
  167.     }
  168.     if ((0 == msgInfo->RTR) && msgInfo->DLC)
  169.     {
  170.         printf("\r\tData: ");
  171.         for (i = 0; (i < msgInfo->DLC) && (i < 8); i++)
  172.         {
  173.             printf(" %02x", msgInfo->DATA[i]);
  174.         }
  175.     }
  176.     printf("\r\n");
  177. #endif
  178. }

  179. /*!
  180. * @brief CAN_EventCallback 中断回调函数, 可通过CAN_IRQHandler了解参数具体含义
  181. *
  182. * @param[in] instance: CAN 模块通道
  183. * @param[in] event: 中断事件
  184. * @param[in] koer: 错误类型
  185. * @return 0: none
  186. */
  187. void CAN_EventCallback(uint8_t instance, uint32_t event, uint32_t koer)
  188. {
  189.     can_msg_info_t recvMsg = {0};
  190.     uint8_t recvData[8] = {0};

  191.     if (event & (uint32_t)CAN_EVENT_BUS_ERROR)         /* 发生错误后,打印错误消息,仅用于调试 */
  192.     {
  193.         printf("CAN[%d]e: EVEN: %x  KOER: %x\r\n", instance, event, koer);
  194.     }

  195.     if (event & (uint32_t)CAN_EVENT_RECEIVE_DONE)      /* 接收数据*/
  196.     {
  197.         while (CAN_DRV_GetRbufStatus(instance))
  198.         {
  199.             recvMsg.DATA = recvData;                   /* 为接收数据索引中的数据域分配空间, 如果未给接收数据索引的数据域分配空间,直操作会触发Haltfault */
  200.             if (!CAN_DRV_Receive(instance, &recvMsg))
  201.             {
  202.                 CAN_HandleMsg(instance, &recvMsg);
  203.             }
  204.         }
  205.     }
  206. }



  207. void init_can(void)
  208. {
  209.         uint8_t instance = 0U;
  210.         can_user_config_t canCfg = {0};
  211.         can_bitrate_t bitrateIndex = CAN_BITRATE_500K;                 /* 低速波特率设置 */
  212.         can_transmit_buff_t type = CAN_TRANSMIT_SECONDARY;             /* 发送缓存设置 */

  213.         canCfg.filterNum = 0U;                                         /* 过滤器数量 */
  214.         canCfg.canMode = CAN_NORMAL_MODE;                              /* 正常模式 */
  215.         canCfg.interruptEn = true;                                     /* 使能中断*/
  216.         canCfg.tsMode = CAN_TSMODE_FIFO;                               /* 选择FIFO模式*/
  217.         canCfg.tsAmount = CAN_TRANSMIT_SEC_ALL;                        /* TSALL*/
  218.         canCfg.tpss = false;                                           /* 失能PTB单次发送 */
  219.         canCfg.tsss = false;                                           /* 失能STB单次发送 */
  220.         canCfg.rom = CAN_ROM_OVER_WRITE;                               /* 缓冲区溢出后,新数据会覆盖旧数据*/
  221.         canCfg.errorWarningLimit = 0x0BU;                              /* 错误警告限制,当 TECNT|RECTN 超过这个限制,会触发EIF错误中断 */
  222. #if CAN_TIME_STAMP_ENABLE
  223.         canCfg.timeStampEn = true;                                     /* 时间戳使能 */
  224.         canCfg.timeStampClkSrc = CAN_TIME_STAMP_CLK_SRC_EXT;           /* 时间戳时钟源选择 */
  225.         canCfg.timeStampClkDiv = CAN_TIME_STAMP_CLK_DIV_8;             /* 时间戳时钟源分频 */
  226.         canCfg.timeStampPos = CAN_TIME_STAMP_SOF;                      /* 时间区采样位置选择 */
  227. #endif
  228.         canCfg.dmaRecvEn = false;                                      /* 不使用DMA */
  229.         canCfg.memEccEn = false;                                       /* 失能ECC */
  230.         canCfg.wakeupIntEn = false;                                    /* 失能唤醒功能 */
  231.         canCfg.busOffRecDisable = false;                               /* 失能自动总线关闭恢复, busoff产生后, 会遵循ISO 11898-规范 */
  232.         canCfg.interruptMask = CAN_IRQ_ALL_ENABLE_MSK;                 /* 使能所有中断*/
  233.         canCfg.bitrate = CAN_GetNormalBitrate(bitrateIndex);           /* 低速波特率配置*/
  234.         canCfg.filterList = (can_filter_config_t *)s_canFilterList;    /* 过滤器配置*/
  235.         canCfg.callback = (can_callback_t)CAN_EventCallback;
  236.         CAN_InitGPIO(instance);                                        /* CAN模块IO口初始化 */
  237.         CAN_DRV_Init(instance, &canCfg);                                                  /* CAN模块初始化 */
  238.        
  239. }

  240. void can_senddat(uint8_t *dat)
  241. {
  242.     int32_t ret = 1;
  243.     static can_msg_info_t s_sendMsg = {0};
  244.     static uint8_t sendData[8] = {0};

  245.     if (!CAN_DRV_IsTransmitBusy(0, CAN_TRANSMIT_SECONDARY))
  246.     {
  247.         s_sendMsg.ID = 0x220;                        /* CAN ID*/
  248.         s_sendMsg.IDE = 0;                           /* 标准帧*/
  249.         s_sendMsg.RTR = 0;                           /* 非远程帧*/
  250.         s_sendMsg.DLC = 8;                           /* 数据长度*/
  251.         s_sendMsg.DATA = sendData;                   /* 分配空间*/
  252.         s_sendMsg.DATA[0] = dat[0];                    /* 填充数据*/
  253.         s_sendMsg.DATA[1] = dat[1];
  254.         s_sendMsg.DATA[2] = dat[2];
  255.         s_sendMsg.DATA[3] = dat[3];
  256.         s_sendMsg.DATA[4] = dat[4];
  257.         s_sendMsg.DATA[5] = dat[5];
  258.         s_sendMsg.DATA[6] = dat[6];
  259.         s_sendMsg.DATA[7] = dat[7];
  260.         if (STATUS_SUCCESS == CAN_DRV_Send(0, &s_sendMsg, CAN_TRANSMIT_SECONDARY))
  261.         {
  262.             s_canCurNode[0].sendCount++;      /* 节点信息更新 */
  263.             ret = 0;
  264.         }
  265.     }

  266.     return ret;
  267. }






2.2、main.c
  1. #include "ac7840x.h"
  2. #include "clock_config.h"
  3. #include "debugout_ac7840x.h"
  4. #include "osif.h"
  5. #include "led/led.h"
  6. #include "key/key.h"
  7. #include "adc/adc.h"
  8. #include "spi/spi.h"
  9. #include "ch376s.h"
  10. #include "can/can.h"

  11. uint8_t can_txbuf[8];

  12. void SystemClock_Config(void)
  13. {
  14.     CKGEN_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,
  15.                    g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
  16.     CKGEN_DRV_UpdateConfiguration(0, CLOCK_MANAGER_POLICY_AGREEMENT);
  17. }

  18. int main(void)
  19. {
  20.         uint8_t i=0;
  21.         SystemClock_Config();
  22.         init_led();
  23.         init_key();
  24.         init_adc();
  25.         InitDebug();
  26.         init_can();

  27.         while (1)
  28.         {
  29.                 i++;
  30.                 can_txbuf[0]=i;
  31.                 can_senddat(can_txbuf);
  32.                 led3_on();
  33.                 OSIF_TimeDelay(100);
  34.                 led3_off();
  35.                 OSIF_TimeDelay(100);
  36.                 //ADC_TriggerTest();
  37.         }
  38. }


三、运行结果

3.1、CAN接收测试
打开CAN调试卡,收到开发板发送的数据
004.jpg

3.2、CAN接收测试
串口打印CAN接收到的数据
005.jpg
您需要登录后才可以回帖 登录 | 注册

本版积分规则

132

主题

701

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部