[活动] 【极海APM32F407IG Tiny Board开发板测评】8.CAN通讯实验

[复制链接]
1784|12
 楼主| yuyy1989 发表于 2023-7-13 09:29 | 显示全部楼层 |阅读模式
#申请原创# @21小跑堂  

8.CAN通讯实验

CAN 是控制器局域网络 Controller Area Network 的缩写,是德国BOSCH(博世)公司研发的一种串行通讯协议总线,它可以使用双绞线来传输信号,是世界上应用最广泛的现场总线之一。CAN协议主要用于汽车中各种不同元件之间的通信,以此取代昂贵而笨重的配电线束,该协议的健壮性使其同样适用于自动化和工业环境中。
APM32F407IG拥有2个CAN,支持 CAN 协议 2.0A 和 2.0B,例程中有个CAN的例程就是用这两个CAN互相发送接收数据,不过代码是针对MINI Board写的,修改一下让它适配TINY Board
先修改一下工程宏定义把MINI改成TINY
QQ截图20230712134553.png
然后将main.c中的APM_MINI全部替换为APM_TINY
查看一下readme文件
QQ截图20230712141452.png
先尝试直接连接PB8与PB13 PB9与PB12,测试结果失败,调换rx与tx的接法也还是失败,看来必须要用CAN模块才行
QQ截图20230712135147.png
搞了2个TJA1050的CAN模块
微信图片_20230712142116.jpg
按照上面readme里那个示意图进行连接,再次测试OK了
QQ截图20230712141022.png
接下来尝试在自己的工程里实现一下,按下按键1 CAN1发送消息CAN2接收消息后打印出来,按下按键2 CAN2发送消息CAN1接收消息后打印出来
代码示例,CAN的相关初始化代码这里就不列举了,参考例程的就行
  1. uint8_t can1_rec_flag = 0;
  2. uint8_t can2_rec_flag = 0;
  3. CAN_RxMessage_T can1rxmsg;
  4. CAN_RxMessage_T can2rxmsg;
  5. void can_senddatas(uint8_t can)
  6. {
  7.     CAN_TxMessage_T TxMessage;
  8.     uint8_t x = 0;
  9.     TxMessage.extID          = 0x1234567;
  10.     TxMessage.typeID         = CAN_TYPEID_EXT;
  11.     if(can == 2)
  12.     {
  13.         TxMessage.stdID          = 0x123;
  14.         TxMessage.typeID         = CAN_TYPEID_STD;
  15.         x = 0x80;
  16.     }
  17.     TxMessage.remoteTxReq    = CAN_RTXR_DATA;
  18.     TxMessage.dataLengthCode = 8;
  19.     TxMessage.data[0]        = 0x01|x;
  20.     TxMessage.data[1]        = 0x02|x;
  21.     TxMessage.data[2]        = 0x03|x;
  22.     TxMessage.data[3]        = 0x04|x;
  23.     TxMessage.data[4]        = 0x05|x;
  24.     TxMessage.data[5]        = 0x06|x;
  25.     TxMessage.data[6]        = 0x07|x;
  26.     TxMessage.data[7]        = 0x08|x;
  27.     if(can == 1)
  28.         CAN_TxMessage(CAN1, &TxMessage);
  29.     else if(can == 2)
  30.         CAN_TxMessage(CAN2, &TxMessage);
  31. }

  32. void can_print_rxmessage(CAN_RxMessage_T *msg)
  33. {
  34.     uint8_t i = 0;
  35.     printf("stdid: %08X\r\n",msg->stdID);
  36.     printf("extid: %08X\r\n",msg->extID);
  37.     printf("datalen: %d\r\n",msg->dataLengthCode);
  38.     printf("data: ");
  39.     while(i<msg->dataLengthCode)
  40.     {
  41.         printf("%02X ",msg->data[i]);
  42.         i++;
  43.     }
  44.     printf("\r\n");
  45. }
  46. int main(void)
  47. {
  48.     APM_TINY_LEDInit(LED2);
  49.     APM_TINY_LEDInit(LED3);
  50.     APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_GPIO);
  51.     APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_GPIO);
  52.     uart_init();
  53.     can_init(CAN_BAUD_500K);
  54.     CAN_EnableInterrupt(CAN1, CAN_INT_F0MP);
  55.     CAN_EnableInterrupt(CAN2, CAN_INT_F0MP);
  56.     NVIC_EnableIRQRequest(CAN1_RX0_IRQn, 0, 0);
  57.     NVIC_EnableIRQRequest(CAN2_RX0_IRQn, 0, 0);
  58.     while (1)
  59.     {
  60.         if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  61.         {
  62.             yuyy_delay_ms(30);
  63.             if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  64.             {
  65.                 while(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET);
  66.                 can_senddatas(1);
  67.             }
  68.         }
  69.         if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  70.         {
  71.             yuyy_delay_ms(30);
  72.             if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  73.             {
  74.                 while(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET);
  75.                 can_senddatas(2);
  76.             }
  77.         }
  78.         if(can1_rec_flag > 0)
  79.         {
  80.             printf("CAN1收到数据\r\n");
  81.             can_print_rxmessage(&can1rxmsg);
  82.             can1_rec_flag = 0;
  83.             APM_TINY_LEDToggle(LED2);
  84.         }
  85.         if(can2_rec_flag > 0)
  86.         {
  87.             printf("CAN2收到数据\r\n");
  88.             can_print_rxmessage(&can2rxmsg);
  89.             can2_rec_flag = 0;
  90.             APM_TINY_LEDToggle(LED3);
  91.         }
  92.     }
  93. }

  94. void CAN1_RX0_IRQHandler(void)
  95. {
  96.     CAN_RxMessage(CAN1, CAN_RX_FIFO_0, &can1rxmsg);
  97.     can1_rec_flag = 1;
  98. }


  99. void CAN2_RX0_IRQHandler(void)
  100. {
  101.     CAN_RxMessage(CAN2, CAN_RX_FIFO_0, &can2rxmsg);
  102.     can2_rec_flag = 1;
  103. }
运行结果
QQ截图20230712161410.png




caizhiwei 发表于 2023-7-13 15:26 | 显示全部楼层
joengchao 发表于 2023-7-20 09:38 | 显示全部楼层
tpgf 发表于 2023-8-8 10:43 | 显示全部楼层
开始的时候可以使用回环模式进行测试吗
qcliu 发表于 2023-8-8 10:52 | 显示全部楼层
can通讯有握手的机制吗?万一数据丢失怎么办
drer 发表于 2023-8-8 11:42 | 显示全部楼层
can通讯数据的接收是只能通过中断来实现的吗
coshi 发表于 2023-8-8 11:57 | 显示全部楼层
can通讯方式需要对数据进行校验吗
 楼主| yuyy1989 发表于 2023-8-8 13:11 | 显示全部楼层
coshi 发表于 2023-8-8 11:57
can通讯方式需要对数据进行校验吗

QQ截图20230808130814.png
CAN报文已经带了CRC校验
kxsi 发表于 2023-8-8 13:20 | 显示全部楼层
楼主这里can中printf函数是向哪里打印输出数据啊
 楼主| yuyy1989 发表于 2023-8-8 13:26 | 显示全部楼层
kxsi 发表于 2023-8-8 13:20
楼主这里can中printf函数是向哪里打印输出数据啊

printf重定向到了串口
wiba 发表于 2023-8-8 14:43 | 显示全部楼层
这个测试使用的是外挂的can模块而不是单片机自己的外设是吗
 楼主| yuyy1989 发表于 2023-8-8 14:54 | 显示全部楼层
wiba 发表于 2023-8-8 14:43
这个测试使用的是外挂的can模块而不是单片机自己的外设是吗

需要can收发模块转换,直接IO连线不行
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

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